aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2015-06-09 13:35:46 -0400
committerMark Brown <broonie@kernel.org>2015-06-09 13:35:46 -0400
commit6724af486903df57338c14424e02599e371cf563 (patch)
tree0e42ae32bbfe7e93ba9db11a1124aeb4378cbd71 /tools
parentd2233325e5b7891914901867ca5355347d59df14 (diff)
parent9deef024a12ebae4965c89837f662905ac88944b (diff)
Merge branch 'fix/fsl-dspi' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi into spi-fsl-dspi
Diffstat (limited to 'tools')
-rw-r--r--tools/build/Build.include81
-rw-r--r--tools/build/Documentation/Build.txt139
-rw-r--r--tools/build/Makefile.build130
-rw-r--r--tools/build/Makefile.feature171
-rw-r--r--tools/build/feature/.gitignore (renamed from tools/perf/config/feature-checks/.gitignore)1
-rw-r--r--tools/build/feature/Makefile (renamed from tools/perf/config/feature-checks/Makefile)31
-rw-r--r--tools/build/feature/test-all.c (renamed from tools/perf/config/feature-checks/test-all.c)19
-rw-r--r--tools/build/feature/test-backtrace.c (renamed from tools/perf/config/feature-checks/test-backtrace.c)0
-rw-r--r--tools/build/feature/test-bionic.c (renamed from tools/perf/config/feature-checks/test-bionic.c)0
-rw-r--r--tools/build/feature/test-compile.c (renamed from tools/perf/config/feature-checks/test-compile.c)0
-rw-r--r--tools/build/feature/test-cplus-demangle.c (renamed from tools/perf/config/feature-checks/test-cplus-demangle.c)0
-rw-r--r--tools/build/feature/test-dwarf.c (renamed from tools/perf/config/feature-checks/test-dwarf.c)0
-rw-r--r--tools/build/feature/test-fortify-source.c (renamed from tools/perf/config/feature-checks/test-fortify-source.c)0
-rw-r--r--tools/build/feature/test-glibc.c (renamed from tools/perf/config/feature-checks/test-glibc.c)0
-rw-r--r--tools/build/feature/test-gtk2-infobar.c (renamed from tools/perf/config/feature-checks/test-gtk2-infobar.c)0
-rw-r--r--tools/build/feature/test-gtk2.c (renamed from tools/perf/config/feature-checks/test-gtk2.c)0
-rw-r--r--tools/build/feature/test-hello.c (renamed from tools/perf/config/feature-checks/test-hello.c)0
-rw-r--r--tools/build/feature/test-libaudit.c (renamed from tools/perf/config/feature-checks/test-libaudit.c)0
-rw-r--r--tools/build/feature/test-libbabeltrace.c9
-rw-r--r--tools/build/feature/test-libbfd.c (renamed from tools/perf/config/feature-checks/test-libbfd.c)0
-rw-r--r--tools/build/feature/test-libdw-dwarf-unwind.c (renamed from tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c)0
-rw-r--r--tools/build/feature/test-libelf-getphdrnum.c (renamed from tools/perf/config/feature-checks/test-libelf-getphdrnum.c)0
-rw-r--r--tools/build/feature/test-libelf-mmap.c (renamed from tools/perf/config/feature-checks/test-libelf-mmap.c)0
-rw-r--r--tools/build/feature/test-libelf.c (renamed from tools/perf/config/feature-checks/test-libelf.c)0
-rw-r--r--tools/build/feature/test-libnuma.c (renamed from tools/perf/config/feature-checks/test-libnuma.c)0
-rw-r--r--tools/build/feature/test-libperl.c (renamed from tools/perf/config/feature-checks/test-libperl.c)0
-rw-r--r--tools/build/feature/test-libpython-version.c (renamed from tools/perf/config/feature-checks/test-libpython-version.c)0
-rw-r--r--tools/build/feature/test-libpython.c (renamed from tools/perf/config/feature-checks/test-libpython.c)0
-rw-r--r--tools/build/feature/test-libslang.c (renamed from tools/perf/config/feature-checks/test-libslang.c)0
-rw-r--r--tools/build/feature/test-libunwind-debug-frame.c (renamed from tools/perf/config/feature-checks/test-libunwind-debug-frame.c)0
-rw-r--r--tools/build/feature/test-libunwind.c (renamed from tools/perf/config/feature-checks/test-libunwind.c)0
-rw-r--r--tools/build/feature/test-lzma.c10
-rw-r--r--tools/build/feature/test-pthread-attr-setaffinity-np.c (renamed from tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c)7
-rw-r--r--tools/build/feature/test-stackprotector-all.c (renamed from tools/perf/config/feature-checks/test-stackprotector-all.c)0
-rw-r--r--tools/build/feature/test-sync-compare-and-swap.c (renamed from tools/perf/config/feature-checks/test-sync-compare-and-swap.c)0
-rw-r--r--tools/build/feature/test-timerfd.c (renamed from tools/perf/config/feature-checks/test-timerfd.c)0
-rw-r--r--tools/build/feature/test-zlib.c (renamed from tools/perf/config/feature-checks/test-zlib.c)0
-rw-r--r--tools/build/tests/ex/Build8
-rw-r--r--tools/build/tests/ex/Makefile23
-rw-r--r--tools/build/tests/ex/a.c5
-rw-r--r--tools/build/tests/ex/arch/Build2
-rw-r--r--tools/build/tests/ex/arch/e.c5
-rw-r--r--tools/build/tests/ex/arch/f.c5
-rw-r--r--tools/build/tests/ex/b.c5
-rw-r--r--tools/build/tests/ex/c.c5
-rw-r--r--tools/build/tests/ex/d.c5
-rw-r--r--tools/build/tests/ex/empty/Build0
-rw-r--r--tools/build/tests/ex/ex.c19
-rwxr-xr-xtools/build/tests/run.sh42
-rw-r--r--tools/hv/Makefile2
-rw-r--r--tools/hv/hv_vss_daemon.c10
-rw-r--r--tools/iio/Makefile16
-rw-r--r--tools/iio/generic_buffer.c359
-rw-r--r--tools/iio/iio_event_monitor.c308
-rw-r--r--tools/iio/iio_utils.c669
-rw-r--r--tools/iio/iio_utils.h71
-rw-r--r--tools/iio/lsiio.c158
-rw-r--r--tools/lib/api/Build2
-rw-r--r--tools/lib/api/Makefile58
-rw-r--r--tools/lib/api/fd/Build1
-rw-r--r--tools/lib/api/fs/Build4
-rw-r--r--tools/lib/api/fs/debugfs.c69
-rw-r--r--tools/lib/api/fs/debugfs.h13
-rw-r--r--tools/lib/api/fs/findfs.c63
-rw-r--r--tools/lib/api/fs/findfs.h23
-rw-r--r--tools/lib/api/fs/tracefs.c78
-rw-r--r--tools/lib/api/fs/tracefs.h21
-rw-r--r--tools/lib/lockdep/Build1
-rw-r--r--tools/lib/lockdep/Makefile132
-rw-r--r--tools/lib/traceevent/Build17
-rw-r--r--tools/lib/traceevent/Makefile169
-rw-r--r--tools/lib/traceevent/event-parse.c307
-rw-r--r--tools/lib/traceevent/event-parse.h24
-rw-r--r--tools/lib/traceevent/event-plugin.c60
-rw-r--r--tools/lib/traceevent/kbuffer-parse.c12
-rw-r--r--tools/lib/traceevent/kbuffer.h1
-rw-r--r--tools/lib/traceevent/parse-filter.c2
-rw-r--r--tools/lib/traceevent/trace-seq.c13
-rw-r--r--tools/net/bpf_exp.l6
-rw-r--r--tools/net/bpf_exp.y23
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Build44
-rw-r--r--tools/perf/Documentation/Build.txt49
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt24
-rw-r--r--tools/perf/Documentation/perf-data.txt40
-rw-r--r--tools/perf/Documentation/perf-diff.txt8
-rw-r--r--tools/perf/Documentation/perf-kmem.txt12
-rw-r--r--tools/perf/Documentation/perf-list.txt7
-rw-r--r--tools/perf/Documentation/perf-probe.txt16
-rw-r--r--tools/perf/Documentation/perf-record.txt30
-rw-r--r--tools/perf/Documentation/perf-report.txt5
-rw-r--r--tools/perf/Documentation/perf-script.txt6
-rw-r--r--tools/perf/Documentation/perf-trace.txt6
-rw-r--r--tools/perf/Documentation/perf.txt7
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/Makefile.perf622
-rw-r--r--tools/perf/arch/Build2
-rw-r--r--tools/perf/arch/arm/Build2
-rw-r--r--tools/perf/arch/arm/Makefile11
-rw-r--r--tools/perf/arch/arm/tests/Build2
-rw-r--r--tools/perf/arch/arm/util/Build4
-rw-r--r--tools/perf/arch/arm64/Build1
-rw-r--r--tools/perf/arch/arm64/Makefile4
-rw-r--r--tools/perf/arch/arm64/util/Build2
-rw-r--r--tools/perf/arch/powerpc/Build1
-rw-r--r--tools/perf/arch/powerpc/Makefile3
-rw-r--r--tools/perf/arch/powerpc/util/Build4
-rw-r--r--tools/perf/arch/s390/Build1
-rw-r--r--tools/perf/arch/s390/Makefile3
-rw-r--r--tools/perf/arch/s390/util/Build4
-rw-r--r--tools/perf/arch/sh/Build1
-rw-r--r--tools/perf/arch/sh/Makefile1
-rw-r--r--tools/perf/arch/sh/util/Build1
-rw-r--r--tools/perf/arch/sparc/Build1
-rw-r--r--tools/perf/arch/sparc/Makefile1
-rw-r--r--tools/perf/arch/sparc/util/Build1
-rw-r--r--tools/perf/arch/x86/Build2
-rw-r--r--tools/perf/arch/x86/Makefile15
-rw-r--r--tools/perf/arch/x86/tests/Build2
-rw-r--r--tools/perf/arch/x86/util/Build8
-rw-r--r--tools/perf/bench/Build11
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm-def.h6
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S2
-rw-r--r--tools/perf/bench/mem-memcpy.c132
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm-def.h6
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm.S2
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-buildid-cache.c107
-rw-r--r--tools/perf/builtin-buildid-list.c2
-rw-r--r--tools/perf/builtin-data.c123
-rw-r--r--tools/perf/builtin-diff.c6
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-help.c17
-rw-r--r--tools/perf/builtin-inject.c16
-rw-r--r--tools/perf/builtin-kmem.c538
-rw-r--r--tools/perf/builtin-kvm.c15
-rw-r--r--tools/perf/builtin-list.c28
-rw-r--r--tools/perf/builtin-lock.c7
-rw-r--r--tools/perf/builtin-mem.c7
-rw-r--r--tools/perf/builtin-probe.c19
-rw-r--r--tools/perf/builtin-record.c108
-rw-r--r--tools/perf/builtin-report.c16
-rw-r--r--tools/perf/builtin-sched.c101
-rw-r--r--tools/perf/builtin-script.c34
-rw-r--r--tools/perf/builtin-stat.c98
-rw-r--r--tools/perf/builtin-timechart.c12
-rw-r--r--tools/perf/builtin-top.c10
-rw-r--r--tools/perf/builtin-trace.c281
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/command-list.txt1
-rw-r--r--tools/perf/config/Makefile293
-rw-r--r--tools/perf/config/Makefile.arch25
-rw-r--r--tools/perf/config/utilities.mak3
-rw-r--r--tools/perf/perf-completion.sh94
-rw-r--r--tools/perf/perf.c29
-rw-r--r--tools/perf/perf.h5
-rw-r--r--tools/perf/scripts/Build2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Build3
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Build3
-rw-r--r--tools/perf/tests/Build43
-rw-r--r--tools/perf/tests/attr/base-record2
-rw-r--r--tools/perf/tests/attr/base-stat2
-rw-r--r--tools/perf/tests/builtin-test.c9
-rw-r--r--tools/perf/tests/dso-data.c22
-rw-r--r--tools/perf/tests/kmod-path.c73
-rw-r--r--tools/perf/tests/make2
-rw-r--r--tools/perf/tests/open-syscall-all-cpus.c7
-rw-r--r--tools/perf/tests/open-syscall.c7
-rw-r--r--tools/perf/tests/parse-events.c53
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/ui/Build14
-rw-r--r--tools/perf/ui/browsers/Build10
-rw-r--r--tools/perf/ui/browsers/annotate.c8
-rw-r--r--tools/perf/ui/browsers/hists.c88
-rw-r--r--tools/perf/ui/gtk/Build9
-rw-r--r--tools/perf/ui/tui/Build4
-rw-r--r--tools/perf/util/Build145
-rw-r--r--tools/perf/util/annotate.c34
-rw-r--r--tools/perf/util/build-id.c209
-rw-r--r--tools/perf/util/build-id.h8
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c8
-rw-r--r--tools/perf/util/callchain.h1
-rw-r--r--tools/perf/util/cloexec.c24
-rw-r--r--tools/perf/util/cloexec.h6
-rw-r--r--tools/perf/util/data-convert-bt.c857
-rw-r--r--tools/perf/util/data-convert-bt.h8
-rw-r--r--tools/perf/util/db-export.c4
-rw-r--r--tools/perf/util/db-export.h3
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debug.h1
-rw-r--r--tools/perf/util/dso.c159
-rw-r--r--tools/perf/util/dso.h49
-rw-r--r--tools/perf/util/dwarf-aux.c29
-rw-r--r--tools/perf/util/dwarf-aux.h3
-rw-r--r--tools/perf/util/event.c190
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evlist.c49
-rw-r--r--tools/perf/util/evlist.h16
-rw-r--r--tools/perf/util/evsel.c354
-rw-r--r--tools/perf/util/evsel.h11
-rw-r--r--tools/perf/util/header.c35
-rw-r--r--tools/perf/util/hist.c11
-rw-r--r--tools/perf/util/hist.h11
-rw-r--r--tools/perf/util/include/asm/alternative-asm.h1
-rw-r--r--tools/perf/util/kvm-stat.h1
-rw-r--r--tools/perf/util/lzma.c95
-rw-r--r--tools/perf/util/machine.c332
-rw-r--r--tools/perf/util/machine.h2
-rw-r--r--tools/perf/util/map.c20
-rw-r--r--tools/perf/util/map.h6
-rw-r--r--tools/perf/util/ordered-events.c65
-rw-r--r--tools/perf/util/ordered-events.h19
-rw-r--r--tools/perf/util/parse-events.c242
-rw-r--r--tools/perf/util/parse-events.h13
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/parse-options.c32
-rw-r--r--tools/perf/util/parse-options.h2
-rw-r--r--tools/perf/util/probe-event.c425
-rw-r--r--tools/perf/util/probe-event.h6
-rw-r--r--tools/perf/util/probe-finder.c100
-rw-r--r--tools/perf/util/probe-finder.h4
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/scripting-engines/Build6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c10
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c21
-rw-r--r--tools/perf/util/session.c320
-rw-r--r--tools/perf/util/session.h18
-rw-r--r--tools/perf/util/setup.py2
-rw-r--r--tools/perf/util/sort.c9
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/symbol-elf.c92
-rw-r--r--tools/perf/util/symbol-minimal.c7
-rw-r--r--tools/perf/util/symbol.c65
-rw-r--r--tools/perf/util/symbol.h8
-rw-r--r--tools/perf/util/target.c7
-rw-r--r--tools/perf/util/thread.c15
-rw-r--r--tools/perf/util/thread.h24
-rw-r--r--tools/perf/util/tool.h8
-rw-r--r--tools/perf/util/trace-event-parse.c12
-rw-r--r--tools/perf/util/trace-event-scripting.c1
-rw-r--r--tools/perf/util/trace-event.h6
-rw-r--r--tools/perf/util/unwind-libunwind.c8
-rw-r--r--tools/perf/util/util.c67
-rw-r--r--tools/perf/util/util.h6
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixmap.c2
-rw-r--r--tools/power/cpupower/Makefile2
-rw-r--r--tools/power/cpupower/utils/helpers/pci.c11
-rw-r--r--tools/power/x86/turbostat/Makefile6
-rw-r--r--tools/power/x86/turbostat/turbostat.8138
-rw-r--r--tools/power/x86/turbostat/turbostat.c436
-rw-r--r--tools/testing/selftests/Makefile42
-rw-r--r--tools/testing/selftests/breakpoints/Makefile5
-rw-r--r--tools/testing/selftests/cpu-hotplug/Makefile7
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh (renamed from tools/testing/selftests/cpu-hotplug/on-off-test.sh)0
-rw-r--r--tools/testing/selftests/efivarfs/Makefile7
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/efivarfs/efivarfs.sh0
-rw-r--r--tools/testing/selftests/exec/Makefile9
-rw-r--r--tools/testing/selftests/exec/execveat.c10
-rw-r--r--tools/testing/selftests/firmware/Makefile20
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/firmware/fw_filesystem.sh0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/firmware/fw_userhelper.sh0
-rw-r--r--tools/testing/selftests/ftrace/Makefile5
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/basic4.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/event-enable.tc15
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc15
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc15
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc6
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc2
-rwxr-xr-xtools/testing/selftests/gen_kselftest_tar.sh55
-rw-r--r--tools/testing/selftests/ipc/Makefile11
-rw-r--r--tools/testing/selftests/kcmp/Makefile6
-rwxr-xr-xtools/testing/selftests/kselftest_install.sh37
-rw-r--r--tools/testing/selftests/lib.mk35
-rw-r--r--tools/testing/selftests/memfd/Makefile14
-rw-r--r--tools/testing/selftests/memory-hotplug/Makefile9
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/memory-hotplug/mem-on-off-test.sh (renamed from tools/testing/selftests/memory-hotplug/on-off-test.sh)0
-rw-r--r--tools/testing/selftests/mount/.gitignore1
-rw-r--r--tools/testing/selftests/mount/Makefile15
-rw-r--r--tools/testing/selftests/mqueue/Makefile22
-rw-r--r--tools/testing/selftests/net/Makefile10
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/net/run_afpackettests0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/net/run_netsocktests0
-rw-r--r--tools/testing/selftests/powerpc/Makefile32
-rw-r--r--tools/testing/selftests/powerpc/copyloops/Makefile16
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h33
-rw-r--r--tools/testing/selftests/powerpc/harness.c47
-rw-r--r--tools/testing/selftests/powerpc/mm/Makefile15
-rw-r--r--tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c8
-rw-r--r--tools/testing/selftests/powerpc/pmu/Makefile48
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/Makefile13
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.c47
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.h1
-rw-r--r--tools/testing/selftests/powerpc/primitives/Makefile15
-rw-r--r--tools/testing/selftests/powerpc/stringloops/Makefile15
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/.gitignore2
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/Makefile24
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/check.S100
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/common.h6
-rw-r--r--tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S81
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile18
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-syscall-asm.S27
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-syscall.c121
-rw-r--r--tools/testing/selftests/powerpc/utils.h3
-rw-r--r--tools/testing/selftests/powerpc/vphn/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/vphn/Makefile15
-rw-r--r--tools/testing/selftests/powerpc/vphn/test-vphn.c410
l---------tools/testing/selftests/powerpc/vphn/vphn.c1
l---------tools/testing/selftests/powerpc/vphn/vphn.h1
-rw-r--r--tools/testing/selftests/ptrace/Makefile5
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFcommon1
-rw-r--r--tools/testing/selftests/size/Makefile7
-rw-r--r--tools/testing/selftests/sysctl/Makefile12
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/sysctl/run_numerictests0
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/sysctl/run_stringtests0
-rw-r--r--tools/testing/selftests/timers/Makefile38
-rw-r--r--tools/testing/selftests/timers/alarmtimer-suspend.c185
-rw-r--r--tools/testing/selftests/timers/change_skew.c107
-rw-r--r--tools/testing/selftests/timers/clocksource-switch.c179
-rw-r--r--tools/testing/selftests/timers/inconsistency-check.c204
-rw-r--r--tools/testing/selftests/timers/leap-a-day.c319
-rw-r--r--tools/testing/selftests/timers/leapcrash.c120
-rw-r--r--tools/testing/selftests/timers/mqueue-lat.c124
-rw-r--r--tools/testing/selftests/timers/nanosleep.c174
-rw-r--r--tools/testing/selftests/timers/nsleep-lat.c190
-rw-r--r--tools/testing/selftests/timers/posix_timers.c9
-rw-r--r--tools/testing/selftests/timers/raw_skew.c154
-rw-r--r--tools/testing/selftests/timers/rtctest.c271
-rw-r--r--tools/testing/selftests/timers/set-2038.c144
-rw-r--r--tools/testing/selftests/timers/set-tai.c79
-rw-r--r--tools/testing/selftests/timers/set-timer-lat.c216
-rw-r--r--tools/testing/selftests/timers/skew_consistency.c89
-rw-r--r--tools/testing/selftests/timers/threadtest.c204
-rw-r--r--tools/testing/selftests/timers/valid-adjtimex.c202
-rw-r--r--tools/testing/selftests/user/Makefile5
-rw-r--r--tools/testing/selftests/vm/Makefile7
-rw-r--r--tools/testing/selftests/vm/hugetlbfstest.c4
-rw-r--r--tools/testing/selftests/vm/map_hugetlb.c6
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/vm/run_vmtests0
-rw-r--r--tools/testing/selftests/x86/.gitignore2
-rw-r--r--tools/testing/selftests/x86/Makefile48
-rw-r--r--tools/testing/selftests/x86/run_x86_tests.sh13
-rw-r--r--tools/testing/selftests/x86/sigreturn.c684
-rw-r--r--tools/testing/selftests/x86/single_step_syscall.c181
-rw-r--r--tools/testing/selftests/x86/trivial_32bit_program.c14
-rw-r--r--tools/thermal/tmon/.gitignore1
-rw-r--r--tools/thermal/tmon/Makefile15
-rw-r--r--tools/thermal/tmon/tmon.82
-rw-r--r--tools/thermal/tmon/tmon.c14
-rw-r--r--tools/thermal/tmon/tui.c45
355 files changed, 14279 insertions, 3077 deletions
diff --git a/tools/build/Build.include b/tools/build/Build.include
new file mode 100644
index 000000000000..4c8daaccb82a
--- /dev/null
+++ b/tools/build/Build.include
@@ -0,0 +1,81 @@
1###
2# build: Generic definitions
3#
4# Lots of this code have been borrowed or heavily inspired from parts
5# of kbuild code, which is not credited, but mostly developed by:
6#
7# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
8# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
9#
10
11###
12# Convenient variables
13comma := ,
14squote := '
15
16###
17# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
18dot-target = $(dir $@).$(notdir $@)
19
20###
21# filename of target with directory and extension stripped
22basetarget = $(basename $(notdir $@))
23
24###
25# The temporary file to save gcc -MD generated dependencies must not
26# contain a comma
27depfile = $(subst $(comma),_,$(dot-target).d)
28
29###
30# Check if both arguments has same arguments. Result is empty string if equal.
31arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
32 $(filter-out $(cmd_$@), $(cmd_$(1))) )
33
34###
35# Escape single quote for use in echo statements
36escsq = $(subst $(squote),'\$(squote)',$1)
37
38# Echo command
39# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
40echo-cmd = $(if $($(quiet)cmd_$(1)),\
41 echo ' $(call escsq,$($(quiet)cmd_$(1)))';)
42
43###
44# Replace >$< with >$$< to preserve $ when reloading the .cmd file
45# (needed for make)
46# Replace >#< with >\#< to avoid starting a comment in the .cmd file
47# (needed for make)
48# Replace >'< with >'\''< to be able to enclose the whole string in '...'
49# (needed for the shell)
50make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1)))))
51
52###
53# Find any prerequisites that is newer than target or that does not exist.
54# PHONY targets skipped in both cases.
55any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
56
57###
58# if_changed_dep - execute command if any prerequisite is newer than
59# target, or command line has changed and update
60# dependencies in the cmd file
61if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \
62 @set -e; \
63 $(echo-cmd) $(cmd_$(1)); \
64 cat $(depfile) > $(dot-target).cmd; \
65 printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
66
67# if_changed - execute command if any prerequisite is newer than
68# target, or command line has changed
69if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
70 @set -e; \
71 $(echo-cmd) $(cmd_$(1)); \
72 printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
73
74###
75# C flags to be used in rule definitions, includes:
76# - depfile generation
77# - global $(CFLAGS)
78# - per target C flags
79# - per object C flags
80# - BUILD_STR macro to allow '-D"$(variable)"' constructs
81c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
new file mode 100644
index 000000000000..00ad2d608727
--- /dev/null
+++ b/tools/build/Documentation/Build.txt
@@ -0,0 +1,139 @@
1Build Framework
2===============
3
4The perf build framework was adopted from the kernel build system, hence the
5idea and the way how objects are built is the same.
6
7Basically the user provides set of 'Build' files that list objects and
8directories to nest for specific target to be build.
9
10Unlike the kernel we don't have a single build object 'obj-y' list that where
11we setup source objects, but we support more. This allows one 'Build' file to
12carry a sources list for multiple build objects.
13
14a) Build framework makefiles
15----------------------------
16
17The build framework consists of 2 Makefiles:
18
19 Build.include
20 Makefile.build
21
22While the 'Build.include' file contains just some generic definitions, the
23'Makefile.build' file is the makefile used from the outside. It's
24interface/usage is following:
25
26 $ make -f tools/build/Makefile srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT)
27
28where:
29
30 KSRC - is the path to kernel sources
31 DIR - is the path to the project to be built
32 OBJECT - is the name of the build object
33
34When succefully finished the $(DIR) directory contains the final object file
35called $(OBJECT)-in.o:
36
37 $ ls $(DIR)/$(OBJECT)-in.o
38
39which includes all compiled sources described in 'Build' makefiles.
40
41a) Build makefiles
42------------------
43
44The user supplies 'Build' makefiles that contains a objects list, and connects
45the build to nested directories.
46
47Assume we have the following project structure:
48
49 ex/a.c
50 /b.c
51 /c.c
52 /d.c
53 /arch/e.c
54 /arch/f.c
55
56Out of which you build the 'ex' binary ' and the 'libex.a' library:
57
58 'ex' - consists of 'a.o', 'b.o' and libex.a
59 'libex.a' - consists of 'c.o', 'd.o', 'e.o' and 'f.o'
60
61The build framework does not create the 'ex' and 'libex.a' binaries for you, it
62only prepares proper objects to be compiled and grouped together.
63
64To follow the above example, the user provides following 'Build' files:
65
66 ex/Build:
67 ex-y += a.o
68 ex-y += b.o
69
70 libex-y += c.o
71 libex-y += d.o
72 libex-y += arch/
73
74 ex/arch/Build:
75 libex-y += e.o
76 libex-y += f.o
77
78and runs:
79
80 $ make -f tools/build/Makefile.build dir=. obj=ex
81 $ make -f tools/build/Makefile.build dir=. obj=libex
82
83which creates the following objects:
84
85 ex/ex-in.o
86 ex/libex-in.o
87
88that contain request objects names in Build files.
89
90It's only a matter of 2 single commands to create the final binaries:
91
92 $ ar rcs libex.a libex-in.o
93 $ gcc -o ex ex-in.o libex.a
94
95You can check the 'ex' example in 'tools/build/tests/ex' for more details.
96
97b) Rules
98--------
99
100The build framework provides standard compilation rules to handle .S and .c
101compilation.
102
103It's possible to include special rule if needed (like we do for flex or bison
104code generation).
105
106c) CFLAGS
107---------
108
109It's possible to alter the standard object C flags in the following way:
110
111 CFLAGS_perf.o += '...' - alters CFLAGS for perf.o object
112 CFLAGS_gtk += '...' - alters CFLAGS for gtk build object
113
114This C flags changes has the scope of the Build makefile they are defined in.
115
116
117d) Dependencies
118---------------
119
120For each built object file 'a.o' the '.a.cmd' is created and holds:
121
122 - Command line used to built that object
123 (for each object)
124
125 - Dependency rules generated by 'gcc -Wp,-MD,...'
126 (for compiled object)
127
128All existing '.cmd' files are included in the Build process to follow properly
129the dependencies and trigger a rebuild when necessary.
130
131
132e) Single rules
133---------------
134
135It's possible to build single object file by choice, like:
136
137 $ make util/map.o # objects
138 $ make util/map.i # preprocessor
139 $ make util/map.s # assembly
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
new file mode 100644
index 000000000000..10df57237a66
--- /dev/null
+++ b/tools/build/Makefile.build
@@ -0,0 +1,130 @@
1###
2# Main build makefile.
3#
4# Lots of this code have been borrowed or heavily inspired from parts
5# of kbuild code, which is not credited, but mostly developed by:
6#
7# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
8# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
9#
10
11PHONY := __build
12__build:
13
14ifeq ($(V),1)
15 quiet =
16 Q =
17else
18 quiet=quiet_
19 Q=@
20endif
21
22build-dir := $(srctree)/tools/build
23
24# Generic definitions
25include $(build-dir)/Build.include
26
27# do not force detected configuration
28-include .config-detected
29
30# Init all relevant variables used in build files so
31# 1) they have correct type
32# 2) they do not inherit any value from the environment
33subdir-y :=
34obj-y :=
35subdir-y :=
36subdir-obj-y :=
37
38# Build definitions
39build-file := $(dir)/Build
40include $(build-file)
41
42quiet_cmd_flex = FLEX $@
43quiet_cmd_bison = BISON $@
44
45# Create directory unless it exists
46quiet_cmd_mkdir = MKDIR $(dir $@)
47 cmd_mkdir = mkdir -p $(dir $@)
48 rule_mkdir = $(if $(wildcard $(dir $@)),,@$(call echo-cmd,mkdir) $(cmd_mkdir))
49
50# Compile command
51quiet_cmd_cc_o_c = CC $@
52 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
53
54quiet_cmd_cc_i_c = CPP $@
55 cmd_cc_i_c = $(CC) $(c_flags) -E -o $@ $<
56
57quiet_cmd_cc_s_c = AS $@
58 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
59
60# Link agregate command
61# If there's nothing to link, create empty $@ object.
62quiet_cmd_ld_multi = LD $@
63 cmd_ld_multi = $(if $(strip $(obj-y)),\
64 $(LD) -r -o $@ $(obj-y),rm -f $@; $(AR) rcs $@)
65
66# Build rules
67$(OUTPUT)%.o: %.c FORCE
68 $(call rule_mkdir)
69 $(call if_changed_dep,cc_o_c)
70
71$(OUTPUT)%.o: %.S FORCE
72 $(call rule_mkdir)
73 $(call if_changed_dep,cc_o_c)
74
75$(OUTPUT)%.i: %.c FORCE
76 $(call rule_mkdir)
77 $(call if_changed_dep,cc_i_c)
78
79$(OUTPUT)%.i: %.S FORCE
80 $(call rule_mkdir)
81 $(call if_changed_dep,cc_i_c)
82
83$(OUTPUT)%.s: %.c FORCE
84 $(call rule_mkdir)
85 $(call if_changed_dep,cc_s_c)
86
87# Gather build data:
88# obj-y - list of build objects
89# subdir-y - list of directories to nest
90# subdir-obj-y - list of directories objects 'dir/$(obj)-in.o'
91obj-y := $($(obj)-y)
92subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
93obj-y := $(patsubst %/, %/$(obj)-in.o, $(obj-y))
94subdir-obj-y := $(filter %/$(obj)-in.o, $(obj-y))
95
96# '$(OUTPUT)/dir' prefix to all objects
97prefix := $(subst ./,,$(OUTPUT)$(dir)/)
98obj-y := $(addprefix $(prefix),$(obj-y))
99subdir-obj-y := $(addprefix $(prefix),$(subdir-obj-y))
100
101# Final '$(obj)-in.o' object
102in-target := $(prefix)$(obj)-in.o
103
104PHONY += $(subdir-y)
105
106$(subdir-y):
107 $(Q)$(MAKE) -f $(build-dir)/Makefile.build dir=$(dir)/$@ obj=$(obj)
108
109$(sort $(subdir-obj-y)): $(subdir-y) ;
110
111$(in-target): $(obj-y) FORCE
112 $(call rule_mkdir)
113 $(call if_changed,ld_multi)
114
115__build: $(in-target)
116 @:
117
118PHONY += FORCE
119FORCE:
120
121# Include all cmd files to get all the dependency rules
122# for all objects included
123targets := $(wildcard $(sort $(obj-y) $(in-target) $(MAKECMDGOALS)))
124cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
125
126ifneq ($(cmd_files),)
127 include $(cmd_files)
128endif
129
130.PHONY: $(PHONY)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
new file mode 100644
index 000000000000..3a0b0ca2a28c
--- /dev/null
+++ b/tools/build/Makefile.feature
@@ -0,0 +1,171 @@
1feature_dir := $(srctree)/tools/build/feature
2
3ifneq ($(OUTPUT),)
4 OUTPUT_FEATURES = $(OUTPUT)feature/
5 $(shell mkdir -p $(OUTPUT_FEATURES))
6endif
7
8feature_check = $(eval $(feature_check_code))
9define feature_check_code
10 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
11endef
12
13feature_set = $(eval $(feature_set_code))
14define feature_set_code
15 feature-$(1) := 1
16endef
17
18#
19# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
20#
21
22#
23# Note that this is not a complete list of all feature tests, just
24# those that are typically built on a fully configured system.
25#
26# [ Feature tests not mentioned here have to be built explicitly in
27# the rule that uses them - an example for that is the 'bionic'
28# feature check. ]
29#
30FEATURE_TESTS = \
31 backtrace \
32 dwarf \
33 fortify-source \
34 sync-compare-and-swap \
35 glibc \
36 gtk2 \
37 gtk2-infobar \
38 libaudit \
39 libbfd \
40 libelf \
41 libelf-getphdrnum \
42 libelf-mmap \
43 libnuma \
44 libperl \
45 libpython \
46 libpython-version \
47 libslang \
48 libunwind \
49 pthread-attr-setaffinity-np \
50 stackprotector-all \
51 timerfd \
52 libdw-dwarf-unwind \
53 zlib \
54 lzma
55
56FEATURE_DISPLAY = \
57 dwarf \
58 glibc \
59 gtk2 \
60 libaudit \
61 libbfd \
62 libelf \
63 libnuma \
64 libperl \
65 libpython \
66 libslang \
67 libunwind \
68 libdw-dwarf-unwind \
69 zlib \
70 lzma
71
72# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
73# If in the future we need per-feature checks/flags for features not
74# mentioned in this list we need to refactor this ;-).
75set_test_all_flags = $(eval $(set_test_all_flags_code))
76define set_test_all_flags_code
77 FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1))
78 FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
79endef
80
81$(foreach feat,$(FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
82
83#
84# Special fast-path for the 'all features are available' case:
85#
86$(call feature_check,all,$(MSG))
87
88#
89# Just in case the build freshly failed, make sure we print the
90# feature matrix:
91#
92ifeq ($(feature-all), 1)
93 #
94 # test-all.c passed - just set all the core feature flags to 1:
95 #
96 $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat)))
97else
98 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C $(feature_dir) $(addsuffix .bin,$(FEATURE_TESTS)) >/dev/null 2>&1)
99 $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))
100endif
101
102#
103# Print the result of the feature test:
104#
105feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
106
107define feature_print_status_code
108 ifeq ($(feature-$(1)), 1)
109 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
110 else
111 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
112 endif
113endef
114
115feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
116define feature_print_text_code
117 MSG = $(shell printf '...%30s: %s' $(1) $(2))
118endef
119
120FEATURE_DUMP := $(foreach feat,$(FEATURE_DISPLAY),feature-$(feat)($(feature-$(feat))))
121FEATURE_DUMP_FILE := $(shell touch $(OUTPUT)FEATURE-DUMP; cat $(OUTPUT)FEATURE-DUMP)
122
123ifeq ($(dwarf-post-unwind),1)
124 FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text))
125endif
126
127# The $(feature_display) controls the default detection message
128# output. It's set if:
129# - detected features differes from stored features from
130# last build (in FEATURE-DUMP file)
131# - one of the $(FEATURE_DISPLAY) is not detected
132# - VF is enabled
133
134ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)")
135 $(shell echo "$(FEATURE_DUMP)" > $(OUTPUT)FEATURE-DUMP)
136 feature_display := 1
137endif
138
139feature_display_check = $(eval $(feature_check_code))
140define feature_display_check_code
141 ifneq ($(feature-$(1)), 1)
142 feature_display := 1
143 endif
144endef
145
146$(foreach feat,$(FEATURE_DISPLAY),$(call feature_display_check,$(feat)))
147
148ifeq ($(VF),1)
149 feature_display := 1
150 feature_verbose := 1
151endif
152
153ifeq ($(feature_display),1)
154 $(info )
155 $(info Auto-detecting system features:)
156 $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),))
157
158 ifeq ($(dwarf-post-unwind),1)
159 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
160 endif
161
162 ifneq ($(feature_verbose),1)
163 $(info )
164 endif
165endif
166
167ifeq ($(feature_verbose),1)
168 TMP := $(filter-out $(FEATURE_DISPLAY),$(FEATURE_TESTS))
169 $(foreach feat,$(TMP),$(call feature_print_status,$(feat),))
170 $(info )
171endif
diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/build/feature/.gitignore
index 80f3da0c3515..09b335b98842 100644
--- a/tools/perf/config/feature-checks/.gitignore
+++ b/tools/build/feature/.gitignore
@@ -1,2 +1,3 @@
1*.d 1*.d
2*.bin 2*.bin
3*.output
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/build/feature/Makefile
index 42ac05aaf8ac..463ed8f2a267 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/build/feature/Makefile
@@ -29,33 +29,36 @@ FILES= \
29 test-stackprotector-all.bin \ 29 test-stackprotector-all.bin \
30 test-timerfd.bin \ 30 test-timerfd.bin \
31 test-libdw-dwarf-unwind.bin \ 31 test-libdw-dwarf-unwind.bin \
32 test-libbabeltrace.bin \
32 test-compile-32.bin \ 33 test-compile-32.bin \
33 test-compile-x32.bin \ 34 test-compile-x32.bin \
34 test-zlib.bin 35 test-zlib.bin \
36 test-lzma.bin
35 37
36CC := $(CROSS_COMPILE)gcc -MD 38CC := $(CROSS_COMPILE)gcc -MD
37PKG_CONFIG := $(CROSS_COMPILE)pkg-config 39PKG_CONFIG := $(CROSS_COMPILE)pkg-config
38 40
39all: $(FILES) 41all: $(FILES)
40 42
41BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) 43__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
44 BUILD = $(__BUILD) > $(OUTPUT)$(@:.bin=.make.output) 2>&1
42 45
43############################### 46###############################
44 47
45test-all.bin: 48test-all.bin:
46 $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz 49 $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma
47 50
48test-hello.bin: 51test-hello.bin:
49 $(BUILD) 52 $(BUILD)
50 53
51test-pthread-attr-setaffinity-np.bin: 54test-pthread-attr-setaffinity-np.bin:
52 $(BUILD) -Werror -lpthread 55 $(BUILD) -D_GNU_SOURCE -lpthread
53 56
54test-stackprotector-all.bin: 57test-stackprotector-all.bin:
55 $(BUILD) -Werror -fstack-protector-all 58 $(BUILD) -fstack-protector-all
56 59
57test-fortify-source.bin: 60test-fortify-source.bin:
58 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2 61 $(BUILD) -O2 -D_FORTIFY_SOURCE=2
59 62
60test-bionic.bin: 63test-bionic.bin:
61 $(BUILD) 64 $(BUILD)
@@ -118,10 +121,10 @@ test-libbfd.bin:
118 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 121 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
119 122
120test-liberty.bin: 123test-liberty.bin:
121 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty 124 $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
122 125
123test-liberty-z.bin: 126test-liberty-z.bin:
124 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz 127 $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
125 128
126test-cplus-demangle.bin: 129test-cplus-demangle.bin:
127 $(BUILD) -liberty 130 $(BUILD) -liberty
@@ -133,10 +136,13 @@ test-timerfd.bin:
133 $(BUILD) 136 $(BUILD)
134 137
135test-libdw-dwarf-unwind.bin: 138test-libdw-dwarf-unwind.bin:
136 $(BUILD) 139 $(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind)
140
141test-libbabeltrace.bin:
142 $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
137 143
138test-sync-compare-and-swap.bin: 144test-sync-compare-and-swap.bin:
139 $(BUILD) -Werror 145 $(BUILD)
140 146
141test-compile-32.bin: 147test-compile-32.bin:
142 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c 148 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
@@ -147,9 +153,12 @@ test-compile-x32.bin:
147test-zlib.bin: 153test-zlib.bin:
148 $(BUILD) -lz 154 $(BUILD) -lz
149 155
156test-lzma.bin:
157 $(BUILD) -llzma
158
150-include *.d 159-include *.d
151 160
152############################### 161###############################
153 162
154clean: 163clean:
155 rm -f $(FILES) *.d 164 rm -f $(FILES) *.d $(FILES:.bin=.make.output)
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/build/feature/test-all.c
index 6d4d09323922..84689a67814a 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -98,7 +98,23 @@
98#undef main 98#undef main
99 99
100#define main main_test_pthread_attr_setaffinity_np 100#define main main_test_pthread_attr_setaffinity_np
101# include "test-pthread_attr_setaffinity_np.c" 101# include "test-pthread-attr-setaffinity-np.c"
102#undef main
103
104# if 0
105/*
106 * Disable libbabeltrace check for test-all, because the requested
107 * library version is not released yet in most distributions. Will
108 * reenable later.
109 */
110
111#define main main_test_libbabeltrace
112# include "test-libbabeltrace.c"
113#undef main
114#endif
115
116#define main main_test_lzma
117# include "test-lzma.c"
102#undef main 118#undef main
103 119
104int main(int argc, char *argv[]) 120int main(int argc, char *argv[])
@@ -126,6 +142,7 @@ int main(int argc, char *argv[])
126 main_test_sync_compare_and_swap(argc, argv); 142 main_test_sync_compare_and_swap(argc, argv);
127 main_test_zlib(); 143 main_test_zlib();
128 main_test_pthread_attr_setaffinity_np(); 144 main_test_pthread_attr_setaffinity_np();
145 main_test_lzma();
129 146
130 return 0; 147 return 0;
131} 148}
diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/build/feature/test-backtrace.c
index 7124aa1dc8fb..7124aa1dc8fb 100644
--- a/tools/perf/config/feature-checks/test-backtrace.c
+++ b/tools/build/feature/test-backtrace.c
diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/build/feature/test-bionic.c
index eac24e9513eb..eac24e9513eb 100644
--- a/tools/perf/config/feature-checks/test-bionic.c
+++ b/tools/build/feature/test-bionic.c
diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/build/feature/test-compile.c
index 31dbf45bf99c..31dbf45bf99c 100644
--- a/tools/perf/config/feature-checks/test-compile.c
+++ b/tools/build/feature/test-compile.c
diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/build/feature/test-cplus-demangle.c
index 610c686e0009..610c686e0009 100644
--- a/tools/perf/config/feature-checks/test-cplus-demangle.c
+++ b/tools/build/feature/test-cplus-demangle.c
diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/build/feature/test-dwarf.c
index 3fc1801ce4a9..3fc1801ce4a9 100644
--- a/tools/perf/config/feature-checks/test-dwarf.c
+++ b/tools/build/feature/test-dwarf.c
diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/build/feature/test-fortify-source.c
index c9f398d87868..c9f398d87868 100644
--- a/tools/perf/config/feature-checks/test-fortify-source.c
+++ b/tools/build/feature/test-fortify-source.c
diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/build/feature/test-glibc.c
index b0820345cd98..b0820345cd98 100644
--- a/tools/perf/config/feature-checks/test-glibc.c
+++ b/tools/build/feature/test-glibc.c
diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/build/feature/test-gtk2-infobar.c
index 397b4646d066..397b4646d066 100644
--- a/tools/perf/config/feature-checks/test-gtk2-infobar.c
+++ b/tools/build/feature/test-gtk2-infobar.c
diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/build/feature/test-gtk2.c
index 6bd80e509439..6bd80e509439 100644
--- a/tools/perf/config/feature-checks/test-gtk2.c
+++ b/tools/build/feature/test-gtk2.c
diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/build/feature/test-hello.c
index c9f398d87868..c9f398d87868 100644
--- a/tools/perf/config/feature-checks/test-hello.c
+++ b/tools/build/feature/test-hello.c
diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/build/feature/test-libaudit.c
index afc019f08641..afc019f08641 100644
--- a/tools/perf/config/feature-checks/test-libaudit.c
+++ b/tools/build/feature/test-libaudit.c
diff --git a/tools/build/feature/test-libbabeltrace.c b/tools/build/feature/test-libbabeltrace.c
new file mode 100644
index 000000000000..9cf802a04885
--- /dev/null
+++ b/tools/build/feature/test-libbabeltrace.c
@@ -0,0 +1,9 @@
1
2#include <babeltrace/ctf-writer/writer.h>
3#include <babeltrace/ctf-ir/stream-class.h>
4
5int main(void)
6{
7 bt_ctf_stream_class_get_packet_context_type((void *) 0);
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/build/feature/test-libbfd.c
index 24059907e990..24059907e990 100644
--- a/tools/perf/config/feature-checks/test-libbfd.c
+++ b/tools/build/feature/test-libbfd.c
diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/build/feature/test-libdw-dwarf-unwind.c
index f676a3ff442a..f676a3ff442a 100644
--- a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
+++ b/tools/build/feature/test-libdw-dwarf-unwind.c
diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/build/feature/test-libelf-getphdrnum.c
index d710459306c3..d710459306c3 100644
--- a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
+++ b/tools/build/feature/test-libelf-getphdrnum.c
diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/build/feature/test-libelf-mmap.c
index 564427d7ef18..564427d7ef18 100644
--- a/tools/perf/config/feature-checks/test-libelf-mmap.c
+++ b/tools/build/feature/test-libelf-mmap.c
diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/build/feature/test-libelf.c
index 08db322d8957..08db322d8957 100644
--- a/tools/perf/config/feature-checks/test-libelf.c
+++ b/tools/build/feature/test-libelf.c
diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/build/feature/test-libnuma.c
index 4763d9cd587d..4763d9cd587d 100644
--- a/tools/perf/config/feature-checks/test-libnuma.c
+++ b/tools/build/feature/test-libnuma.c
diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/build/feature/test-libperl.c
index 8871f6a0fdb4..8871f6a0fdb4 100644
--- a/tools/perf/config/feature-checks/test-libperl.c
+++ b/tools/build/feature/test-libperl.c
diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/build/feature/test-libpython-version.c
index facea122d812..facea122d812 100644
--- a/tools/perf/config/feature-checks/test-libpython-version.c
+++ b/tools/build/feature/test-libpython-version.c
diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/build/feature/test-libpython.c
index b24b28ad6324..b24b28ad6324 100644
--- a/tools/perf/config/feature-checks/test-libpython.c
+++ b/tools/build/feature/test-libpython.c
diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/build/feature/test-libslang.c
index 22ff22ed94d1..22ff22ed94d1 100644
--- a/tools/perf/config/feature-checks/test-libslang.c
+++ b/tools/build/feature/test-libslang.c
diff --git a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c b/tools/build/feature/test-libunwind-debug-frame.c
index 0ef8087a104a..0ef8087a104a 100644
--- a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c
+++ b/tools/build/feature/test-libunwind-debug-frame.c
diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/build/feature/test-libunwind.c
index 43b9369bcab7..43b9369bcab7 100644
--- a/tools/perf/config/feature-checks/test-libunwind.c
+++ b/tools/build/feature/test-libunwind.c
diff --git a/tools/build/feature/test-lzma.c b/tools/build/feature/test-lzma.c
new file mode 100644
index 000000000000..95adc8ced3dd
--- /dev/null
+++ b/tools/build/feature/test-lzma.c
@@ -0,0 +1,10 @@
1#include <lzma.h>
2
3int main(void)
4{
5 lzma_stream strm = LZMA_STREAM_INIT;
6 int ret;
7
8 ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
9 return ret ? -1 : 0;
10}
diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/build/feature/test-pthread-attr-setaffinity-np.c
index 0a0d3ecb4e8a..fdada5e8d454 100644
--- a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
+++ b/tools/build/feature/test-pthread-attr-setaffinity-np.c
@@ -1,14 +1,17 @@
1#include <stdint.h> 1#include <stdint.h>
2#include <pthread.h> 2#include <pthread.h>
3#include <sched.h>
3 4
4int main(void) 5int main(void)
5{ 6{
6 int ret = 0; 7 int ret = 0;
7 pthread_attr_t thread_attr; 8 pthread_attr_t thread_attr;
9 cpu_set_t cs;
8 10
9 pthread_attr_init(&thread_attr); 11 pthread_attr_init(&thread_attr);
10 /* don't care abt exact args, just the API itself in libpthread */ 12 CPU_ZERO(&cs);
11 ret = pthread_attr_setaffinity_np(&thread_attr, 0, NULL); 13
14 ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs);
12 15
13 return ret; 16 return ret;
14} 17}
diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/build/feature/test-stackprotector-all.c
index c9f398d87868..c9f398d87868 100644
--- a/tools/perf/config/feature-checks/test-stackprotector-all.c
+++ b/tools/build/feature/test-stackprotector-all.c
diff --git a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c b/tools/build/feature/test-sync-compare-and-swap.c
index c34d4ca4af56..c34d4ca4af56 100644
--- a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c
+++ b/tools/build/feature/test-sync-compare-and-swap.c
diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/build/feature/test-timerfd.c
index 8c5c083b4d3c..8c5c083b4d3c 100644
--- a/tools/perf/config/feature-checks/test-timerfd.c
+++ b/tools/build/feature/test-timerfd.c
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/build/feature/test-zlib.c
index e111fff6240e..e111fff6240e 100644
--- a/tools/perf/config/feature-checks/test-zlib.c
+++ b/tools/build/feature/test-zlib.c
diff --git a/tools/build/tests/ex/Build b/tools/build/tests/ex/Build
new file mode 100644
index 000000000000..0e6c3e6767e6
--- /dev/null
+++ b/tools/build/tests/ex/Build
@@ -0,0 +1,8 @@
1ex-y += ex.o
2ex-y += a.o
3ex-y += b.o
4ex-y += empty/
5
6libex-y += c.o
7libex-y += d.o
8libex-y += arch/
diff --git a/tools/build/tests/ex/Makefile b/tools/build/tests/ex/Makefile
new file mode 100644
index 000000000000..52d2476073a3
--- /dev/null
+++ b/tools/build/tests/ex/Makefile
@@ -0,0 +1,23 @@
1export srctree := ../../../..
2export CC := gcc
3export LD := ld
4export AR := ar
5
6build := -f $(srctree)/tools/build/Makefile.build dir=. obj
7ex: ex-in.o libex-in.o
8 gcc -o $@ $^
9
10ex.%: FORCE
11 make -f $(srctree)/tools/build/Makefile.build dir=. $@
12
13ex-in.o: FORCE
14 make $(build)=ex
15
16libex-in.o: FORCE
17 make $(build)=libex
18
19clean:
20 find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
21 rm -f ex ex.i ex.s
22
23.PHONY: FORCE
diff --git a/tools/build/tests/ex/a.c b/tools/build/tests/ex/a.c
new file mode 100644
index 000000000000..851762798c83
--- /dev/null
+++ b/tools/build/tests/ex/a.c
@@ -0,0 +1,5 @@
1
2int a(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/arch/Build b/tools/build/tests/ex/arch/Build
new file mode 100644
index 000000000000..55506189efae
--- /dev/null
+++ b/tools/build/tests/ex/arch/Build
@@ -0,0 +1,2 @@
1libex-y += e.o
2libex-y += f.o
diff --git a/tools/build/tests/ex/arch/e.c b/tools/build/tests/ex/arch/e.c
new file mode 100644
index 000000000000..beaa4a1d7ba8
--- /dev/null
+++ b/tools/build/tests/ex/arch/e.c
@@ -0,0 +1,5 @@
1
2int e(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/arch/f.c b/tools/build/tests/ex/arch/f.c
new file mode 100644
index 000000000000..7c3e9e9da5b7
--- /dev/null
+++ b/tools/build/tests/ex/arch/f.c
@@ -0,0 +1,5 @@
1
2int f(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/b.c b/tools/build/tests/ex/b.c
new file mode 100644
index 000000000000..c24ff9ca9a97
--- /dev/null
+++ b/tools/build/tests/ex/b.c
@@ -0,0 +1,5 @@
1
2int b(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/c.c b/tools/build/tests/ex/c.c
new file mode 100644
index 000000000000..e216d0217499
--- /dev/null
+++ b/tools/build/tests/ex/c.c
@@ -0,0 +1,5 @@
1
2int c(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/d.c b/tools/build/tests/ex/d.c
new file mode 100644
index 000000000000..80dc0f06151b
--- /dev/null
+++ b/tools/build/tests/ex/d.c
@@ -0,0 +1,5 @@
1
2int d(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/empty/Build b/tools/build/tests/ex/empty/Build
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/build/tests/ex/empty/Build
diff --git a/tools/build/tests/ex/ex.c b/tools/build/tests/ex/ex.c
new file mode 100644
index 000000000000..dc42eb2e1a67
--- /dev/null
+++ b/tools/build/tests/ex/ex.c
@@ -0,0 +1,19 @@
1
2int a(void);
3int b(void);
4int c(void);
5int d(void);
6int e(void);
7int f(void);
8
9int main(void)
10{
11 a();
12 b();
13 c();
14 d();
15 e();
16 f();
17
18 return 0;
19}
diff --git a/tools/build/tests/run.sh b/tools/build/tests/run.sh
new file mode 100755
index 000000000000..5494f8ea7567
--- /dev/null
+++ b/tools/build/tests/run.sh
@@ -0,0 +1,42 @@
1#!/bin/sh
2
3function test_ex {
4 make -C ex V=1 clean > ex.out 2>&1
5 make -C ex V=1 >> ex.out 2>&1
6
7 if [ ! -x ./ex/ex ]; then
8 echo FAILED
9 exit -1
10 fi
11
12 make -C ex V=1 clean > /dev/null 2>&1
13 rm -f ex.out
14}
15
16function test_ex_suffix {
17 make -C ex V=1 clean > ex.out 2>&1
18
19 # use -rR to disable make's builtin rules
20 make -rR -C ex V=1 ex.o >> ex.out 2>&1
21 make -rR -C ex V=1 ex.i >> ex.out 2>&1
22 make -rR -C ex V=1 ex.s >> ex.out 2>&1
23
24 if [ -x ./ex/ex ]; then
25 echo FAILED
26 exit -1
27 fi
28
29 if [ ! -f ./ex/ex.o -o ! -f ./ex/ex.i -o ! -f ./ex/ex.s ]; then
30 echo FAILED
31 exit -1
32 fi
33
34 make -C ex V=1 clean > /dev/null 2>&1
35 rm -f ex.out
36}
37echo -n Testing..
38
39test_ex
40test_ex_suffix
41
42echo OK
diff --git a/tools/hv/Makefile b/tools/hv/Makefile
index 99ffe61051a7..a8ab79556926 100644
--- a/tools/hv/Makefile
+++ b/tools/hv/Makefile
@@ -3,7 +3,7 @@
3CC = $(CROSS_COMPILE)gcc 3CC = $(CROSS_COMPILE)gcc
4PTHREAD_LIBS = -lpthread 4PTHREAD_LIBS = -lpthread
5WARNINGS = -Wall -Wextra 5WARNINGS = -Wall -Wextra
6CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) 6CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) $(shell getconf LFS_CFLAGS)
7 7
8all: hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon 8all: hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon
9%: %.c 9%: %.c
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 5e63f70bd956..506dd0148828 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -81,6 +81,7 @@ static int vss_operate(int operation)
81 char match[] = "/dev/"; 81 char match[] = "/dev/";
82 FILE *mounts; 82 FILE *mounts;
83 struct mntent *ent; 83 struct mntent *ent;
84 char errdir[1024] = {0};
84 unsigned int cmd; 85 unsigned int cmd;
85 int error = 0, root_seen = 0, save_errno = 0; 86 int error = 0, root_seen = 0, save_errno = 0;
86 87
@@ -115,6 +116,8 @@ static int vss_operate(int operation)
115 goto err; 116 goto err;
116 } 117 }
117 118
119 endmntent(mounts);
120
118 if (root_seen) { 121 if (root_seen) {
119 error |= vss_do_freeze("/", cmd); 122 error |= vss_do_freeze("/", cmd);
120 if (error && operation == VSS_OP_FREEZE) 123 if (error && operation == VSS_OP_FREEZE)
@@ -124,16 +127,19 @@ static int vss_operate(int operation)
124 goto out; 127 goto out;
125err: 128err:
126 save_errno = errno; 129 save_errno = errno;
130 if (ent) {
131 strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1);
132 endmntent(mounts);
133 }
127 vss_operate(VSS_OP_THAW); 134 vss_operate(VSS_OP_THAW);
128 /* Call syslog after we thaw all filesystems */ 135 /* Call syslog after we thaw all filesystems */
129 if (ent) 136 if (ent)
130 syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s", 137 syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
131 ent->mnt_dir, save_errno, strerror(save_errno)); 138 errdir, save_errno, strerror(save_errno));
132 else 139 else
133 syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno, 140 syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
134 strerror(save_errno)); 141 strerror(save_errno));
135out: 142out:
136 endmntent(mounts);
137 return error; 143 return error;
138} 144}
139 145
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
new file mode 100644
index 000000000000..bf7ae6d6612a
--- /dev/null
+++ b/tools/iio/Makefile
@@ -0,0 +1,16 @@
1CC = gcc
2CFLAGS = -Wall -g -D_GNU_SOURCE
3
4all: iio_event_monitor lsiio generic_buffer
5
6iio_event_monitor: iio_event_monitor.o iio_utils.o
7
8lsiio: lsiio.o iio_utils.o
9
10generic_buffer: generic_buffer.o iio_utils.o
11
12%.o: %.c iio_utils.h
13
14.PHONY: clean
15clean:
16 rm -f *.o iio_event_monitor lsiio generic_buffer
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c
new file mode 100644
index 000000000000..f805493be3eb
--- /dev/null
+++ b/tools/iio/generic_buffer.c
@@ -0,0 +1,359 @@
1/* Industrialio buffer test code.
2 *
3 * Copyright (c) 2008 Jonathan Cameron
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is primarily intended as an example application.
10 * Reads the current buffer setup from sysfs and starts a short capture
11 * from the specified device, pretty printing the result after appropriate
12 * conversion.
13 *
14 * Command line parameters
15 * generic_buffer -n <device_name> -t <trigger_name>
16 * If trigger name is not specified the program assumes you want a dataready
17 * trigger associated with the device and goes looking for it.
18 *
19 */
20
21#include <unistd.h>
22#include <stdlib.h>
23#include <dirent.h>
24#include <fcntl.h>
25#include <stdio.h>
26#include <errno.h>
27#include <sys/stat.h>
28#include <sys/dir.h>
29#include <linux/types.h>
30#include <string.h>
31#include <poll.h>
32#include <endian.h>
33#include <getopt.h>
34#include <inttypes.h>
35#include "iio_utils.h"
36
37/**
38 * size_from_channelarray() - calculate the storage size of a scan
39 * @channels: the channel info array
40 * @num_channels: number of channels
41 *
42 * Has the side effect of filling the channels[i].location values used
43 * in processing the buffer output.
44 **/
45int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
46{
47 int bytes = 0;
48 int i = 0;
49
50 while (i < num_channels) {
51 if (bytes % channels[i].bytes == 0)
52 channels[i].location = bytes;
53 else
54 channels[i].location = bytes - bytes%channels[i].bytes
55 + channels[i].bytes;
56 bytes = channels[i].location + channels[i].bytes;
57 i++;
58 }
59 return bytes;
60}
61
62void print2byte(int input, struct iio_channel_info *info)
63{
64 /* First swap if incorrect endian */
65 if (info->be)
66 input = be16toh((uint16_t)input);
67 else
68 input = le16toh((uint16_t)input);
69
70 /*
71 * Shift before conversion to avoid sign extension
72 * of left aligned data
73 */
74 input >>= info->shift;
75 if (info->is_signed) {
76 int16_t val = input;
77
78 val &= (1 << info->bits_used) - 1;
79 val = (int16_t)(val << (16 - info->bits_used)) >>
80 (16 - info->bits_used);
81 printf("%05f ", ((float)val + info->offset)*info->scale);
82 } else {
83 uint16_t val = input;
84
85 val &= (1 << info->bits_used) - 1;
86 printf("%05f ", ((float)val + info->offset)*info->scale);
87 }
88}
89/**
90 * process_scan() - print out the values in SI units
91 * @data: pointer to the start of the scan
92 * @channels: information about the channels. Note
93 * size_from_channelarray must have been called first to fill the
94 * location offsets.
95 * @num_channels: number of channels
96 **/
97void process_scan(char *data,
98 struct iio_channel_info *channels,
99 int num_channels)
100{
101 int k;
102
103 for (k = 0; k < num_channels; k++)
104 switch (channels[k].bytes) {
105 /* only a few cases implemented so far */
106 case 2:
107 print2byte(*(uint16_t *)(data + channels[k].location),
108 &channels[k]);
109 break;
110 case 4:
111 if (!channels[k].is_signed) {
112 uint32_t val = *(uint32_t *)
113 (data + channels[k].location);
114 printf("%05f ", ((float)val +
115 channels[k].offset)*
116 channels[k].scale);
117
118 }
119 break;
120 case 8:
121 if (channels[k].is_signed) {
122 int64_t val = *(int64_t *)
123 (data +
124 channels[k].location);
125 if ((val >> channels[k].bits_used) & 1)
126 val = (val & channels[k].mask) |
127 ~channels[k].mask;
128 /* special case for timestamp */
129 if (channels[k].scale == 1.0f &&
130 channels[k].offset == 0.0f)
131 printf("%" PRId64 " ", val);
132 else
133 printf("%05f ", ((float)val +
134 channels[k].offset)*
135 channels[k].scale);
136 }
137 break;
138 default:
139 break;
140 }
141 printf("\n");
142}
143
144int main(int argc, char **argv)
145{
146 unsigned long num_loops = 2;
147 unsigned long timedelay = 1000000;
148 unsigned long buf_len = 128;
149
150 int ret, c, i, j, toread;
151 int fp;
152
153 int num_channels;
154 char *trigger_name = NULL, *device_name = NULL;
155 char *dev_dir_name, *buf_dir_name;
156
157 int datardytrigger = 1;
158 char *data;
159 ssize_t read_size;
160 int dev_num, trig_num;
161 char *buffer_access;
162 int scan_size;
163 int noevents = 0;
164 int notrigger = 0;
165 char *dummy;
166
167 struct iio_channel_info *channels;
168
169 while ((c = getopt(argc, argv, "l:w:c:et:n:g")) != -1) {
170 switch (c) {
171 case 'n':
172 device_name = optarg;
173 break;
174 case 't':
175 trigger_name = optarg;
176 datardytrigger = 0;
177 break;
178 case 'e':
179 noevents = 1;
180 break;
181 case 'c':
182 num_loops = strtoul(optarg, &dummy, 10);
183 break;
184 case 'w':
185 timedelay = strtoul(optarg, &dummy, 10);
186 break;
187 case 'l':
188 buf_len = strtoul(optarg, &dummy, 10);
189 break;
190 case 'g':
191 notrigger = 1;
192 break;
193 case '?':
194 return -1;
195 }
196 }
197
198 if (device_name == NULL)
199 return -1;
200
201 /* Find the device requested */
202 dev_num = find_type_by_name(device_name, "iio:device");
203 if (dev_num < 0) {
204 printf("Failed to find the %s\n", device_name);
205 ret = -ENODEV;
206 goto error_ret;
207 }
208 printf("iio device number being used is %d\n", dev_num);
209
210 asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
211
212 if (!notrigger) {
213 if (trigger_name == NULL) {
214 /*
215 * Build the trigger name. If it is device associated
216 * its name is <device_name>_dev[n] where n matches
217 * the device number found above.
218 */
219 ret = asprintf(&trigger_name,
220 "%s-dev%d", device_name, dev_num);
221 if (ret < 0) {
222 ret = -ENOMEM;
223 goto error_ret;
224 }
225 }
226
227 /* Verify the trigger exists */
228 trig_num = find_type_by_name(trigger_name, "trigger");
229 if (trig_num < 0) {
230 printf("Failed to find the trigger %s\n", trigger_name);
231 ret = -ENODEV;
232 goto error_free_triggername;
233 }
234 printf("iio trigger number being used is %d\n", trig_num);
235 } else
236 printf("trigger-less mode selected\n");
237
238 /*
239 * Parse the files in scan_elements to identify what channels are
240 * present
241 */
242 ret = build_channel_array(dev_dir_name, &channels, &num_channels);
243 if (ret) {
244 printf("Problem reading scan element information\n");
245 printf("diag %s\n", dev_dir_name);
246 goto error_free_triggername;
247 }
248
249 /*
250 * Construct the directory name for the associated buffer.
251 * As we know that the lis3l02dq has only one buffer this may
252 * be built rather than found.
253 */
254 ret = asprintf(&buf_dir_name,
255 "%siio:device%d/buffer", iio_dir, dev_num);
256 if (ret < 0) {
257 ret = -ENOMEM;
258 goto error_free_triggername;
259 }
260
261 if (!notrigger) {
262 printf("%s %s\n", dev_dir_name, trigger_name);
263 /* Set the device trigger to be the data ready trigger found
264 * above */
265 ret = write_sysfs_string_and_verify("trigger/current_trigger",
266 dev_dir_name,
267 trigger_name);
268 if (ret < 0) {
269 printf("Failed to write current_trigger file\n");
270 goto error_free_buf_dir_name;
271 }
272 }
273
274 /* Setup ring buffer parameters */
275 ret = write_sysfs_int("length", buf_dir_name, buf_len);
276 if (ret < 0)
277 goto error_free_buf_dir_name;
278
279 /* Enable the buffer */
280 ret = write_sysfs_int("enable", buf_dir_name, 1);
281 if (ret < 0)
282 goto error_free_buf_dir_name;
283 scan_size = size_from_channelarray(channels, num_channels);
284 data = malloc(scan_size*buf_len);
285 if (!data) {
286 ret = -ENOMEM;
287 goto error_free_buf_dir_name;
288 }
289
290 ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
291 if (ret < 0) {
292 ret = -ENOMEM;
293 goto error_free_data;
294 }
295
296 /* Attempt to open non blocking the access dev */
297 fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
298 if (fp == -1) { /* If it isn't there make the node */
299 printf("Failed to open %s\n", buffer_access);
300 ret = -errno;
301 goto error_free_buffer_access;
302 }
303
304 /* Wait for events 10 times */
305 for (j = 0; j < num_loops; j++) {
306 if (!noevents) {
307 struct pollfd pfd = {
308 .fd = fp,
309 .events = POLLIN,
310 };
311
312 poll(&pfd, 1, -1);
313 toread = buf_len;
314
315 } else {
316 usleep(timedelay);
317 toread = 64;
318 }
319
320 read_size = read(fp,
321 data,
322 toread*scan_size);
323 if (read_size < 0) {
324 if (errno == -EAGAIN) {
325 printf("nothing available\n");
326 continue;
327 } else
328 break;
329 }
330 for (i = 0; i < read_size/scan_size; i++)
331 process_scan(data + scan_size*i,
332 channels,
333 num_channels);
334 }
335
336 /* Stop the buffer */
337 ret = write_sysfs_int("enable", buf_dir_name, 0);
338 if (ret < 0)
339 goto error_close_buffer_access;
340
341 if (!notrigger)
342 /* Disconnect the trigger - just write a dummy name. */
343 write_sysfs_string("trigger/current_trigger",
344 dev_dir_name, "NULL");
345
346error_close_buffer_access:
347 close(fp);
348error_free_data:
349 free(data);
350error_free_buffer_access:
351 free(buffer_access);
352error_free_buf_dir_name:
353 free(buf_dir_name);
354error_free_triggername:
355 if (datardytrigger)
356 free(trigger_name);
357error_ret:
358 return ret;
359}
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
new file mode 100644
index 000000000000..427c271ac0d6
--- /dev/null
+++ b/tools/iio/iio_event_monitor.c
@@ -0,0 +1,308 @@
1/* Industrialio event test code.
2 *
3 * Copyright (c) 2011-2012 Lars-Peter Clausen <lars@metafoo.de>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is primarily intended as an example application.
10 * Reads the current buffer setup from sysfs and starts a short capture
11 * from the specified device, pretty printing the result after appropriate
12 * conversion.
13 *
14 * Usage:
15 * iio_event_monitor <device_name>
16 *
17 */
18
19#include <unistd.h>
20#include <stdlib.h>
21#include <stdbool.h>
22#include <stdio.h>
23#include <errno.h>
24#include <string.h>
25#include <poll.h>
26#include <fcntl.h>
27#include <sys/ioctl.h>
28#include "iio_utils.h"
29#include <linux/iio/events.h>
30#include <linux/iio/types.h>
31
32static const char * const iio_chan_type_name_spec[] = {
33 [IIO_VOLTAGE] = "voltage",
34 [IIO_CURRENT] = "current",
35 [IIO_POWER] = "power",
36 [IIO_ACCEL] = "accel",
37 [IIO_ANGL_VEL] = "anglvel",
38 [IIO_MAGN] = "magn",
39 [IIO_LIGHT] = "illuminance",
40 [IIO_INTENSITY] = "intensity",
41 [IIO_PROXIMITY] = "proximity",
42 [IIO_TEMP] = "temp",
43 [IIO_INCLI] = "incli",
44 [IIO_ROT] = "rot",
45 [IIO_ANGL] = "angl",
46 [IIO_TIMESTAMP] = "timestamp",
47 [IIO_CAPACITANCE] = "capacitance",
48 [IIO_ALTVOLTAGE] = "altvoltage",
49 [IIO_CCT] = "cct",
50 [IIO_PRESSURE] = "pressure",
51 [IIO_HUMIDITYRELATIVE] = "humidityrelative",
52 [IIO_ACTIVITY] = "activity",
53 [IIO_STEPS] = "steps",
54};
55
56static const char * const iio_ev_type_text[] = {
57 [IIO_EV_TYPE_THRESH] = "thresh",
58 [IIO_EV_TYPE_MAG] = "mag",
59 [IIO_EV_TYPE_ROC] = "roc",
60 [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",
61 [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",
62 [IIO_EV_TYPE_CHANGE] = "change",
63};
64
65static const char * const iio_ev_dir_text[] = {
66 [IIO_EV_DIR_EITHER] = "either",
67 [IIO_EV_DIR_RISING] = "rising",
68 [IIO_EV_DIR_FALLING] = "falling"
69};
70
71static const char * const iio_modifier_names[] = {
72 [IIO_MOD_X] = "x",
73 [IIO_MOD_Y] = "y",
74 [IIO_MOD_Z] = "z",
75 [IIO_MOD_X_AND_Y] = "x&y",
76 [IIO_MOD_X_AND_Z] = "x&z",
77 [IIO_MOD_Y_AND_Z] = "y&z",
78 [IIO_MOD_X_AND_Y_AND_Z] = "x&y&z",
79 [IIO_MOD_X_OR_Y] = "x|y",
80 [IIO_MOD_X_OR_Z] = "x|z",
81 [IIO_MOD_Y_OR_Z] = "y|z",
82 [IIO_MOD_X_OR_Y_OR_Z] = "x|y|z",
83 [IIO_MOD_LIGHT_BOTH] = "both",
84 [IIO_MOD_LIGHT_IR] = "ir",
85 [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
86 [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
87 [IIO_MOD_LIGHT_CLEAR] = "clear",
88 [IIO_MOD_LIGHT_RED] = "red",
89 [IIO_MOD_LIGHT_GREEN] = "green",
90 [IIO_MOD_LIGHT_BLUE] = "blue",
91 [IIO_MOD_QUATERNION] = "quaternion",
92 [IIO_MOD_TEMP_AMBIENT] = "ambient",
93 [IIO_MOD_TEMP_OBJECT] = "object",
94 [IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
95 [IIO_MOD_NORTH_TRUE] = "from_north_true",
96 [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
97 [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
98 [IIO_MOD_RUNNING] = "running",
99 [IIO_MOD_JOGGING] = "jogging",
100 [IIO_MOD_WALKING] = "walking",
101 [IIO_MOD_STILL] = "still",
102};
103
104static bool event_is_known(struct iio_event_data *event)
105{
106 enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
107 enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
108 enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
109 enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
110
111 switch (type) {
112 case IIO_VOLTAGE:
113 case IIO_CURRENT:
114 case IIO_POWER:
115 case IIO_ACCEL:
116 case IIO_ANGL_VEL:
117 case IIO_MAGN:
118 case IIO_LIGHT:
119 case IIO_INTENSITY:
120 case IIO_PROXIMITY:
121 case IIO_TEMP:
122 case IIO_INCLI:
123 case IIO_ROT:
124 case IIO_ANGL:
125 case IIO_TIMESTAMP:
126 case IIO_CAPACITANCE:
127 case IIO_ALTVOLTAGE:
128 case IIO_CCT:
129 case IIO_PRESSURE:
130 case IIO_HUMIDITYRELATIVE:
131 case IIO_ACTIVITY:
132 case IIO_STEPS:
133 break;
134 default:
135 return false;
136 }
137
138 switch (mod) {
139 case IIO_NO_MOD:
140 case IIO_MOD_X:
141 case IIO_MOD_Y:
142 case IIO_MOD_Z:
143 case IIO_MOD_X_AND_Y:
144 case IIO_MOD_X_AND_Z:
145 case IIO_MOD_Y_AND_Z:
146 case IIO_MOD_X_AND_Y_AND_Z:
147 case IIO_MOD_X_OR_Y:
148 case IIO_MOD_X_OR_Z:
149 case IIO_MOD_Y_OR_Z:
150 case IIO_MOD_X_OR_Y_OR_Z:
151 case IIO_MOD_LIGHT_BOTH:
152 case IIO_MOD_LIGHT_IR:
153 case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
154 case IIO_MOD_SUM_SQUARED_X_Y_Z:
155 case IIO_MOD_LIGHT_CLEAR:
156 case IIO_MOD_LIGHT_RED:
157 case IIO_MOD_LIGHT_GREEN:
158 case IIO_MOD_LIGHT_BLUE:
159 case IIO_MOD_QUATERNION:
160 case IIO_MOD_TEMP_AMBIENT:
161 case IIO_MOD_TEMP_OBJECT:
162 case IIO_MOD_NORTH_MAGN:
163 case IIO_MOD_NORTH_TRUE:
164 case IIO_MOD_NORTH_MAGN_TILT_COMP:
165 case IIO_MOD_NORTH_TRUE_TILT_COMP:
166 case IIO_MOD_RUNNING:
167 case IIO_MOD_JOGGING:
168 case IIO_MOD_WALKING:
169 case IIO_MOD_STILL:
170 break;
171 default:
172 return false;
173 }
174
175 switch (ev_type) {
176 case IIO_EV_TYPE_THRESH:
177 case IIO_EV_TYPE_MAG:
178 case IIO_EV_TYPE_ROC:
179 case IIO_EV_TYPE_THRESH_ADAPTIVE:
180 case IIO_EV_TYPE_MAG_ADAPTIVE:
181 case IIO_EV_TYPE_CHANGE:
182 break;
183 default:
184 return false;
185 }
186
187 switch (dir) {
188 case IIO_EV_DIR_EITHER:
189 case IIO_EV_DIR_RISING:
190 case IIO_EV_DIR_FALLING:
191 case IIO_EV_DIR_NONE:
192 break;
193 default:
194 return false;
195 }
196
197 return true;
198}
199
200static void print_event(struct iio_event_data *event)
201{
202 enum iio_chan_type type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
203 enum iio_modifier mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
204 enum iio_event_type ev_type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
205 enum iio_event_direction dir = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
206 int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event->id);
207 int chan2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id);
208 bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
209
210 if (!event_is_known(event)) {
211 printf("Unknown event: time: %lld, id: %llx\n",
212 event->timestamp, event->id);
213 return;
214 }
215
216 printf("Event: time: %lld, ", event->timestamp);
217
218 if (mod != IIO_NO_MOD) {
219 printf("type: %s(%s), ",
220 iio_chan_type_name_spec[type],
221 iio_modifier_names[mod]);
222 } else {
223 printf("type: %s, ",
224 iio_chan_type_name_spec[type]);
225 }
226
227 if (diff && chan >= 0 && chan2 >= 0)
228 printf("channel: %d-%d, ", chan, chan2);
229 else if (chan >= 0)
230 printf("channel: %d, ", chan);
231
232 printf("evtype: %s", iio_ev_type_text[ev_type]);
233
234 if (dir != IIO_EV_DIR_NONE)
235 printf(", direction: %s", iio_ev_dir_text[dir]);
236 printf("\n");
237}
238
239int main(int argc, char **argv)
240{
241 struct iio_event_data event;
242 const char *device_name;
243 char *chrdev_name;
244 int ret;
245 int dev_num;
246 int fd, event_fd;
247
248 if (argc <= 1) {
249 printf("Usage: %s <device_name>\n", argv[0]);
250 return -1;
251 }
252
253 device_name = argv[1];
254
255 dev_num = find_type_by_name(device_name, "iio:device");
256 if (dev_num >= 0) {
257 printf("Found IIO device with name %s with device number %d\n",
258 device_name, dev_num);
259 ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num);
260 if (ret < 0) {
261 ret = -ENOMEM;
262 goto error_ret;
263 }
264 } else {
265 /* If we can't find a IIO device by name assume device_name is a
266 IIO chrdev */
267 chrdev_name = strdup(device_name);
268 }
269
270 fd = open(chrdev_name, 0);
271 if (fd == -1) {
272 fprintf(stdout, "Failed to open %s\n", chrdev_name);
273 ret = -errno;
274 goto error_free_chrdev_name;
275 }
276
277 ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
278
279 close(fd);
280
281 if (ret == -1 || event_fd == -1) {
282 fprintf(stdout, "Failed to retrieve event fd\n");
283 ret = -errno;
284 goto error_free_chrdev_name;
285 }
286
287 while (true) {
288 ret = read(event_fd, &event, sizeof(event));
289 if (ret == -1) {
290 if (errno == EAGAIN) {
291 printf("nothing available\n");
292 continue;
293 } else {
294 perror("Failed to read event from device");
295 ret = -errno;
296 break;
297 }
298 }
299
300 print_event(&event);
301 }
302
303 close(event_fd);
304error_free_chrdev_name:
305 free(chrdev_name);
306error_ret:
307 return ret;
308}
diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
new file mode 100644
index 000000000000..6f6452167b67
--- /dev/null
+++ b/tools/iio/iio_utils.c
@@ -0,0 +1,669 @@
1/* IIO - useful set of util functionality
2 *
3 * Copyright (c) 2008 Jonathan Cameron
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 */
9#ifndef _IIO_UTILS_H
10#define _IIO_UTILS_H
11
12#include <string.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <stdint.h>
16#include <dirent.h>
17#include <errno.h>
18#include <ctype.h>
19#include "iio_utils.h"
20
21const char *iio_dir = "/sys/bus/iio/devices/";
22
23static char * const iio_direction[] = {
24 "in",
25 "out",
26};
27
28/**
29 * iioutils_break_up_name() - extract generic name from full channel name
30 * @full_name: the full channel name
31 * @generic_name: the output generic channel name
32 **/
33int iioutils_break_up_name(const char *full_name,
34 char **generic_name)
35{
36 char *current;
37 char *w, *r;
38 char *working, *prefix = "";
39 int i;
40
41 for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
42 if (!strncmp(full_name, iio_direction[i],
43 strlen(iio_direction[i]))) {
44 prefix = iio_direction[i];
45 break;
46 }
47
48 current = strdup(full_name + strlen(prefix) + 1);
49 working = strtok(current, "_\0");
50
51 w = working;
52 r = working;
53
54 while (*r != '\0') {
55 if (!isdigit(*r)) {
56 *w = *r;
57 w++;
58 }
59 r++;
60 }
61 *w = '\0';
62 asprintf(generic_name, "%s_%s", prefix, working);
63 free(current);
64
65 return 0;
66}
67
68/**
69 * iioutils_get_type() - find and process _type attribute data
70 * @is_signed: output whether channel is signed
71 * @bytes: output how many bytes the channel storage occupies
72 * @mask: output a bit mask for the raw data
73 * @be: big endian
74 * @device_dir: the iio device directory
75 * @name: the channel name
76 * @generic_name: the channel type name
77 **/
78int iioutils_get_type(unsigned *is_signed,
79 unsigned *bytes,
80 unsigned *bits_used,
81 unsigned *shift,
82 uint64_t *mask,
83 unsigned *be,
84 const char *device_dir,
85 const char *name,
86 const char *generic_name)
87{
88 FILE *sysfsfp;
89 int ret;
90 DIR *dp;
91 char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
92 char signchar, endianchar;
93 unsigned padint;
94 const struct dirent *ent;
95
96 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
97 if (ret < 0) {
98 ret = -ENOMEM;
99 goto error_ret;
100 }
101 ret = asprintf(&builtname, FORMAT_TYPE_FILE, name);
102 if (ret < 0) {
103 ret = -ENOMEM;
104 goto error_free_scan_el_dir;
105 }
106 ret = asprintf(&builtname_generic, FORMAT_TYPE_FILE, generic_name);
107 if (ret < 0) {
108 ret = -ENOMEM;
109 goto error_free_builtname;
110 }
111
112 dp = opendir(scan_el_dir);
113 if (dp == NULL) {
114 ret = -errno;
115 goto error_free_builtname_generic;
116 }
117 while (ent = readdir(dp), ent != NULL)
118 /*
119 * Do we allow devices to override a generic name with
120 * a specific one?
121 */
122 if ((strcmp(builtname, ent->d_name) == 0) ||
123 (strcmp(builtname_generic, ent->d_name) == 0)) {
124 ret = asprintf(&filename,
125 "%s/%s", scan_el_dir, ent->d_name);
126 if (ret < 0) {
127 ret = -ENOMEM;
128 goto error_closedir;
129 }
130 sysfsfp = fopen(filename, "r");
131 if (sysfsfp == NULL) {
132 printf("failed to open %s\n", filename);
133 ret = -errno;
134 goto error_free_filename;
135 }
136
137 ret = fscanf(sysfsfp,
138 "%ce:%c%u/%u>>%u",
139 &endianchar,
140 &signchar,
141 bits_used,
142 &padint, shift);
143 if (ret < 0) {
144 printf("failed to pass scan type description\n");
145 ret = -errno;
146 goto error_close_sysfsfp;
147 }
148 *be = (endianchar == 'b');
149 *bytes = padint / 8;
150 if (*bits_used == 64)
151 *mask = ~0;
152 else
153 *mask = (1 << *bits_used) - 1;
154 if (signchar == 's')
155 *is_signed = 1;
156 else
157 *is_signed = 0;
158 fclose(sysfsfp);
159 free(filename);
160
161 filename = 0;
162 sysfsfp = 0;
163 }
164error_close_sysfsfp:
165 if (sysfsfp)
166 fclose(sysfsfp);
167error_free_filename:
168 if (filename)
169 free(filename);
170error_closedir:
171 closedir(dp);
172error_free_builtname_generic:
173 free(builtname_generic);
174error_free_builtname:
175 free(builtname);
176error_free_scan_el_dir:
177 free(scan_el_dir);
178error_ret:
179 return ret;
180}
181
182int iioutils_get_param_float(float *output,
183 const char *param_name,
184 const char *device_dir,
185 const char *name,
186 const char *generic_name)
187{
188 FILE *sysfsfp;
189 int ret;
190 DIR *dp;
191 char *builtname, *builtname_generic;
192 char *filename = NULL;
193 const struct dirent *ent;
194
195 ret = asprintf(&builtname, "%s_%s", name, param_name);
196 if (ret < 0) {
197 ret = -ENOMEM;
198 goto error_ret;
199 }
200 ret = asprintf(&builtname_generic,
201 "%s_%s", generic_name, param_name);
202 if (ret < 0) {
203 ret = -ENOMEM;
204 goto error_free_builtname;
205 }
206 dp = opendir(device_dir);
207 if (dp == NULL) {
208 ret = -errno;
209 goto error_free_builtname_generic;
210 }
211 while (ent = readdir(dp), ent != NULL)
212 if ((strcmp(builtname, ent->d_name) == 0) ||
213 (strcmp(builtname_generic, ent->d_name) == 0)) {
214 ret = asprintf(&filename,
215 "%s/%s", device_dir, ent->d_name);
216 if (ret < 0) {
217 ret = -ENOMEM;
218 goto error_closedir;
219 }
220 sysfsfp = fopen(filename, "r");
221 if (!sysfsfp) {
222 ret = -errno;
223 goto error_free_filename;
224 }
225 fscanf(sysfsfp, "%f", output);
226 break;
227 }
228error_free_filename:
229 if (filename)
230 free(filename);
231error_closedir:
232 closedir(dp);
233error_free_builtname_generic:
234 free(builtname_generic);
235error_free_builtname:
236 free(builtname);
237error_ret:
238 return ret;
239}
240
241/**
242 * bsort_channel_array_by_index() - reorder so that the array is in index order
243 *
244 **/
245
246void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
247 int cnt)
248{
249
250 struct iio_channel_info temp;
251 int x, y;
252
253 for (x = 0; x < cnt; x++)
254 for (y = 0; y < (cnt - 1); y++)
255 if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
256 temp = (*ci_array)[y + 1];
257 (*ci_array)[y + 1] = (*ci_array)[y];
258 (*ci_array)[y] = temp;
259 }
260}
261
262/**
263 * build_channel_array() - function to figure out what channels are present
264 * @device_dir: the IIO device directory in sysfs
265 * @
266 **/
267int build_channel_array(const char *device_dir,
268 struct iio_channel_info **ci_array,
269 int *counter)
270{
271 DIR *dp;
272 FILE *sysfsfp;
273 int count, i;
274 struct iio_channel_info *current;
275 int ret;
276 const struct dirent *ent;
277 char *scan_el_dir;
278 char *filename;
279
280 *counter = 0;
281 ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
282 if (ret < 0) {
283 ret = -ENOMEM;
284 goto error_ret;
285 }
286 dp = opendir(scan_el_dir);
287 if (dp == NULL) {
288 ret = -errno;
289 goto error_free_name;
290 }
291 while (ent = readdir(dp), ent != NULL)
292 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
293 "_en") == 0) {
294 ret = asprintf(&filename,
295 "%s/%s", scan_el_dir, ent->d_name);
296 if (ret < 0) {
297 ret = -ENOMEM;
298 goto error_close_dir;
299 }
300 sysfsfp = fopen(filename, "r");
301 if (sysfsfp == NULL) {
302 ret = -errno;
303 free(filename);
304 goto error_close_dir;
305 }
306 fscanf(sysfsfp, "%i", &ret);
307 if (ret == 1)
308 (*counter)++;
309 fclose(sysfsfp);
310 free(filename);
311 }
312 *ci_array = malloc(sizeof(**ci_array) * (*counter));
313 if (*ci_array == NULL) {
314 ret = -ENOMEM;
315 goto error_close_dir;
316 }
317 seekdir(dp, 0);
318 count = 0;
319 while (ent = readdir(dp), ent != NULL) {
320 if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
321 "_en") == 0) {
322 int current_enabled = 0;
323
324 current = &(*ci_array)[count++];
325 ret = asprintf(&filename,
326 "%s/%s", scan_el_dir, ent->d_name);
327 if (ret < 0) {
328 ret = -ENOMEM;
329 /* decrement count to avoid freeing name */
330 count--;
331 goto error_cleanup_array;
332 }
333 sysfsfp = fopen(filename, "r");
334 if (sysfsfp == NULL) {
335 free(filename);
336 ret = -errno;
337 goto error_cleanup_array;
338 }
339 fscanf(sysfsfp, "%i", &current_enabled);
340 fclose(sysfsfp);
341
342 if (!current_enabled) {
343 free(filename);
344 count--;
345 continue;
346 }
347
348 current->scale = 1.0;
349 current->offset = 0;
350 current->name = strndup(ent->d_name,
351 strlen(ent->d_name) -
352 strlen("_en"));
353 if (current->name == NULL) {
354 free(filename);
355 ret = -ENOMEM;
356 goto error_cleanup_array;
357 }
358 /* Get the generic and specific name elements */
359 ret = iioutils_break_up_name(current->name,
360 &current->generic_name);
361 if (ret) {
362 free(filename);
363 goto error_cleanup_array;
364 }
365 ret = asprintf(&filename,
366 "%s/%s_index",
367 scan_el_dir,
368 current->name);
369 if (ret < 0) {
370 free(filename);
371 ret = -ENOMEM;
372 goto error_cleanup_array;
373 }
374 sysfsfp = fopen(filename, "r");
375 fscanf(sysfsfp, "%u", &current->index);
376 fclose(sysfsfp);
377 free(filename);
378 /* Find the scale */
379 ret = iioutils_get_param_float(&current->scale,
380 "scale",
381 device_dir,
382 current->name,
383 current->generic_name);
384 if (ret < 0)
385 goto error_cleanup_array;
386 ret = iioutils_get_param_float(&current->offset,
387 "offset",
388 device_dir,
389 current->name,
390 current->generic_name);
391 if (ret < 0)
392 goto error_cleanup_array;
393 ret = iioutils_get_type(&current->is_signed,
394 &current->bytes,
395 &current->bits_used,
396 &current->shift,
397 &current->mask,
398 &current->be,
399 device_dir,
400 current->name,
401 current->generic_name);
402 }
403 }
404
405 closedir(dp);
406 /* reorder so that the array is in index order */
407 bsort_channel_array_by_index(ci_array, *counter);
408
409 return 0;
410
411error_cleanup_array:
412 for (i = count - 1; i >= 0; i--)
413 free((*ci_array)[i].name);
414 free(*ci_array);
415error_close_dir:
416 closedir(dp);
417error_free_name:
418 free(scan_el_dir);
419error_ret:
420 return ret;
421}
422
423/**
424 * find_type_by_name() - function to match top level types by name
425 * @name: top level type instance name
426 * @type: the type of top level instance being sort
427 *
428 * Typical types this is used for are device and trigger.
429 **/
430int find_type_by_name(const char *name, const char *type)
431{
432 const struct dirent *ent;
433 int number, numstrlen;
434
435 FILE *nameFile;
436 DIR *dp;
437 char thisname[IIO_MAX_NAME_LENGTH];
438 char *filename;
439
440 dp = opendir(iio_dir);
441 if (dp == NULL) {
442 printf("No industrialio devices available\n");
443 return -ENODEV;
444 }
445
446 while (ent = readdir(dp), ent != NULL) {
447 if (strcmp(ent->d_name, ".") != 0 &&
448 strcmp(ent->d_name, "..") != 0 &&
449 strlen(ent->d_name) > strlen(type) &&
450 strncmp(ent->d_name, type, strlen(type)) == 0) {
451 numstrlen = sscanf(ent->d_name + strlen(type),
452 "%d",
453 &number);
454 /* verify the next character is not a colon */
455 if (strncmp(ent->d_name + strlen(type) + numstrlen,
456 ":",
457 1) != 0) {
458 filename = malloc(strlen(iio_dir)
459 + strlen(type)
460 + numstrlen
461 + 6);
462 if (filename == NULL) {
463 closedir(dp);
464 return -ENOMEM;
465 }
466 sprintf(filename, "%s%s%d/name",
467 iio_dir,
468 type,
469 number);
470 nameFile = fopen(filename, "r");
471 if (!nameFile) {
472 free(filename);
473 continue;
474 }
475 free(filename);
476 fscanf(nameFile, "%s", thisname);
477 fclose(nameFile);
478 if (strcmp(name, thisname) == 0) {
479 closedir(dp);
480 return number;
481 }
482 }
483 }
484 }
485 closedir(dp);
486 return -ENODEV;
487}
488
489int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
490{
491 int ret = 0;
492 FILE *sysfsfp;
493 int test;
494 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
495
496 if (temp == NULL)
497 return -ENOMEM;
498 sprintf(temp, "%s/%s", basedir, filename);
499 sysfsfp = fopen(temp, "w");
500 if (sysfsfp == NULL) {
501 printf("failed to open %s\n", temp);
502 ret = -errno;
503 goto error_free;
504 }
505 fprintf(sysfsfp, "%d", val);
506 fclose(sysfsfp);
507 if (verify) {
508 sysfsfp = fopen(temp, "r");
509 if (sysfsfp == NULL) {
510 printf("failed to open %s\n", temp);
511 ret = -errno;
512 goto error_free;
513 }
514 fscanf(sysfsfp, "%d", &test);
515 fclose(sysfsfp);
516 if (test != val) {
517 printf("Possible failure in int write %d to %s%s\n",
518 val,
519 basedir,
520 filename);
521 ret = -1;
522 }
523 }
524error_free:
525 free(temp);
526 return ret;
527}
528
529int write_sysfs_int(char *filename, char *basedir, int val)
530{
531 return _write_sysfs_int(filename, basedir, val, 0);
532}
533
534int write_sysfs_int_and_verify(char *filename, char *basedir, int val)
535{
536 return _write_sysfs_int(filename, basedir, val, 1);
537}
538
539int _write_sysfs_string(char *filename, char *basedir, char *val, int verify)
540{
541 int ret = 0;
542 FILE *sysfsfp;
543 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
544
545 if (temp == NULL) {
546 printf("Memory allocation failed\n");
547 return -ENOMEM;
548 }
549 sprintf(temp, "%s/%s", basedir, filename);
550 sysfsfp = fopen(temp, "w");
551 if (sysfsfp == NULL) {
552 printf("Could not open %s\n", temp);
553 ret = -errno;
554 goto error_free;
555 }
556 fprintf(sysfsfp, "%s", val);
557 fclose(sysfsfp);
558 if (verify) {
559 sysfsfp = fopen(temp, "r");
560 if (sysfsfp == NULL) {
561 printf("could not open file to verify\n");
562 ret = -errno;
563 goto error_free;
564 }
565 fscanf(sysfsfp, "%s", temp);
566 fclose(sysfsfp);
567 if (strcmp(temp, val) != 0) {
568 printf("Possible failure in string write of %s "
569 "Should be %s "
570 "written to %s\%s\n",
571 temp,
572 val,
573 basedir,
574 filename);
575 ret = -1;
576 }
577 }
578error_free:
579 free(temp);
580
581 return ret;
582}
583
584/**
585 * write_sysfs_string_and_verify() - string write, readback and verify
586 * @filename: name of file to write to
587 * @basedir: the sysfs directory in which the file is to be found
588 * @val: the string to write
589 **/
590int write_sysfs_string_and_verify(char *filename, char *basedir, char *val)
591{
592 return _write_sysfs_string(filename, basedir, val, 1);
593}
594
595int write_sysfs_string(char *filename, char *basedir, char *val)
596{
597 return _write_sysfs_string(filename, basedir, val, 0);
598}
599
600int read_sysfs_posint(char *filename, char *basedir)
601{
602 int ret;
603 FILE *sysfsfp;
604 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
605
606 if (temp == NULL) {
607 printf("Memory allocation failed");
608 return -ENOMEM;
609 }
610 sprintf(temp, "%s/%s", basedir, filename);
611 sysfsfp = fopen(temp, "r");
612 if (sysfsfp == NULL) {
613 ret = -errno;
614 goto error_free;
615 }
616 fscanf(sysfsfp, "%d\n", &ret);
617 fclose(sysfsfp);
618error_free:
619 free(temp);
620 return ret;
621}
622
623int read_sysfs_float(char *filename, char *basedir, float *val)
624{
625 int ret = 0;
626 FILE *sysfsfp;
627 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
628
629 if (temp == NULL) {
630 printf("Memory allocation failed");
631 return -ENOMEM;
632 }
633 sprintf(temp, "%s/%s", basedir, filename);
634 sysfsfp = fopen(temp, "r");
635 if (sysfsfp == NULL) {
636 ret = -errno;
637 goto error_free;
638 }
639 fscanf(sysfsfp, "%f\n", val);
640 fclose(sysfsfp);
641error_free:
642 free(temp);
643 return ret;
644}
645
646int read_sysfs_string(const char *filename, const char *basedir, char *str)
647{
648 int ret = 0;
649 FILE *sysfsfp;
650 char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
651
652 if (temp == NULL) {
653 printf("Memory allocation failed");
654 return -ENOMEM;
655 }
656 sprintf(temp, "%s/%s", basedir, filename);
657 sysfsfp = fopen(temp, "r");
658 if (sysfsfp == NULL) {
659 ret = -errno;
660 goto error_free;
661 }
662 fscanf(sysfsfp, "%s\n", str);
663 fclose(sysfsfp);
664error_free:
665 free(temp);
666 return ret;
667}
668
669#endif /* _IIO_UTILS_H */
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
new file mode 100644
index 000000000000..1bc837b2d769
--- /dev/null
+++ b/tools/iio/iio_utils.h
@@ -0,0 +1,71 @@
1#ifndef _IIO_UTILS_H_
2#define _IIO_UTILS_H_
3
4/* IIO - useful set of util functionality
5 *
6 * Copyright (c) 2008 Jonathan Cameron
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 by
10 * the Free Software Foundation.
11 */
12
13#include <stdint.h>
14
15/* Made up value to limit allocation sizes */
16#define IIO_MAX_NAME_LENGTH 30
17
18#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
19#define FORMAT_TYPE_FILE "%s_type"
20
21extern const char *iio_dir;
22
23/**
24 * struct iio_channel_info - information about a given channel
25 * @name: channel name
26 * @generic_name: general name for channel type
27 * @scale: scale factor to be applied for conversion to si units
28 * @offset: offset to be applied for conversion to si units
29 * @index: the channel index in the buffer output
30 * @bytes: number of bytes occupied in buffer output
31 * @mask: a bit mask for the raw output
32 * @is_signed: is the raw value stored signed
33 * @enabled: is this channel enabled
34 **/
35struct iio_channel_info {
36 char *name;
37 char *generic_name;
38 float scale;
39 float offset;
40 unsigned index;
41 unsigned bytes;
42 unsigned bits_used;
43 unsigned shift;
44 uint64_t mask;
45 unsigned be;
46 unsigned is_signed;
47 unsigned location;
48};
49
50int iioutils_break_up_name(const char *full_name, char **generic_name);
51int iioutils_get_type(unsigned *is_signed, unsigned *bytes,
52 unsigned *bits_used, unsigned *shift,
53 uint64_t *mask, unsigned *be,
54 const char *device_dir, const char *name,
55 const char *generic_name);
56int iioutils_get_param_float(float *output, const char *param_name,
57 const char *device_dir, const char *name,
58 const char *generic_name);
59void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt);
60int build_channel_array(const char *device_dir,
61 struct iio_channel_info **ci_array, int *counter);
62int find_type_by_name(const char *name, const char *type);
63int write_sysfs_int(char *filename, char *basedir, int val);
64int write_sysfs_int_and_verify(char *filename, char *basedir, int val);
65int write_sysfs_string_and_verify(char *filename, char *basedir, char *val);
66int write_sysfs_string(char *filename, char *basedir, char *val);
67int read_sysfs_posint(char *filename, char *basedir);
68int read_sysfs_float(char *filename, char *basedir, float *val);
69int read_sysfs_string(const char *filename, const char *basedir, char *str);
70
71#endif /* _IIO_UTILS_H_ */
diff --git a/tools/iio/lsiio.c b/tools/iio/lsiio.c
new file mode 100644
index 000000000000..c585440f864e
--- /dev/null
+++ b/tools/iio/lsiio.c
@@ -0,0 +1,158 @@
1/*
2 * Industrial I/O utilities - lsiio.c
3 *
4 * Copyright (c) 2010 Manuel Stahl <manuel.stahl@iis.fraunhofer.de>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#include <string.h>
12#include <dirent.h>
13#include <stdio.h>
14#include <errno.h>
15#include <stdint.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <sys/dir.h>
21#include "iio_utils.h"
22
23
24static enum verbosity {
25 VERBLEVEL_DEFAULT, /* 0 gives lspci behaviour */
26 VERBLEVEL_SENSORS, /* 1 lists sensors */
27} verblevel = VERBLEVEL_DEFAULT;
28
29const char *type_device = "iio:device";
30const char *type_trigger = "trigger";
31
32
33static inline int check_prefix(const char *str, const char *prefix)
34{
35 return strlen(str) > strlen(prefix) &&
36 strncmp(str, prefix, strlen(prefix)) == 0;
37}
38
39static inline int check_postfix(const char *str, const char *postfix)
40{
41 return strlen(str) > strlen(postfix) &&
42 strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
43}
44
45static int dump_channels(const char *dev_dir_name)
46{
47 DIR *dp;
48 const struct dirent *ent;
49
50 dp = opendir(dev_dir_name);
51 if (dp == NULL)
52 return -errno;
53 while (ent = readdir(dp), ent != NULL)
54 if (check_prefix(ent->d_name, "in_") &&
55 check_postfix(ent->d_name, "_raw")) {
56 printf(" %-10s\n", ent->d_name);
57 }
58
59 return 0;
60}
61
62static int dump_one_device(const char *dev_dir_name)
63{
64 char name[IIO_MAX_NAME_LENGTH];
65 int dev_idx;
66 int retval;
67
68 retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device),
69 "%i", &dev_idx);
70 if (retval != 1)
71 return -EINVAL;
72 read_sysfs_string("name", dev_dir_name, name);
73 printf("Device %03d: %s\n", dev_idx, name);
74
75 if (verblevel >= VERBLEVEL_SENSORS)
76 return dump_channels(dev_dir_name);
77 return 0;
78}
79
80static int dump_one_trigger(const char *dev_dir_name)
81{
82 char name[IIO_MAX_NAME_LENGTH];
83 int dev_idx;
84 int retval;
85
86 retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
87 "%i", &dev_idx);
88 if (retval != 1)
89 return -EINVAL;
90 read_sysfs_string("name", dev_dir_name, name);
91 printf("Trigger %03d: %s\n", dev_idx, name);
92 return 0;
93}
94
95static void dump_devices(void)
96{
97 const struct dirent *ent;
98 DIR *dp;
99
100 dp = opendir(iio_dir);
101 if (dp == NULL) {
102 printf("No industrial I/O devices available\n");
103 return;
104 }
105
106 while (ent = readdir(dp), ent != NULL) {
107 if (check_prefix(ent->d_name, type_device)) {
108 char *dev_dir_name;
109
110 asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
111 dump_one_device(dev_dir_name);
112 free(dev_dir_name);
113 if (verblevel >= VERBLEVEL_SENSORS)
114 printf("\n");
115 }
116 }
117 rewinddir(dp);
118 while (ent = readdir(dp), ent != NULL) {
119 if (check_prefix(ent->d_name, type_trigger)) {
120 char *dev_dir_name;
121
122 asprintf(&dev_dir_name, "%s%s", iio_dir, ent->d_name);
123 dump_one_trigger(dev_dir_name);
124 free(dev_dir_name);
125 }
126 }
127 closedir(dp);
128}
129
130int main(int argc, char **argv)
131{
132 int c, err = 0;
133
134 while ((c = getopt(argc, argv, "d:D:v")) != EOF) {
135 switch (c) {
136 case 'v':
137 verblevel++;
138 break;
139
140 case '?':
141 default:
142 err++;
143 break;
144 }
145 }
146 if (err || argc > optind) {
147 fprintf(stderr, "Usage: lsiio [options]...\n"
148 "List industrial I/O devices\n"
149 " -v, --verbose\n"
150 " Increase verbosity (may be given multiple times)\n"
151 );
152 exit(1);
153 }
154
155 dump_devices();
156
157 return 0;
158}
diff --git a/tools/lib/api/Build b/tools/lib/api/Build
new file mode 100644
index 000000000000..3653965cf481
--- /dev/null
+++ b/tools/lib/api/Build
@@ -0,0 +1,2 @@
1libapi-y += fd/
2libapi-y += fs/
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index 36c08b1f4afb..d8fe29fc19a4 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -1,49 +1,43 @@
1include ../../scripts/Makefile.include 1include ../../scripts/Makefile.include
2include ../../perf/config/utilities.mak # QUIET_CLEAN 2include ../../perf/config/utilities.mak # QUIET_CLEAN
3 3
4ifeq ($(srctree),)
5srctree := $(patsubst %/,%,$(dir $(shell pwd)))
6srctree := $(patsubst %/,%,$(dir $(srctree)))
7srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree))
9endif
10
4CC = $(CROSS_COMPILE)gcc 11CC = $(CROSS_COMPILE)gcc
5AR = $(CROSS_COMPILE)ar 12AR = $(CROSS_COMPILE)ar
6 13
7# guard against environment variables 14MAKEFLAGS += --no-print-directory
8LIB_H=
9LIB_OBJS=
10
11LIB_H += fs/debugfs.h
12LIB_H += fs/fs.h
13# See comment below about piggybacking...
14LIB_H += fd/array.h
15
16LIB_OBJS += $(OUTPUT)fs/debugfs.o
17LIB_OBJS += $(OUTPUT)fs/fs.o
18# XXX piggybacking here, need to introduce libapikfd, or rename this
19# to plain libapik.a and make it have it all api goodies
20LIB_OBJS += $(OUTPUT)fd/array.o
21 15
22LIBFILE = libapikfs.a 16LIBFILE = $(OUTPUT)libapi.a
23 17
24CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC 18CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
25EXTLIBS = -lelf -lpthread -lrt -lm 19CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 -fPIC
26ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 20CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
27ALL_LDFLAGS = $(LDFLAGS)
28 21
29RM = rm -f 22RM = rm -f
30 23
31$(LIBFILE): $(LIB_OBJS) 24build := -f $(srctree)/tools/build/Makefile.build dir=. obj
32 $(QUIET_AR)$(RM) $@ && $(AR) rcs $(OUTPUT)$@ $(LIB_OBJS) 25API_IN := $(OUTPUT)libapi-in.o
33 26
34$(LIB_OBJS): $(LIB_H) 27export srctree OUTPUT CC LD CFLAGS V
35 28
36libapi_dirs: 29all: $(LIBFILE)
37 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs
38 30
39$(OUTPUT)%.o: %.c libapi_dirs 31$(API_IN): FORCE
40 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 32 @$(MAKE) $(build)=libapi
41$(OUTPUT)%.s: %.c libapi_dirs 33
42 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< 34$(LIBFILE): $(API_IN)
43$(OUTPUT)%.o: %.S libapi_dirs 35 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(API_IN)
44 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
45 36
46clean: 37clean:
47 $(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE) 38 $(call QUIET_CLEAN, libapi) $(RM) $(LIBFILE); \
39 find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o | xargs $(RM)
40
41FORCE:
48 42
49.PHONY: clean 43.PHONY: clean FORCE
diff --git a/tools/lib/api/fd/Build b/tools/lib/api/fd/Build
new file mode 100644
index 000000000000..605d99f6d71a
--- /dev/null
+++ b/tools/lib/api/fd/Build
@@ -0,0 +1 @@
libapi-y += array.o
diff --git a/tools/lib/api/fs/Build b/tools/lib/api/fs/Build
new file mode 100644
index 000000000000..6de5a4f0b501
--- /dev/null
+++ b/tools/lib/api/fs/Build
@@ -0,0 +1,4 @@
1libapi-y += fs.o
2libapi-y += debugfs.o
3libapi-y += findfs.o
4libapi-y += tracefs.o
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
index d2b18e887071..8305b3e9d48e 100644
--- a/tools/lib/api/fs/debugfs.c
+++ b/tools/lib/api/fs/debugfs.c
@@ -3,75 +3,50 @@
3#include <stdio.h> 3#include <stdio.h>
4#include <stdlib.h> 4#include <stdlib.h>
5#include <string.h> 5#include <string.h>
6#include <unistd.h>
6#include <stdbool.h> 7#include <stdbool.h>
7#include <sys/vfs.h> 8#include <sys/vfs.h>
9#include <sys/types.h>
10#include <sys/stat.h>
8#include <sys/mount.h> 11#include <sys/mount.h>
9#include <linux/kernel.h> 12#include <linux/kernel.h>
10 13
11#include "debugfs.h" 14#include "debugfs.h"
12 15
13char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; 16#ifndef DEBUGFS_DEFAULT_PATH
17#define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
18#endif
19
20char debugfs_mountpoint[PATH_MAX + 1] = DEBUGFS_DEFAULT_PATH;
14 21
15static const char * const debugfs_known_mountpoints[] = { 22static const char * const debugfs_known_mountpoints[] = {
16 "/sys/kernel/debug", 23 DEBUGFS_DEFAULT_PATH,
17 "/debug", 24 "/debug",
18 0, 25 0,
19}; 26};
20 27
21static bool debugfs_found; 28static bool debugfs_found;
22 29
30bool debugfs_configured(void)
31{
32 return debugfs_find_mountpoint() != NULL;
33}
34
23/* find the path to the mounted debugfs */ 35/* find the path to the mounted debugfs */
24const char *debugfs_find_mountpoint(void) 36const char *debugfs_find_mountpoint(void)
25{ 37{
26 const char * const *ptr; 38 const char *ret;
27 char type[100];
28 FILE *fp;
29 39
30 if (debugfs_found) 40 if (debugfs_found)
31 return (const char *)debugfs_mountpoint; 41 return (const char *)debugfs_mountpoint;
32 42
33 ptr = debugfs_known_mountpoints; 43 ret = find_mountpoint("debugfs", (long) DEBUGFS_MAGIC,
34 while (*ptr) { 44 debugfs_mountpoint, PATH_MAX + 1,
35 if (debugfs_valid_mountpoint(*ptr) == 0) { 45 debugfs_known_mountpoints);
36 debugfs_found = true; 46 if (ret)
37 strcpy(debugfs_mountpoint, *ptr); 47 debugfs_found = true;
38 return debugfs_mountpoint;
39 }
40 ptr++;
41 }
42
43 /* give up and parse /proc/mounts */
44 fp = fopen("/proc/mounts", "r");
45 if (fp == NULL)
46 return NULL;
47
48 while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
49 debugfs_mountpoint, type) == 2) {
50 if (strcmp(type, "debugfs") == 0)
51 break;
52 }
53 fclose(fp);
54 48
55 if (strcmp(type, "debugfs") != 0) 49 return ret;
56 return NULL;
57
58 debugfs_found = true;
59
60 return debugfs_mountpoint;
61}
62
63/* verify that a mountpoint is actually a debugfs instance */
64
65int debugfs_valid_mountpoint(const char *debugfs)
66{
67 struct statfs st_fs;
68
69 if (statfs(debugfs, &st_fs) < 0)
70 return -ENOENT;
71 else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC)
72 return -ENOENT;
73
74 return 0;
75} 50}
76 51
77/* mount the debugfs somewhere if it's not mounted */ 52/* mount the debugfs somewhere if it's not mounted */
@@ -87,7 +62,7 @@ char *debugfs_mount(const char *mountpoint)
87 mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT); 62 mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
88 /* if no environment variable, use default */ 63 /* if no environment variable, use default */
89 if (mountpoint == NULL) 64 if (mountpoint == NULL)
90 mountpoint = "/sys/kernel/debug"; 65 mountpoint = DEBUGFS_DEFAULT_PATH;
91 } 66 }
92 67
93 if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) 68 if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
diff --git a/tools/lib/api/fs/debugfs.h b/tools/lib/api/fs/debugfs.h
index 0739881a9897..455023698d2b 100644
--- a/tools/lib/api/fs/debugfs.h
+++ b/tools/lib/api/fs/debugfs.h
@@ -1,16 +1,7 @@
1#ifndef __API_DEBUGFS_H__ 1#ifndef __API_DEBUGFS_H__
2#define __API_DEBUGFS_H__ 2#define __API_DEBUGFS_H__
3 3
4#define _STR(x) #x 4#include "findfs.h"
5#define STR(x) _STR(x)
6
7/*
8 * On most systems <limits.h> would have given us this, but not on some systems
9 * (e.g. GNU/Hurd).
10 */
11#ifndef PATH_MAX
12#define PATH_MAX 4096
13#endif
14 5
15#ifndef DEBUGFS_MAGIC 6#ifndef DEBUGFS_MAGIC
16#define DEBUGFS_MAGIC 0x64626720 7#define DEBUGFS_MAGIC 0x64626720
@@ -20,8 +11,8 @@
20#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" 11#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
21#endif 12#endif
22 13
14bool debugfs_configured(void);
23const char *debugfs_find_mountpoint(void); 15const char *debugfs_find_mountpoint(void);
24int debugfs_valid_mountpoint(const char *debugfs);
25char *debugfs_mount(const char *mountpoint); 16char *debugfs_mount(const char *mountpoint);
26 17
27extern char debugfs_mountpoint[]; 18extern char debugfs_mountpoint[];
diff --git a/tools/lib/api/fs/findfs.c b/tools/lib/api/fs/findfs.c
new file mode 100644
index 000000000000..49946cb6d7af
--- /dev/null
+++ b/tools/lib/api/fs/findfs.c
@@ -0,0 +1,63 @@
1#include <errno.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <stdbool.h>
6#include <sys/vfs.h>
7
8#include "findfs.h"
9
10/* verify that a mountpoint is actually the type we want */
11
12int valid_mountpoint(const char *mount, long magic)
13{
14 struct statfs st_fs;
15
16 if (statfs(mount, &st_fs) < 0)
17 return -ENOENT;
18 else if ((long)st_fs.f_type != magic)
19 return -ENOENT;
20
21 return 0;
22}
23
24/* find the path to a mounted file system */
25const char *find_mountpoint(const char *fstype, long magic,
26 char *mountpoint, int len,
27 const char * const *known_mountpoints)
28{
29 const char * const *ptr;
30 char format[128];
31 char type[100];
32 FILE *fp;
33
34 if (known_mountpoints) {
35 ptr = known_mountpoints;
36 while (*ptr) {
37 if (valid_mountpoint(*ptr, magic) == 0) {
38 strncpy(mountpoint, *ptr, len - 1);
39 mountpoint[len-1] = 0;
40 return mountpoint;
41 }
42 ptr++;
43 }
44 }
45
46 /* give up and parse /proc/mounts */
47 fp = fopen("/proc/mounts", "r");
48 if (fp == NULL)
49 return NULL;
50
51 snprintf(format, 128, "%%*s %%%ds %%99s %%*s %%*d %%*d\n", len);
52
53 while (fscanf(fp, format, mountpoint, type) == 2) {
54 if (strcmp(type, fstype) == 0)
55 break;
56 }
57 fclose(fp);
58
59 if (strcmp(type, fstype) != 0)
60 return NULL;
61
62 return mountpoint;
63}
diff --git a/tools/lib/api/fs/findfs.h b/tools/lib/api/fs/findfs.h
new file mode 100644
index 000000000000..b6f5d05acc42
--- /dev/null
+++ b/tools/lib/api/fs/findfs.h
@@ -0,0 +1,23 @@
1#ifndef __API_FINDFS_H__
2#define __API_FINDFS_H__
3
4#include <stdbool.h>
5
6#define _STR(x) #x
7#define STR(x) _STR(x)
8
9/*
10 * On most systems <limits.h> would have given us this, but not on some systems
11 * (e.g. GNU/Hurd).
12 */
13#ifndef PATH_MAX
14#define PATH_MAX 4096
15#endif
16
17const char *find_mountpoint(const char *fstype, long magic,
18 char *mountpoint, int len,
19 const char * const *known_mountpoints);
20
21int valid_mountpoint(const char *mount, long magic);
22
23#endif /* __API_FINDFS_H__ */
diff --git a/tools/lib/api/fs/tracefs.c b/tools/lib/api/fs/tracefs.c
new file mode 100644
index 000000000000..e4aa9688b71e
--- /dev/null
+++ b/tools/lib/api/fs/tracefs.c
@@ -0,0 +1,78 @@
1#include <errno.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <unistd.h>
6#include <stdbool.h>
7#include <sys/vfs.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <sys/mount.h>
11#include <linux/kernel.h>
12
13#include "tracefs.h"
14
15#ifndef TRACEFS_DEFAULT_PATH
16#define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
17#endif
18
19char tracefs_mountpoint[PATH_MAX + 1] = TRACEFS_DEFAULT_PATH;
20
21static const char * const tracefs_known_mountpoints[] = {
22 TRACEFS_DEFAULT_PATH,
23 "/sys/kernel/debug/tracing",
24 "/tracing",
25 "/trace",
26 0,
27};
28
29static bool tracefs_found;
30
31bool tracefs_configured(void)
32{
33 return tracefs_find_mountpoint() != NULL;
34}
35
36/* find the path to the mounted tracefs */
37const char *tracefs_find_mountpoint(void)
38{
39 const char *ret;
40
41 if (tracefs_found)
42 return (const char *)tracefs_mountpoint;
43
44 ret = find_mountpoint("tracefs", (long) TRACEFS_MAGIC,
45 tracefs_mountpoint, PATH_MAX + 1,
46 tracefs_known_mountpoints);
47
48 if (ret)
49 tracefs_found = true;
50
51 return ret;
52}
53
54/* mount the tracefs somewhere if it's not mounted */
55char *tracefs_mount(const char *mountpoint)
56{
57 /* see if it's already mounted */
58 if (tracefs_find_mountpoint())
59 goto out;
60
61 /* if not mounted and no argument */
62 if (mountpoint == NULL) {
63 /* see if environment variable set */
64 mountpoint = getenv(PERF_TRACEFS_ENVIRONMENT);
65 /* if no environment variable, use default */
66 if (mountpoint == NULL)
67 mountpoint = TRACEFS_DEFAULT_PATH;
68 }
69
70 if (mount(NULL, mountpoint, "tracefs", 0, NULL) < 0)
71 return NULL;
72
73 /* save the mountpoint */
74 tracefs_found = true;
75 strncpy(tracefs_mountpoint, mountpoint, sizeof(tracefs_mountpoint));
76out:
77 return tracefs_mountpoint;
78}
diff --git a/tools/lib/api/fs/tracefs.h b/tools/lib/api/fs/tracefs.h
new file mode 100644
index 000000000000..da780ac49acb
--- /dev/null
+++ b/tools/lib/api/fs/tracefs.h
@@ -0,0 +1,21 @@
1#ifndef __API_TRACEFS_H__
2#define __API_TRACEFS_H__
3
4#include "findfs.h"
5
6#ifndef TRACEFS_MAGIC
7#define TRACEFS_MAGIC 0x74726163
8#endif
9
10#ifndef PERF_TRACEFS_ENVIRONMENT
11#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
12#endif
13
14bool tracefs_configured(void);
15const char *tracefs_find_mountpoint(void);
16int tracefs_valid_mountpoint(const char *debugfs);
17char *tracefs_mount(const char *mountpoint);
18
19extern char tracefs_mountpoint[];
20
21#endif /* __API_DEBUGFS_H__ */
diff --git a/tools/lib/lockdep/Build b/tools/lib/lockdep/Build
new file mode 100644
index 000000000000..6f667355b068
--- /dev/null
+++ b/tools/lib/lockdep/Build
@@ -0,0 +1 @@
liblockdep-y += common.o lockdep.o preload.o rbtree.o
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 4b866c54f624..0c356fb65022 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -35,6 +35,10 @@ bindir = $(prefix)/$(bindir_relative)
35 35
36export DESTDIR DESTDIR_SQ INSTALL 36export DESTDIR DESTDIR_SQ INSTALL
37 37
38MAKEFLAGS += --no-print-directory
39
40include ../../scripts/Makefile.include
41
38# copy a bit from Linux kbuild 42# copy a bit from Linux kbuild
39 43
40ifeq ("$(origin V)", "command line") 44ifeq ("$(origin V)", "command line")
@@ -44,56 +48,21 @@ ifndef VERBOSE
44 VERBOSE = 0 48 VERBOSE = 0
45endif 49endif
46 50
47ifeq ("$(origin O)", "command line") 51ifeq ($(srctree),)
48 BUILD_OUTPUT := $(O) 52srctree := $(patsubst %/,%,$(dir $(shell pwd)))
53srctree := $(patsubst %/,%,$(dir $(srctree)))
54srctree := $(patsubst %/,%,$(dir $(srctree)))
55#$(info Determined 'srctree' to be $(srctree))
49endif 56endif
50 57
51ifeq ($(BUILD_SRC),)
52ifneq ($(BUILD_OUTPUT),)
53
54define build_output
55 $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
56 BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
57endef
58
59saved-output := $(BUILD_OUTPUT)
60BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
61$(if $(BUILD_OUTPUT),, \
62 $(error output directory "$(saved-output)" does not exist))
63
64all: sub-make
65
66gui: force
67 $(call build_output, all_cmd)
68
69$(filter-out gui,$(MAKECMDGOALS)): sub-make
70
71sub-make: force
72 $(call build_output, $(MAKECMDGOALS))
73
74
75# Leave processing to above invocation of make
76skip-makefile := 1
77
78endif # BUILD_OUTPUT
79endif # BUILD_SRC
80
81# We process the rest of the Makefile if this is the final invocation of make
82ifeq ($(skip-makefile),)
83
84srctree := $(realpath $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)))
85objtree := $(realpath $(CURDIR))
86src := $(srctree)
87obj := $(objtree)
88
89export prefix libdir bindir src obj
90
91# Shell quotes 58# Shell quotes
92libdir_SQ = $(subst ','\'',$(libdir)) 59libdir_SQ = $(subst ','\'',$(libdir))
93bindir_SQ = $(subst ','\'',$(bindir)) 60bindir_SQ = $(subst ','\'',$(bindir))
94 61
95LIB_FILE = liblockdep.a liblockdep.so.$(LIBLOCKDEP_VERSION) 62LIB_IN := $(OUTPUT)liblockdep-in.o
63
96BIN_FILE = lockdep 64BIN_FILE = lockdep
65LIB_FILE = $(OUTPUT)liblockdep.a $(OUTPUT)liblockdep.so.$(LIBLOCKDEP_VERSION)
97 66
98CONFIG_INCLUDES = 67CONFIG_INCLUDES =
99CONFIG_LIBS = 68CONFIG_LIBS =
@@ -108,33 +77,23 @@ INCLUDES = -I. -I./uinclude -I./include -I../../include $(CONFIG_INCLUDES)
108 77
109# Set compile option CFLAGS if not set elsewhere 78# Set compile option CFLAGS if not set elsewhere
110CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g 79CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
80CFLAGS += -fPIC
111 81
112override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 82override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
113 83
114ifeq ($(VERBOSE),1) 84ifeq ($(VERBOSE),1)
115 Q = 85 Q =
116 print_compile =
117 print_app_build =
118 print_fpic_compile =
119 print_shared_lib_compile = 86 print_shared_lib_compile =
120 print_install = 87 print_install =
121else 88else
122 Q = @ 89 Q = @
123 print_compile = echo ' CC '$(OBJ); 90 print_shared_lib_compile = echo ' LD '$(OBJ);
124 print_app_build = echo ' BUILD '$(OBJ); 91 print_static_lib_build = echo ' LD '$(OBJ);
125 print_fpic_compile = echo ' CC FPIC '$(OBJ); 92 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
126 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
127 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
128 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
129endif 93endif
130 94
131do_fpic_compile = \ 95export srctree OUTPUT CC LD CFLAGS V
132 ($(print_fpic_compile) \ 96build := -f $(srctree)/tools/build/Makefile.build dir=. obj
133 $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
134
135do_app_build = \
136 ($(print_app_build) \
137 $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
138 97
139do_compile_shared_library = \ 98do_compile_shared_library = \
140 ($(print_shared_lib_compile) \ 99 ($(print_shared_lib_compile) \
@@ -144,22 +103,6 @@ do_build_static_lib = \
144 ($(print_static_lib_build) \ 103 ($(print_static_lib_build) \
145 $(RM) $@; $(AR) rcs $@ $^) 104 $(RM) $@; $(AR) rcs $@ $^)
146 105
147
148define do_compile
149 $(print_compile) \
150 $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
151endef
152
153$(obj)/%.o: $(src)/%.c
154 $(Q)$(call do_compile)
155
156%.o: $(src)/%.c
157 $(Q)$(call do_compile)
158
159PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o
160
161ALL_OBJS = $(PEVENT_LIB_OBJS)
162
163CMD_TARGETS = $(LIB_FILE) 106CMD_TARGETS = $(LIB_FILE)
164 107
165TARGETS = $(CMD_TARGETS) 108TARGETS = $(CMD_TARGETS)
@@ -169,42 +112,15 @@ all: all_cmd
169 112
170all_cmd: $(CMD_TARGETS) 113all_cmd: $(CMD_TARGETS)
171 114
172liblockdep.so.$(LIBLOCKDEP_VERSION): $(PEVENT_LIB_OBJS) 115$(LIB_IN): force
116 $(Q)$(MAKE) $(build)=liblockdep
117
118liblockdep.so.$(LIBLOCKDEP_VERSION): $(LIB_IN)
173 $(Q)$(do_compile_shared_library) 119 $(Q)$(do_compile_shared_library)
174 120
175liblockdep.a: $(PEVENT_LIB_OBJS) 121liblockdep.a: $(LIB_IN)
176 $(Q)$(do_build_static_lib) 122 $(Q)$(do_build_static_lib)
177 123
178$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
179 $(Q)$(do_fpic_compile)
180
181## make deps
182
183all_objs := $(sort $(ALL_OBJS))
184all_deps := $(all_objs:%.o=.%.d)
185
186# let .d file also depends on the source and header files
187define check_deps
188 @set -e; $(RM) $@; \
189 $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
190 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
191 $(RM) $@.$$$$
192endef
193
194$(all_deps): .%.d: $(src)/%.c
195 $(Q)$(call check_deps)
196
197$(all_objs) : %.o : .%.d
198
199dep_includes := $(wildcard $(all_deps))
200
201ifneq ($(dep_includes),)
202 include $(dep_includes)
203endif
204
205### Detect environment changes
206TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
207
208tags: force 124tags: force
209 $(RM) tags 125 $(RM) tags
210 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ 126 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -233,8 +149,6 @@ clean:
233 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d 149 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d
234 $(RM) tags TAGS 150 $(RM) tags TAGS
235 151
236endif # skip-makefile
237
238PHONY += force 152PHONY += force
239force: 153force:
240 154
diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build
new file mode 100644
index 000000000000..c681d0575d16
--- /dev/null
+++ b/tools/lib/traceevent/Build
@@ -0,0 +1,17 @@
1libtraceevent-y += event-parse.o
2libtraceevent-y += event-plugin.o
3libtraceevent-y += trace-seq.o
4libtraceevent-y += parse-filter.o
5libtraceevent-y += parse-utils.o
6libtraceevent-y += kbuffer-parse.o
7
8plugin_jbd2-y += plugin_jbd2.o
9plugin_hrtimer-y += plugin_hrtimer.o
10plugin_kmem-y += plugin_kmem.o
11plugin_kvm-y += plugin_kvm.o
12plugin_mac80211-y += plugin_mac80211.o
13plugin_sched_switch-y += plugin_sched_switch.o
14plugin_function-y += plugin_function.o
15plugin_xen-y += plugin_xen.o
16plugin_scsi-y += plugin_scsi.o
17plugin_cfg80211-y += plugin_cfg80211.o
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 005c9cc06935..d410da335e3d 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -67,7 +67,7 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)"
67PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' 67PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
68endif 68endif
69 69
70include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include 70include ../../scripts/Makefile.include
71 71
72# copy a bit from Linux kbuild 72# copy a bit from Linux kbuild
73 73
@@ -78,40 +78,13 @@ ifndef VERBOSE
78 VERBOSE = 0 78 VERBOSE = 0
79endif 79endif
80 80
81ifeq ("$(origin O)", "command line") 81ifeq ($(srctree),)
82 BUILD_OUTPUT := $(O) 82srctree := $(patsubst %/,%,$(dir $(shell pwd)))
83srctree := $(patsubst %/,%,$(dir $(srctree)))
84srctree := $(patsubst %/,%,$(dir $(srctree)))
85#$(info Determined 'srctree' to be $(srctree))
83endif 86endif
84 87
85ifeq ($(BUILD_SRC),)
86ifneq ($(OUTPUT),)
87
88define build_output
89 $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \
90 BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1
91endef
92
93all: sub-make
94
95$(MAKECMDGOALS): sub-make
96
97sub-make: force
98 $(call build_output, $(MAKECMDGOALS))
99
100
101# Leave processing to above invocation of make
102skip-makefile := 1
103
104endif # OUTPUT
105endif # BUILD_SRC
106
107# We process the rest of the Makefile if this is the final invocation of make
108ifeq ($(skip-makefile),)
109
110srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
111objtree := $(CURDIR)
112src := $(srctree)
113obj := $(objtree)
114
115export prefix bindir src obj 88export prefix bindir src obj
116 89
117# Shell quotes 90# Shell quotes
@@ -132,16 +105,19 @@ EXTRAVERSION = $(EP_EXTRAVERSION)
132OBJ = $@ 105OBJ = $@
133N = 106N =
134 107
135export Q VERBOSE
136
137EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) 108EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
138 109
139INCLUDES = -I. -I $(srctree)/../../include $(CONFIG_INCLUDES) 110INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
140 111
141# Set compile option CFLAGS if not set elsewhere 112# Set compile option CFLAGS
142CFLAGS ?= -g -Wall 113ifdef EXTRA_CFLAGS
114 CFLAGS := $(EXTRA_CFLAGS)
115else
116 CFLAGS := -g -Wall
117endif
143 118
144# Append required CFLAGS 119# Append required CFLAGS
120override CFLAGS += -fPIC
145override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 121override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
146override CFLAGS += $(udis86-flags) -D_GNU_SOURCE 122override CFLAGS += $(udis86-flags) -D_GNU_SOURCE
147 123
@@ -151,74 +127,58 @@ else
151 Q = @ 127 Q = @
152endif 128endif
153 129
154do_compile_shared_library = \ 130# Disable command line variables (CFLAGS) overide from top
155 ($(print_shared_lib_compile) \ 131# level Makefile (perf), otherwise build Makefile will get
156 $(CC) --shared $^ -o $@) 132# the same command line setup.
157 133MAKEOVERRIDES=
158do_plugin_build = \
159 ($(print_plugin_build) \
160 $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
161
162do_build_static_lib = \
163 ($(print_static_lib_build) \
164 $(RM) $@; $(AR) rcs $@ $^)
165
166
167do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
168 134
169$(obj)/%.o: $(src)/%.c 135export srctree OUTPUT CC LD CFLAGS V
170 $(call do_compile) 136build := -f $(srctree)/tools/build/Makefile.build dir=. obj
171 137
172%.o: $(src)/%.c 138PLUGINS = plugin_jbd2.so
173 $(call do_compile) 139PLUGINS += plugin_hrtimer.so
140PLUGINS += plugin_kmem.so
141PLUGINS += plugin_kvm.so
142PLUGINS += plugin_mac80211.so
143PLUGINS += plugin_sched_switch.so
144PLUGINS += plugin_function.so
145PLUGINS += plugin_xen.so
146PLUGINS += plugin_scsi.so
147PLUGINS += plugin_cfg80211.so
174 148
175PEVENT_LIB_OBJS = event-parse.o 149PLUGINS := $(addprefix $(OUTPUT),$(PLUGINS))
176PEVENT_LIB_OBJS += event-plugin.o 150PLUGINS_IN := $(PLUGINS:.so=-in.o)
177PEVENT_LIB_OBJS += trace-seq.o
178PEVENT_LIB_OBJS += parse-filter.o
179PEVENT_LIB_OBJS += parse-utils.o
180PEVENT_LIB_OBJS += kbuffer-parse.o
181 151
182PLUGIN_OBJS = plugin_jbd2.o 152TE_IN := $(OUTPUT)libtraceevent-in.o
183PLUGIN_OBJS += plugin_hrtimer.o 153LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
184PLUGIN_OBJS += plugin_kmem.o
185PLUGIN_OBJS += plugin_kvm.o
186PLUGIN_OBJS += plugin_mac80211.o
187PLUGIN_OBJS += plugin_sched_switch.o
188PLUGIN_OBJS += plugin_function.o
189PLUGIN_OBJS += plugin_xen.o
190PLUGIN_OBJS += plugin_scsi.o
191PLUGIN_OBJS += plugin_cfg80211.o
192
193PLUGINS := $(PLUGIN_OBJS:.o=.so)
194
195ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS)
196 154
197CMD_TARGETS = $(LIB_FILE) $(PLUGINS) 155CMD_TARGETS = $(LIB_FILE) $(PLUGINS)
198 156
199TARGETS = $(CMD_TARGETS) 157TARGETS = $(CMD_TARGETS)
200 158
201
202all: all_cmd 159all: all_cmd
203 160
204all_cmd: $(CMD_TARGETS) 161all_cmd: $(CMD_TARGETS)
205 162
206libtraceevent.so: $(PEVENT_LIB_OBJS) 163$(TE_IN): force
164 $(Q)$(MAKE) $(build)=libtraceevent
165
166$(OUTPUT)libtraceevent.so: $(TE_IN)
207 $(QUIET_LINK)$(CC) --shared $^ -o $@ 167 $(QUIET_LINK)$(CC) --shared $^ -o $@
208 168
209libtraceevent.a: $(PEVENT_LIB_OBJS) 169$(OUTPUT)libtraceevent.a: $(TE_IN)
210 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ 170 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
211 171
212plugins: $(PLUGINS) 172plugins: $(PLUGINS)
213 173
214$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS 174__plugin_obj = $(notdir $@)
215 $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@ 175 plugin_obj = $(__plugin_obj:-in.o=)
216 176
217$(PLUGIN_OBJS): %.o : $(src)/%.c 177$(PLUGINS_IN): force
218 $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< 178 $(Q)$(MAKE) $(build)=$(plugin_obj)
219 179
220$(PLUGINS): %.so: %.o 180$(OUTPUT)%.so: $(OUTPUT)%-in.o
221 $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< 181 $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $^
222 182
223define make_version.h 183define make_version.h
224 (echo '/* This file is automatically generated. Do not modify. */'; \ 184 (echo '/* This file is automatically generated. Do not modify. */'; \
@@ -255,40 +215,6 @@ define update_dir
255 fi); 215 fi);
256endef 216endef
257 217
258## make deps
259
260all_objs := $(sort $(ALL_OBJS))
261all_deps := $(all_objs:%.o=.%.d)
262
263# let .d file also depends on the source and header files
264define check_deps
265 @set -e; $(RM) $@; \
266 $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
267 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
268 $(RM) $@.$$$$
269endef
270
271$(all_deps): .%.d: $(src)/%.c
272 $(Q)$(call check_deps)
273
274$(all_objs) : %.o : .%.d
275
276dep_includes := $(wildcard $(all_deps))
277
278ifneq ($(dep_includes),)
279 include $(dep_includes)
280endif
281
282### Detect environment changes
283TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
284
285TRACEEVENT-CFLAGS: force
286 @FLAGS='$(TRACK_CFLAGS)'; \
287 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
288 echo 1>&2 " FLAGS: * new build flags or cross compiler"; \
289 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
290 fi
291
292tags: force 218tags: force
293 $(RM) tags 219 $(RM) tags
294 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ 220 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -327,14 +253,9 @@ clean:
327 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ 253 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
328 $(RM) TRACEEVENT-CFLAGS tags TAGS 254 $(RM) TRACEEVENT-CFLAGS tags TAGS
329 255
330endif # skip-makefile
331
332PHONY += force plugins 256PHONY += force plugins
333force: 257force:
334 258
335plugins:
336 @echo > /dev/null
337
338# Declare the contents of the .PHONY variable as phony. We keep that 259# Declare the contents of the .PHONY variable as phony. We keep that
339# information in a variable so we can use it in if_changed and friends. 260# information in a variable so we can use it in if_changed and friends.
340.PHONY: $(PHONY) 261.PHONY: $(PHONY)
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index afe20ed9fac8..e0917c0f5d9f 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -304,7 +304,10 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
304 if (!item) 304 if (!item)
305 return -1; 305 return -1;
306 306
307 item->comm = strdup(comm); 307 if (comm)
308 item->comm = strdup(comm);
309 else
310 item->comm = strdup("<...>");
308 if (!item->comm) { 311 if (!item->comm) {
309 free(item); 312 free(item);
310 return -1; 313 return -1;
@@ -318,9 +321,14 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
318 return 0; 321 return 0;
319} 322}
320 323
321void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock) 324int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock)
322{ 325{
323 pevent->trace_clock = trace_clock; 326 pevent->trace_clock = strdup(trace_clock);
327 if (!pevent->trace_clock) {
328 errno = ENOMEM;
329 return -1;
330 }
331 return 0;
324} 332}
325 333
326struct func_map { 334struct func_map {
@@ -758,6 +766,11 @@ static void free_arg(struct print_arg *arg)
758 free_arg(arg->hex.field); 766 free_arg(arg->hex.field);
759 free_arg(arg->hex.size); 767 free_arg(arg->hex.size);
760 break; 768 break;
769 case PRINT_INT_ARRAY:
770 free_arg(arg->int_array.field);
771 free_arg(arg->int_array.count);
772 free_arg(arg->int_array.el_size);
773 break;
761 case PRINT_TYPE: 774 case PRINT_TYPE:
762 free(arg->typecast.type); 775 free(arg->typecast.type);
763 free_arg(arg->typecast.item); 776 free_arg(arg->typecast.item);
@@ -1926,7 +1939,22 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
1926 goto out_warn_free; 1939 goto out_warn_free;
1927 1940
1928 type = process_arg_token(event, right, tok, type); 1941 type = process_arg_token(event, right, tok, type);
1929 arg->op.right = right; 1942
1943 if (right->type == PRINT_OP &&
1944 get_op_prio(arg->op.op) < get_op_prio(right->op.op)) {
1945 struct print_arg tmp;
1946
1947 /* rotate ops according to the priority */
1948 arg->op.right = right->op.left;
1949
1950 tmp = *arg;
1951 *arg = *right;
1952 *right = tmp;
1953
1954 arg->op.left = right;
1955 } else {
1956 arg->op.right = right;
1957 }
1930 1958
1931 } else if (strcmp(token, "[") == 0) { 1959 } else if (strcmp(token, "[") == 0) {
1932 1960
@@ -2014,6 +2042,38 @@ process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
2014 return EVENT_ERROR; 2042 return EVENT_ERROR;
2015} 2043}
2016 2044
2045static int alloc_and_process_delim(struct event_format *event, char *next_token,
2046 struct print_arg **print_arg)
2047{
2048 struct print_arg *field;
2049 enum event_type type;
2050 char *token;
2051 int ret = 0;
2052
2053 field = alloc_arg();
2054 if (!field) {
2055 do_warning_event(event, "%s: not enough memory!", __func__);
2056 errno = ENOMEM;
2057 return -1;
2058 }
2059
2060 type = process_arg(event, field, &token);
2061
2062 if (test_type_token(type, token, EVENT_DELIM, next_token)) {
2063 errno = EINVAL;
2064 ret = -1;
2065 free_arg(field);
2066 goto out_free_token;
2067 }
2068
2069 *print_arg = field;
2070
2071out_free_token:
2072 free_token(token);
2073
2074 return ret;
2075}
2076
2017static char *arg_eval (struct print_arg *arg); 2077static char *arg_eval (struct print_arg *arg);
2018 2078
2019static unsigned long long 2079static unsigned long long
@@ -2486,49 +2546,46 @@ out_free:
2486static enum event_type 2546static enum event_type
2487process_hex(struct event_format *event, struct print_arg *arg, char **tok) 2547process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2488{ 2548{
2489 struct print_arg *field;
2490 enum event_type type;
2491 char *token = NULL;
2492
2493 memset(arg, 0, sizeof(*arg)); 2549 memset(arg, 0, sizeof(*arg));
2494 arg->type = PRINT_HEX; 2550 arg->type = PRINT_HEX;
2495 2551
2496 field = alloc_arg(); 2552 if (alloc_and_process_delim(event, ",", &arg->hex.field))
2497 if (!field) { 2553 goto out;
2498 do_warning_event(event, "%s: not enough memory!", __func__);
2499 goto out_free;
2500 }
2501 2554
2502 type = process_arg(event, field, &token); 2555 if (alloc_and_process_delim(event, ")", &arg->hex.size))
2556 goto free_field;
2503 2557
2504 if (test_type_token(type, token, EVENT_DELIM, ",")) 2558 return read_token_item(tok);
2505 goto out_free;
2506
2507 arg->hex.field = field;
2508 2559
2509 free_token(token); 2560free_field:
2561 free_arg(arg->hex.field);
2562out:
2563 *tok = NULL;
2564 return EVENT_ERROR;
2565}
2510 2566
2511 field = alloc_arg(); 2567static enum event_type
2512 if (!field) { 2568process_int_array(struct event_format *event, struct print_arg *arg, char **tok)
2513 do_warning_event(event, "%s: not enough memory!", __func__); 2569{
2514 *tok = NULL; 2570 memset(arg, 0, sizeof(*arg));
2515 return EVENT_ERROR; 2571 arg->type = PRINT_INT_ARRAY;
2516 }
2517 2572
2518 type = process_arg(event, field, &token); 2573 if (alloc_and_process_delim(event, ",", &arg->int_array.field))
2574 goto out;
2519 2575
2520 if (test_type_token(type, token, EVENT_DELIM, ")")) 2576 if (alloc_and_process_delim(event, ",", &arg->int_array.count))
2521 goto out_free; 2577 goto free_field;
2522 2578
2523 arg->hex.size = field; 2579 if (alloc_and_process_delim(event, ")", &arg->int_array.el_size))
2580 goto free_size;
2524 2581
2525 free_token(token); 2582 return read_token_item(tok);
2526 type = read_token_item(tok);
2527 return type;
2528 2583
2529 out_free: 2584free_size:
2530 free_arg(field); 2585 free_arg(arg->int_array.count);
2531 free_token(token); 2586free_field:
2587 free_arg(arg->int_array.field);
2588out:
2532 *tok = NULL; 2589 *tok = NULL;
2533 return EVENT_ERROR; 2590 return EVENT_ERROR;
2534} 2591}
@@ -2828,6 +2885,10 @@ process_function(struct event_format *event, struct print_arg *arg,
2828 free_token(token); 2885 free_token(token);
2829 return process_hex(event, arg, tok); 2886 return process_hex(event, arg, tok);
2830 } 2887 }
2888 if (strcmp(token, "__print_array") == 0) {
2889 free_token(token);
2890 return process_int_array(event, arg, tok);
2891 }
2831 if (strcmp(token, "__get_str") == 0) { 2892 if (strcmp(token, "__get_str") == 0) {
2832 free_token(token); 2893 free_token(token);
2833 return process_str(event, arg, tok); 2894 return process_str(event, arg, tok);
@@ -3356,6 +3417,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
3356 break; 3417 break;
3357 case PRINT_FLAGS: 3418 case PRINT_FLAGS:
3358 case PRINT_SYMBOL: 3419 case PRINT_SYMBOL:
3420 case PRINT_INT_ARRAY:
3359 case PRINT_HEX: 3421 case PRINT_HEX:
3360 break; 3422 break;
3361 case PRINT_TYPE: 3423 case PRINT_TYPE:
@@ -3568,7 +3630,7 @@ static const struct flag flags[] = {
3568 { "HRTIMER_RESTART", 1 }, 3630 { "HRTIMER_RESTART", 1 },
3569}; 3631};
3570 3632
3571static unsigned long long eval_flag(const char *flag) 3633static long long eval_flag(const char *flag)
3572{ 3634{
3573 int i; 3635 int i;
3574 3636
@@ -3584,7 +3646,7 @@ static unsigned long long eval_flag(const char *flag)
3584 if (strcmp(flags[i].name, flag) == 0) 3646 if (strcmp(flags[i].name, flag) == 0)
3585 return flags[i].value; 3647 return flags[i].value;
3586 3648
3587 return 0; 3649 return -1LL;
3588} 3650}
3589 3651
3590static void print_str_to_seq(struct trace_seq *s, const char *format, 3652static void print_str_to_seq(struct trace_seq *s, const char *format,
@@ -3658,7 +3720,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3658 struct print_flag_sym *flag; 3720 struct print_flag_sym *flag;
3659 struct format_field *field; 3721 struct format_field *field;
3660 struct printk_map *printk; 3722 struct printk_map *printk;
3661 unsigned long long val, fval; 3723 long long val, fval;
3662 unsigned long addr; 3724 unsigned long addr;
3663 char *str; 3725 char *str;
3664 unsigned char *hex; 3726 unsigned char *hex;
@@ -3717,11 +3779,11 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3717 print = 0; 3779 print = 0;
3718 for (flag = arg->flags.flags; flag; flag = flag->next) { 3780 for (flag = arg->flags.flags; flag; flag = flag->next) {
3719 fval = eval_flag(flag->value); 3781 fval = eval_flag(flag->value);
3720 if (!val && !fval) { 3782 if (!val && fval < 0) {
3721 print_str_to_seq(s, format, len_arg, flag->str); 3783 print_str_to_seq(s, format, len_arg, flag->str);
3722 break; 3784 break;
3723 } 3785 }
3724 if (fval && (val & fval) == fval) { 3786 if (fval > 0 && (val & fval) == fval) {
3725 if (print && arg->flags.delim) 3787 if (print && arg->flags.delim)
3726 trace_seq_puts(s, arg->flags.delim); 3788 trace_seq_puts(s, arg->flags.delim);
3727 print_str_to_seq(s, format, len_arg, flag->str); 3789 print_str_to_seq(s, format, len_arg, flag->str);
@@ -3766,6 +3828,54 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3766 } 3828 }
3767 break; 3829 break;
3768 3830
3831 case PRINT_INT_ARRAY: {
3832 void *num;
3833 int el_size;
3834
3835 if (arg->int_array.field->type == PRINT_DYNAMIC_ARRAY) {
3836 unsigned long offset;
3837 struct format_field *field =
3838 arg->int_array.field->dynarray.field;
3839 offset = pevent_read_number(pevent,
3840 data + field->offset,
3841 field->size);
3842 num = data + (offset & 0xffff);
3843 } else {
3844 field = arg->int_array.field->field.field;
3845 if (!field) {
3846 str = arg->int_array.field->field.name;
3847 field = pevent_find_any_field(event, str);
3848 if (!field)
3849 goto out_warning_field;
3850 arg->int_array.field->field.field = field;
3851 }
3852 num = data + field->offset;
3853 }
3854 len = eval_num_arg(data, size, event, arg->int_array.count);
3855 el_size = eval_num_arg(data, size, event,
3856 arg->int_array.el_size);
3857 for (i = 0; i < len; i++) {
3858 if (i)
3859 trace_seq_putc(s, ' ');
3860
3861 if (el_size == 1) {
3862 trace_seq_printf(s, "%u", *(uint8_t *)num);
3863 } else if (el_size == 2) {
3864 trace_seq_printf(s, "%u", *(uint16_t *)num);
3865 } else if (el_size == 4) {
3866 trace_seq_printf(s, "%u", *(uint32_t *)num);
3867 } else if (el_size == 8) {
3868 trace_seq_printf(s, "%lu", *(uint64_t *)num);
3869 } else {
3870 trace_seq_printf(s, "BAD SIZE:%d 0x%x",
3871 el_size, *(uint8_t *)num);
3872 el_size = 1;
3873 }
3874
3875 num += el_size;
3876 }
3877 break;
3878 }
3769 case PRINT_TYPE: 3879 case PRINT_TYPE:
3770 break; 3880 break;
3771 case PRINT_STRING: { 3881 case PRINT_STRING: {
@@ -3976,7 +4086,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3976 if (asprintf(&arg->atom.atom, "%lld", ip) < 0) 4086 if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
3977 goto out_free; 4087 goto out_free;
3978 4088
3979 /* skip the first "%pf: " */ 4089 /* skip the first "%ps: " */
3980 for (ptr = fmt + 5, bptr = data + field->offset; 4090 for (ptr = fmt + 5, bptr = data + field->offset;
3981 bptr < data + size && *ptr; ptr++) { 4091 bptr < data + size && *ptr; ptr++) {
3982 int ls = 0; 4092 int ls = 0;
@@ -3997,6 +4107,10 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3997 goto process_again; 4107 goto process_again;
3998 case '.': 4108 case '.':
3999 goto process_again; 4109 goto process_again;
4110 case 'z':
4111 case 'Z':
4112 ls = 1;
4113 goto process_again;
4000 case 'p': 4114 case 'p':
4001 ls = 1; 4115 ls = 1;
4002 /* fall through */ 4116 /* fall through */
@@ -4939,6 +5053,96 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
4939 return comm; 5053 return comm;
4940} 5054}
4941 5055
5056static struct cmdline *
5057pid_from_cmdlist(struct pevent *pevent, const char *comm, struct cmdline *next)
5058{
5059 struct cmdline_list *cmdlist = (struct cmdline_list *)next;
5060
5061 if (cmdlist)
5062 cmdlist = cmdlist->next;
5063 else
5064 cmdlist = pevent->cmdlist;
5065
5066 while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
5067 cmdlist = cmdlist->next;
5068
5069 return (struct cmdline *)cmdlist;
5070}
5071
5072/**
5073 * pevent_data_pid_from_comm - return the pid from a given comm
5074 * @pevent: a handle to the pevent
5075 * @comm: the cmdline to find the pid from
5076 * @next: the cmdline structure to find the next comm
5077 *
5078 * This returns the cmdline structure that holds a pid for a given
5079 * comm, or NULL if none found. As there may be more than one pid for
5080 * a given comm, the result of this call can be passed back into
5081 * a recurring call in the @next paramater, and then it will find the
5082 * next pid.
5083 * Also, it does a linear seach, so it may be slow.
5084 */
5085struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
5086 struct cmdline *next)
5087{
5088 struct cmdline *cmdline;
5089
5090 /*
5091 * If the cmdlines have not been converted yet, then use
5092 * the list.
5093 */
5094 if (!pevent->cmdlines)
5095 return pid_from_cmdlist(pevent, comm, next);
5096
5097 if (next) {
5098 /*
5099 * The next pointer could have been still from
5100 * a previous call before cmdlines were created
5101 */
5102 if (next < pevent->cmdlines ||
5103 next >= pevent->cmdlines + pevent->cmdline_count)
5104 next = NULL;
5105 else
5106 cmdline = next++;
5107 }
5108
5109 if (!next)
5110 cmdline = pevent->cmdlines;
5111
5112 while (cmdline < pevent->cmdlines + pevent->cmdline_count) {
5113 if (strcmp(cmdline->comm, comm) == 0)
5114 return cmdline;
5115 cmdline++;
5116 }
5117 return NULL;
5118}
5119
5120/**
5121 * pevent_cmdline_pid - return the pid associated to a given cmdline
5122 * @cmdline: The cmdline structure to get the pid from
5123 *
5124 * Returns the pid for a give cmdline. If @cmdline is NULL, then
5125 * -1 is returned.
5126 */
5127int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline)
5128{
5129 struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
5130
5131 if (!cmdline)
5132 return -1;
5133
5134 /*
5135 * If cmdlines have not been created yet, or cmdline is
5136 * not part of the array, then treat it as a cmdlist instead.
5137 */
5138 if (!pevent->cmdlines ||
5139 cmdline < pevent->cmdlines ||
5140 cmdline >= pevent->cmdlines + pevent->cmdline_count)
5141 return cmdlist->pid;
5142
5143 return cmdline->pid;
5144}
5145
4942/** 5146/**
4943 * pevent_data_comm_from_pid - parse the data into the print format 5147 * pevent_data_comm_from_pid - parse the data into the print format
4944 * @s: the trace_seq to write to 5148 * @s: the trace_seq to write to
@@ -5256,6 +5460,15 @@ static void print_args(struct print_arg *args)
5256 print_args(args->hex.size); 5460 print_args(args->hex.size);
5257 printf(")"); 5461 printf(")");
5258 break; 5462 break;
5463 case PRINT_INT_ARRAY:
5464 printf("__print_array(");
5465 print_args(args->int_array.field);
5466 printf(", ");
5467 print_args(args->int_array.count);
5468 printf(", ");
5469 print_args(args->int_array.el_size);
5470 printf(")");
5471 break;
5259 case PRINT_STRING: 5472 case PRINT_STRING:
5260 case PRINT_BSTRING: 5473 case PRINT_BSTRING:
5261 printf("__get_str(%s)", args->string.string); 5474 printf("__get_str(%s)", args->string.string);
@@ -6228,15 +6441,20 @@ void pevent_ref(struct pevent *pevent)
6228 pevent->ref_count++; 6441 pevent->ref_count++;
6229} 6442}
6230 6443
6444void pevent_free_format_field(struct format_field *field)
6445{
6446 free(field->type);
6447 free(field->name);
6448 free(field);
6449}
6450
6231static void free_format_fields(struct format_field *field) 6451static void free_format_fields(struct format_field *field)
6232{ 6452{
6233 struct format_field *next; 6453 struct format_field *next;
6234 6454
6235 while (field) { 6455 while (field) {
6236 next = field->next; 6456 next = field->next;
6237 free(field->type); 6457 pevent_free_format_field(field);
6238 free(field->name);
6239 free(field);
6240 field = next; 6458 field = next;
6241 } 6459 }
6242} 6460}
@@ -6341,6 +6559,7 @@ void pevent_free(struct pevent *pevent)
6341 free_handler(handle); 6559 free_handler(handle);
6342 } 6560 }
6343 6561
6562 free(pevent->trace_clock);
6344 free(pevent->events); 6563 free(pevent->events);
6345 free(pevent->sort_events); 6564 free(pevent->sort_events);
6346 6565
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 7a3873ff9a4f..86a5839fb048 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -22,6 +22,7 @@
22 22
23#include <stdbool.h> 23#include <stdbool.h>
24#include <stdarg.h> 24#include <stdarg.h>
25#include <stdio.h>
25#include <regex.h> 26#include <regex.h>
26#include <string.h> 27#include <string.h>
27 28
@@ -91,6 +92,7 @@ extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
91 92
92extern void trace_seq_terminate(struct trace_seq *s); 93extern void trace_seq_terminate(struct trace_seq *s);
93 94
95extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp);
94extern int trace_seq_do_printf(struct trace_seq *s); 96extern int trace_seq_do_printf(struct trace_seq *s);
95 97
96 98
@@ -114,7 +116,7 @@ struct pevent_plugin_option {
114 char *name; 116 char *name;
115 char *plugin_alias; 117 char *plugin_alias;
116 char *description; 118 char *description;
117 char *value; 119 const char *value;
118 void *priv; 120 void *priv;
119 int set; 121 int set;
120}; 122};
@@ -152,6 +154,10 @@ struct pevent_plugin_option {
152 * .plugin_alias is used to give a shorter name to access 154 * .plugin_alias is used to give a shorter name to access
153 * the vairable. Useful if a plugin handles more than one event. 155 * the vairable. Useful if a plugin handles more than one event.
154 * 156 *
157 * If .value is not set, then it is considered a boolean and only
158 * .set will be processed. If .value is defined, then it is considered
159 * a string option and .set will be ignored.
160 *
155 * PEVENT_PLUGIN_ALIAS: (optional) 161 * PEVENT_PLUGIN_ALIAS: (optional)
156 * The name to use for finding options (uses filename if not defined) 162 * The name to use for finding options (uses filename if not defined)
157 */ 163 */
@@ -245,6 +251,12 @@ struct print_arg_hex {
245 struct print_arg *size; 251 struct print_arg *size;
246}; 252};
247 253
254struct print_arg_int_array {
255 struct print_arg *field;
256 struct print_arg *count;
257 struct print_arg *el_size;
258};
259
248struct print_arg_dynarray { 260struct print_arg_dynarray {
249 struct format_field *field; 261 struct format_field *field;
250 struct print_arg *index; 262 struct print_arg *index;
@@ -273,6 +285,7 @@ enum print_arg_type {
273 PRINT_FLAGS, 285 PRINT_FLAGS,
274 PRINT_SYMBOL, 286 PRINT_SYMBOL,
275 PRINT_HEX, 287 PRINT_HEX,
288 PRINT_INT_ARRAY,
276 PRINT_TYPE, 289 PRINT_TYPE,
277 PRINT_STRING, 290 PRINT_STRING,
278 PRINT_BSTRING, 291 PRINT_BSTRING,
@@ -292,6 +305,7 @@ struct print_arg {
292 struct print_arg_flags flags; 305 struct print_arg_flags flags;
293 struct print_arg_symbol symbol; 306 struct print_arg_symbol symbol;
294 struct print_arg_hex hex; 307 struct print_arg_hex hex;
308 struct print_arg_int_array int_array;
295 struct print_arg_func func; 309 struct print_arg_func func;
296 struct print_arg_string string; 310 struct print_arg_string string;
297 struct print_arg_bitmask bitmask; 311 struct print_arg_bitmask bitmask;
@@ -597,7 +611,7 @@ enum trace_flag_type {
597}; 611};
598 612
599int pevent_register_comm(struct pevent *pevent, const char *comm, int pid); 613int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
600void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock); 614int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock);
601int pevent_register_function(struct pevent *pevent, char *name, 615int pevent_register_function(struct pevent *pevent, char *name,
602 unsigned long long addr, char *mod); 616 unsigned long long addr, char *mod);
603int pevent_register_print_string(struct pevent *pevent, const char *fmt, 617int pevent_register_print_string(struct pevent *pevent, const char *fmt,
@@ -617,6 +631,7 @@ enum pevent_errno pevent_parse_format(struct pevent *pevent,
617 const char *buf, 631 const char *buf,
618 unsigned long size, const char *sys); 632 unsigned long size, const char *sys);
619void pevent_free_format(struct event_format *event); 633void pevent_free_format(struct event_format *event);
634void pevent_free_format_field(struct format_field *field);
620 635
621void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event, 636void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
622 const char *name, struct pevent_record *record, 637 const char *name, struct pevent_record *record,
@@ -675,6 +690,11 @@ int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
675struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type); 690struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
676int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec); 691int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
677const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid); 692const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
693struct cmdline;
694struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
695 struct cmdline *next);
696int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline);
697
678void pevent_event_info(struct trace_seq *s, struct event_format *event, 698void pevent_event_info(struct trace_seq *s, struct event_format *event,
679 struct pevent_record *record); 699 struct pevent_record *record);
680int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, 700int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
index 136162c03af1..a16756ae3526 100644
--- a/tools/lib/traceevent/event-plugin.c
+++ b/tools/lib/traceevent/event-plugin.c
@@ -18,6 +18,7 @@
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 19 */
20 20
21#include <ctype.h>
21#include <stdio.h> 22#include <stdio.h>
22#include <string.h> 23#include <string.h>
23#include <dlfcn.h> 24#include <dlfcn.h>
@@ -49,6 +50,52 @@ struct plugin_list {
49 void *handle; 50 void *handle;
50}; 51};
51 52
53static void lower_case(char *str)
54{
55 if (!str)
56 return;
57 for (; *str; str++)
58 *str = tolower(*str);
59}
60
61static int update_option_value(struct pevent_plugin_option *op, const char *val)
62{
63 char *op_val;
64
65 if (!val) {
66 /* toggle, only if option is boolean */
67 if (op->value)
68 /* Warn? */
69 return 0;
70 op->set ^= 1;
71 return 0;
72 }
73
74 /*
75 * If the option has a value then it takes a string
76 * otherwise the option is a boolean.
77 */
78 if (op->value) {
79 op->value = val;
80 return 0;
81 }
82
83 /* Option is boolean, must be either "1", "0", "true" or "false" */
84
85 op_val = strdup(val);
86 if (!op_val)
87 return -1;
88 lower_case(op_val);
89
90 if (strcmp(val, "1") == 0 || strcmp(val, "true") == 0)
91 op->set = 1;
92 else if (strcmp(val, "0") == 0 || strcmp(val, "false") == 0)
93 op->set = 0;
94 free(op_val);
95
96 return 0;
97}
98
52/** 99/**
53 * traceevent_plugin_list_options - get list of plugin options 100 * traceevent_plugin_list_options - get list of plugin options
54 * 101 *
@@ -120,6 +167,7 @@ update_option(const char *file, struct pevent_plugin_option *option)
120{ 167{
121 struct trace_plugin_options *op; 168 struct trace_plugin_options *op;
122 char *plugin; 169 char *plugin;
170 int ret = 0;
123 171
124 if (option->plugin_alias) { 172 if (option->plugin_alias) {
125 plugin = strdup(option->plugin_alias); 173 plugin = strdup(option->plugin_alias);
@@ -144,9 +192,10 @@ update_option(const char *file, struct pevent_plugin_option *option)
144 if (strcmp(op->option, option->name) != 0) 192 if (strcmp(op->option, option->name) != 0)
145 continue; 193 continue;
146 194
147 option->value = op->value; 195 ret = update_option_value(option, op->value);
148 option->set ^= 1; 196 if (ret)
149 goto out; 197 goto out;
198 break;
150 } 199 }
151 200
152 /* first look for unnamed options */ 201 /* first look for unnamed options */
@@ -156,14 +205,13 @@ update_option(const char *file, struct pevent_plugin_option *option)
156 if (strcmp(op->option, option->name) != 0) 205 if (strcmp(op->option, option->name) != 0)
157 continue; 206 continue;
158 207
159 option->value = op->value; 208 ret = update_option_value(option, op->value);
160 option->set ^= 1;
161 break; 209 break;
162 } 210 }
163 211
164 out: 212 out:
165 free(plugin); 213 free(plugin);
166 return 0; 214 return ret;
167} 215}
168 216
169/** 217/**
diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c
index dcc665228c71..3bcada3ae05a 100644
--- a/tools/lib/traceevent/kbuffer-parse.c
+++ b/tools/lib/traceevent/kbuffer-parse.c
@@ -372,7 +372,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
372 switch (type_len) { 372 switch (type_len) {
373 case KBUFFER_TYPE_PADDING: 373 case KBUFFER_TYPE_PADDING:
374 *length = read_4(kbuf, data); 374 *length = read_4(kbuf, data);
375 data += *length;
376 break; 375 break;
377 376
378 case KBUFFER_TYPE_TIME_EXTEND: 377 case KBUFFER_TYPE_TIME_EXTEND:
@@ -730,3 +729,14 @@ void kbuffer_set_old_format(struct kbuffer *kbuf)
730 729
731 kbuf->next_event = __old_next_event; 730 kbuf->next_event = __old_next_event;
732} 731}
732
733/**
734 * kbuffer_start_of_data - return offset of where data starts on subbuffer
735 * @kbuf: The kbuffer
736 *
737 * Returns the location on the subbuffer where the data starts.
738 */
739int kbuffer_start_of_data(struct kbuffer *kbuf)
740{
741 return kbuf->start;
742}
diff --git a/tools/lib/traceevent/kbuffer.h b/tools/lib/traceevent/kbuffer.h
index c831f64b17a0..03dce757553f 100644
--- a/tools/lib/traceevent/kbuffer.h
+++ b/tools/lib/traceevent/kbuffer.h
@@ -63,5 +63,6 @@ int kbuffer_missed_events(struct kbuffer *kbuf);
63int kbuffer_subbuffer_size(struct kbuffer *kbuf); 63int kbuffer_subbuffer_size(struct kbuffer *kbuf);
64 64
65void kbuffer_set_old_format(struct kbuffer *kbuf); 65void kbuffer_set_old_format(struct kbuffer *kbuf);
66int kbuffer_start_of_data(struct kbuffer *kbuf);
66 67
67#endif /* _K_BUFFER_H */ 68#endif /* _K_BUFFER_H */
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index b50234402fc2..0144b3d1bb77 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -1058,6 +1058,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1058 *parg = current_op; 1058 *parg = current_op;
1059 else 1059 else
1060 *parg = current_exp; 1060 *parg = current_exp;
1061 free(token);
1061 return PEVENT_ERRNO__UNBALANCED_PAREN; 1062 return PEVENT_ERRNO__UNBALANCED_PAREN;
1062 } 1063 }
1063 break; 1064 break;
@@ -1168,6 +1169,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1168 1169
1169 *parg = current_op; 1170 *parg = current_op;
1170 1171
1172 free(token);
1171 return 0; 1173 return 0;
1172 1174
1173 fail_alloc: 1175 fail_alloc:
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
index ec3bd16a5488..292dc9f1d233 100644
--- a/tools/lib/traceevent/trace-seq.c
+++ b/tools/lib/traceevent/trace-seq.c
@@ -231,19 +231,24 @@ void trace_seq_terminate(struct trace_seq *s)
231 s->buffer[s->len] = 0; 231 s->buffer[s->len] = 0;
232} 232}
233 233
234int trace_seq_do_printf(struct trace_seq *s) 234int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp)
235{ 235{
236 TRACE_SEQ_CHECK(s); 236 TRACE_SEQ_CHECK(s);
237 237
238 switch (s->state) { 238 switch (s->state) {
239 case TRACE_SEQ__GOOD: 239 case TRACE_SEQ__GOOD:
240 return printf("%.*s", s->len, s->buffer); 240 return fprintf(fp, "%.*s", s->len, s->buffer);
241 case TRACE_SEQ__BUFFER_POISONED: 241 case TRACE_SEQ__BUFFER_POISONED:
242 puts("Usage of trace_seq after it was destroyed"); 242 fprintf(fp, "%s\n", "Usage of trace_seq after it was destroyed");
243 break; 243 break;
244 case TRACE_SEQ__MEM_ALLOC_FAILED: 244 case TRACE_SEQ__MEM_ALLOC_FAILED:
245 puts("Can't allocate trace_seq buffer memory"); 245 fprintf(fp, "%s\n", "Can't allocate trace_seq buffer memory");
246 break; 246 break;
247 } 247 }
248 return -1; 248 return -1;
249} 249}
250
251int trace_seq_do_printf(struct trace_seq *s)
252{
253 return trace_seq_do_fprintf(s, stdout);
254}
diff --git a/tools/net/bpf_exp.l b/tools/net/bpf_exp.l
index 833a96611da6..7cc72a336645 100644
--- a/tools/net/bpf_exp.l
+++ b/tools/net/bpf_exp.l
@@ -90,8 +90,10 @@ extern void yyerror(const char *str);
90"#"?("hatype") { return K_HATYPE; } 90"#"?("hatype") { return K_HATYPE; }
91"#"?("rxhash") { return K_RXHASH; } 91"#"?("rxhash") { return K_RXHASH; }
92"#"?("cpu") { return K_CPU; } 92"#"?("cpu") { return K_CPU; }
93"#"?("vlan_tci") { return K_VLANT; } 93"#"?("vlan_tci") { return K_VLAN_TCI; }
94"#"?("vlan_pr") { return K_VLANP; } 94"#"?("vlan_pr") { return K_VLAN_AVAIL; }
95"#"?("vlan_avail") { return K_VLAN_AVAIL; }
96"#"?("vlan_tpid") { return K_VLAN_TPID; }
95"#"?("rand") { return K_RAND; } 97"#"?("rand") { return K_RAND; }
96 98
97":" { return ':'; } 99":" { return ':'; }
diff --git a/tools/net/bpf_exp.y b/tools/net/bpf_exp.y
index e6306c51c26f..e24eea1b0db5 100644
--- a/tools/net/bpf_exp.y
+++ b/tools/net/bpf_exp.y
@@ -56,7 +56,7 @@ static void bpf_set_jmp_label(char *label, enum jmp_type type);
56%token OP_LDXI 56%token OP_LDXI
57 57
58%token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE 58%token K_PKT_LEN K_PROTO K_TYPE K_NLATTR K_NLATTR_NEST K_MARK K_QUEUE K_HATYPE
59%token K_RXHASH K_CPU K_IFIDX K_VLANT K_VLANP K_POFF K_RAND 59%token K_RXHASH K_CPU K_IFIDX K_VLAN_TCI K_VLAN_AVAIL K_VLAN_TPID K_POFF K_RAND
60 60
61%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%' 61%token ':' ',' '[' ']' '(' ')' 'x' 'a' '+' 'M' '*' '&' '#' '%'
62 62
@@ -155,10 +155,10 @@ ldb
155 | OP_LDB K_CPU { 155 | OP_LDB K_CPU {
156 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, 156 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
157 SKF_AD_OFF + SKF_AD_CPU); } 157 SKF_AD_OFF + SKF_AD_CPU); }
158 | OP_LDB K_VLANT { 158 | OP_LDB K_VLAN_TCI {
159 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, 159 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
160 SKF_AD_OFF + SKF_AD_VLAN_TAG); } 160 SKF_AD_OFF + SKF_AD_VLAN_TAG); }
161 | OP_LDB K_VLANP { 161 | OP_LDB K_VLAN_AVAIL {
162 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, 162 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
163 SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); } 163 SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
164 | OP_LDB K_POFF { 164 | OP_LDB K_POFF {
@@ -167,6 +167,9 @@ ldb
167 | OP_LDB K_RAND { 167 | OP_LDB K_RAND {
168 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0, 168 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
169 SKF_AD_OFF + SKF_AD_RANDOM); } 169 SKF_AD_OFF + SKF_AD_RANDOM); }
170 | OP_LDB K_VLAN_TPID {
171 bpf_set_curr_instr(BPF_LD | BPF_B | BPF_ABS, 0, 0,
172 SKF_AD_OFF + SKF_AD_VLAN_TPID); }
170 ; 173 ;
171 174
172ldh 175ldh
@@ -206,10 +209,10 @@ ldh
206 | OP_LDH K_CPU { 209 | OP_LDH K_CPU {
207 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, 210 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
208 SKF_AD_OFF + SKF_AD_CPU); } 211 SKF_AD_OFF + SKF_AD_CPU); }
209 | OP_LDH K_VLANT { 212 | OP_LDH K_VLAN_TCI {
210 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, 213 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
211 SKF_AD_OFF + SKF_AD_VLAN_TAG); } 214 SKF_AD_OFF + SKF_AD_VLAN_TAG); }
212 | OP_LDH K_VLANP { 215 | OP_LDH K_VLAN_AVAIL {
213 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, 216 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
214 SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); } 217 SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
215 | OP_LDH K_POFF { 218 | OP_LDH K_POFF {
@@ -218,6 +221,9 @@ ldh
218 | OP_LDH K_RAND { 221 | OP_LDH K_RAND {
219 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0, 222 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
220 SKF_AD_OFF + SKF_AD_RANDOM); } 223 SKF_AD_OFF + SKF_AD_RANDOM); }
224 | OP_LDH K_VLAN_TPID {
225 bpf_set_curr_instr(BPF_LD | BPF_H | BPF_ABS, 0, 0,
226 SKF_AD_OFF + SKF_AD_VLAN_TPID); }
221 ; 227 ;
222 228
223ldi 229ldi
@@ -262,10 +268,10 @@ ld
262 | OP_LD K_CPU { 268 | OP_LD K_CPU {
263 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, 269 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
264 SKF_AD_OFF + SKF_AD_CPU); } 270 SKF_AD_OFF + SKF_AD_CPU); }
265 | OP_LD K_VLANT { 271 | OP_LD K_VLAN_TCI {
266 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, 272 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
267 SKF_AD_OFF + SKF_AD_VLAN_TAG); } 273 SKF_AD_OFF + SKF_AD_VLAN_TAG); }
268 | OP_LD K_VLANP { 274 | OP_LD K_VLAN_AVAIL {
269 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, 275 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
270 SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); } 276 SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT); }
271 | OP_LD K_POFF { 277 | OP_LD K_POFF {
@@ -274,6 +280,9 @@ ld
274 | OP_LD K_RAND { 280 | OP_LD K_RAND {
275 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0, 281 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
276 SKF_AD_OFF + SKF_AD_RANDOM); } 282 SKF_AD_OFF + SKF_AD_RANDOM); }
283 | OP_LD K_VLAN_TPID {
284 bpf_set_curr_instr(BPF_LD | BPF_W | BPF_ABS, 0, 0,
285 SKF_AD_OFF + SKF_AD_VLAN_TPID); }
277 | OP_LD 'M' '[' number ']' { 286 | OP_LD 'M' '[' number ']' {
278 bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); } 287 bpf_set_curr_instr(BPF_LD | BPF_MEM, 0, 0, $4); }
279 | OP_LD '[' 'x' '+' number ']' { 288 | OP_LD '[' 'x' '+' number ']' {
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 40399c3d97d6..812f904193e8 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -1,6 +1,7 @@
1PERF-CFLAGS 1PERF-CFLAGS
2PERF-GUI-VARS 2PERF-GUI-VARS
3PERF-VERSION-FILE 3PERF-VERSION-FILE
4FEATURE-DUMP
4perf 5perf
5perf-read-vdso32 6perf-read-vdso32
6perf-read-vdsox32 7perf-read-vdsox32
diff --git a/tools/perf/Build b/tools/perf/Build
new file mode 100644
index 000000000000..b77370ef7005
--- /dev/null
+++ b/tools/perf/Build
@@ -0,0 +1,44 @@
1perf-y += builtin-bench.o
2perf-y += builtin-annotate.o
3perf-y += builtin-diff.o
4perf-y += builtin-evlist.o
5perf-y += builtin-help.o
6perf-y += builtin-sched.o
7perf-y += builtin-buildid-list.o
8perf-y += builtin-buildid-cache.o
9perf-y += builtin-list.o
10perf-y += builtin-record.o
11perf-y += builtin-report.o
12perf-y += builtin-stat.o
13perf-y += builtin-timechart.o
14perf-y += builtin-top.o
15perf-y += builtin-script.o
16perf-y += builtin-kmem.o
17perf-y += builtin-lock.o
18perf-y += builtin-kvm.o
19perf-y += builtin-inject.o
20perf-y += builtin-mem.o
21perf-y += builtin-data.o
22
23perf-$(CONFIG_AUDIT) += builtin-trace.o
24perf-$(CONFIG_LIBELF) += builtin-probe.o
25
26perf-y += bench/
27perf-y += tests/
28
29perf-y += perf.o
30
31paths += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))"
32paths += -DPERF_INFO_PATH="BUILD_STR($(infodir_SQ))"
33paths += -DPERF_MAN_PATH="BUILD_STR($(mandir_SQ))"
34
35CFLAGS_builtin-help.o += $(paths)
36CFLAGS_builtin-timechart.o += $(paths)
37CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" -include $(OUTPUT)PERF-VERSION-FILE
38
39libperf-y += util/
40libperf-y += arch/
41libperf-y += ui/
42libperf-y += scripts/
43
44gtk-y += ui/gtk/
diff --git a/tools/perf/Documentation/Build.txt b/tools/perf/Documentation/Build.txt
new file mode 100644
index 000000000000..f6fc6507ba55
--- /dev/null
+++ b/tools/perf/Documentation/Build.txt
@@ -0,0 +1,49 @@
1
21) perf build
3=============
4The perf build process consists of several separated building blocks,
5which are linked together to form the perf binary:
6 - libperf library (static)
7 - perf builtin commands
8 - traceevent library (static)
9 - GTK ui library
10
11Several makefiles govern the perf build:
12
13 - Makefile
14 top level Makefile working as a wrapper that calls the main
15 Makefile.perf with a -j option to do parallel builds.
16
17 - Makefile.perf
18 main makefile that triggers build of all perf objects including
19 installation and documentation processing.
20
21 - tools/build/Makefile.build
22 main makefile of the build framework
23
24 - tools/build/Build.include
25 build framework generic definitions
26
27 - Build makefiles
28 makefiles that defines build objects
29
30Please refer to tools/build/Documentation/Build.txt for more
31information about build framework.
32
33
342) perf build
35=============
36The Makefile.perf triggers the build framework for build objects:
37 perf, libperf, gtk
38
39resulting in following objects:
40 $ ls *-in.o
41 gtk-in.o libperf-in.o perf-in.o
42
43Those objects are then used in final linking:
44 libperf-gtk.so <- gtk-in.o libperf-in.o
45 perf <- perf-in.o libperf-in.o
46
47
48NOTE this description is omitting other libraries involved, only
49 focusing on build framework outcomes
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index 0294c57b1f5e..dd07b55f58d8 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -12,9 +12,9 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command manages the build-id cache. It can add and remove files to/from 15This command manages the build-id cache. It can add, remove, update and purge
16the cache. In the future it should as well purge older entries, set upper 16files to/from the cache. In the future it should as well set upper limits for
17limits for the space used by the cache, etc. 17the space used by the cache, etc.
18 18
19OPTIONS 19OPTIONS
20------- 20-------
@@ -36,14 +36,24 @@ OPTIONS
36 actually made. 36 actually made.
37-r:: 37-r::
38--remove=:: 38--remove=::
39 Remove specified file from the cache. 39 Remove a cached binary which has same build-id of specified file
40 from the cache.
41-p::
42--purge=::
43 Purge all cached binaries including older caches which have specified
44 path from the cache.
40-M:: 45-M::
41--missing=:: 46--missing=::
42 List missing build ids in the cache for the specified file. 47 List missing build ids in the cache for the specified file.
43-u:: 48-u::
44--update:: 49--update=::
45 Update specified file of the cache. It can be used to update kallsyms 50 Update specified file of the cache. Note that this doesn't remove
46 kernel dso to vmlinux in order to support annotation. 51 older entires since those may be still needed for annotating old
52 (or remote) perf.data. Only if there is already a cache which has
53 exactly same build-id, that is replaced by new one. It can be used
54 to update kallsyms and kernel dso to vmlinux in order to support
55 annotation.
56
47-v:: 57-v::
48--verbose:: 58--verbose::
49 Be more verbose. 59 Be more verbose.
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt
new file mode 100644
index 000000000000..be8fa1a0a97e
--- /dev/null
+++ b/tools/perf/Documentation/perf-data.txt
@@ -0,0 +1,40 @@
1perf-data(1)
2==============
3
4NAME
5----
6perf-data - Data file related processing
7
8SYNOPSIS
9--------
10[verse]
11'perf data' [<common options>] <command> [<options>]",
12
13DESCRIPTION
14-----------
15Data file related processing.
16
17COMMANDS
18--------
19convert::
20 Converts perf data file into another format (only CTF [1] format is support by now).
21 It's possible to set data-convert debug variable to get debug messages from conversion,
22 like:
23 perf --debug data-convert data convert ...
24
25OPTIONS for 'convert'
26---------------------
27--to-ctf::
28 Triggers the CTF conversion, specify the path of CTF data directory.
29
30-i::
31 Specify input perf data file path.
32
33-v::
34--verbose::
35 Be more verbose (show counter open errors, etc).
36
37SEE ALSO
38--------
39linkperf:perf[1]
40[1] Common Trace Format - http://www.efficios.com/ctf
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index e463caa3eb49..d1deb573877f 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -20,12 +20,20 @@ If no parameters are passed it will assume perf.data.old and perf.data.
20The differential profile is displayed only for events matching both 20The differential profile is displayed only for events matching both
21specified perf.data files. 21specified perf.data files.
22 22
23If no parameters are passed the samples will be sorted by dso and symbol.
24As the perf.data files could come from different binaries, the symbols addresses
25could vary. So perf diff is based on the comparison of the files and
26symbols name.
27
23OPTIONS 28OPTIONS
24------- 29-------
25-D:: 30-D::
26--dump-raw-trace:: 31--dump-raw-trace::
27 Dump raw trace in ASCII. 32 Dump raw trace in ASCII.
28 33
34--kallsyms=<file>::
35 kallsyms pathname
36
29-m:: 37-m::
30--modules:: 38--modules::
31 Load module symbols. WARNING: use only with -k and LIVE kernel 39 Load module symbols. WARNING: use only with -k and LIVE kernel
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index 7c8fbbf3f61c..23219c65c16f 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -3,7 +3,7 @@ perf-kmem(1)
3 3
4NAME 4NAME
5---- 5----
6perf-kmem - Tool to trace/measure kernel memory(slab) properties 6perf-kmem - Tool to trace/measure kernel memory properties
7 7
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
@@ -25,6 +25,10 @@ OPTIONS
25--input=<file>:: 25--input=<file>::
26 Select the input file (default: perf.data unless stdin is a fifo) 26 Select the input file (default: perf.data unless stdin is a fifo)
27 27
28-v::
29--verbose::
30 Be more verbose. (show symbol address, etc)
31
28--caller:: 32--caller::
29 Show per-callsite statistics 33 Show per-callsite statistics
30 34
@@ -42,6 +46,12 @@ OPTIONS
42--raw-ip:: 46--raw-ip::
43 Print raw ip instead of symbol 47 Print raw ip instead of symbol
44 48
49--slab::
50 Analyze SLAB allocator events.
51
52--page::
53 Analyze page allocator events
54
45SEE ALSO 55SEE ALSO
46-------- 56--------
47linkperf:perf-record[1] 57linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 3e2aec94f806..bada8933fdd4 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -26,6 +26,7 @@ counted. The following modifiers exist:
26 u - user-space counting 26 u - user-space counting
27 k - kernel counting 27 k - kernel counting
28 h - hypervisor counting 28 h - hypervisor counting
29 I - non idle counting
29 G - guest counting (in KVM guests) 30 G - guest counting (in KVM guests)
30 H - host counting (not in KVM guests) 31 H - host counting (not in KVM guests)
31 p - precise level 32 p - precise level
@@ -127,6 +128,12 @@ To limit the list use:
127One or more types can be used at the same time, listing the events for the 128One or more types can be used at the same time, listing the events for the
128types specified. 129types specified.
129 130
131Support raw format:
132
133. '--raw-dump', shows the raw-dump of all the events.
134. '--raw-dump [hw|sw|cache|tracepoint|pmu|event_glob]', shows the raw-dump of
135 a certain kind of events.
136
130SEE ALSO 137SEE ALSO
131-------- 138--------
132linkperf:perf-stat[1], linkperf:perf-top[1], 139linkperf:perf-stat[1], linkperf:perf-top[1],
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index aaa869be3dc1..239609c09f83 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -47,6 +47,12 @@ OPTIONS
47-v:: 47-v::
48--verbose:: 48--verbose::
49 Be more verbose (show parsed arguments, etc). 49 Be more verbose (show parsed arguments, etc).
50 Can not use with -q.
51
52-q::
53--quiet::
54 Be quiet (do not show any messages including errors).
55 Can not use with -v.
50 56
51-a:: 57-a::
52--add=:: 58--add=::
@@ -96,7 +102,7 @@ OPTIONS
96 Dry run. With this option, --add and --del doesn't execute actual 102 Dry run. With this option, --add and --del doesn't execute actual
97 adding and removal operations. 103 adding and removal operations.
98 104
99--max-probes:: 105--max-probes=NUM::
100 Set the maximum number of probe points for an event. Default is 128. 106 Set the maximum number of probe points for an event. Default is 128.
101 107
102-x:: 108-x::
@@ -104,8 +110,13 @@ OPTIONS
104 Specify path to the executable or shared library file for user 110 Specify path to the executable or shared library file for user
105 space tracing. Can also be used with --funcs option. 111 space tracing. Can also be used with --funcs option.
106 112
113--demangle::
114 Demangle application symbols. --no-demangle is also available
115 for disabling demangling.
116
107--demangle-kernel:: 117--demangle-kernel::
108 Demangle kernel symbols. 118 Demangle kernel symbols. --no-demangle-kernel is also available
119 for disabling kernel demangling.
109 120
110In absence of -m/-x options, perf probe checks if the first argument after 121In absence of -m/-x options, perf probe checks if the first argument after
111the options is an absolute path name. If its an absolute path, perf probe 122the options is an absolute path name. If its an absolute path, perf probe
@@ -137,6 +148,7 @@ Each probe argument follows below syntax.
137 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE] 148 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]
138 149
139'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'.) 150'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'.)
151'$vars' special argument is also available for NAME, it is expanded to the local variables which can access at given probe point.
140'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. 152'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.
141 153
142On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid. 154On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 31e977459c51..4847a793de65 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -55,6 +55,11 @@ OPTIONS
55 If you want to profile write accesses in [0x1000~1008), just set 55 If you want to profile write accesses in [0x1000~1008), just set
56 'mem:0x1000/8:w'. 56 'mem:0x1000/8:w'.
57 57
58 - a group of events surrounded by a pair of brace ("{event1,event2,...}").
59 Each event is separated by commas and the group should be quoted to
60 prevent the shell interpretation. You also need to use --group on
61 "perf report" to view group events together.
62
58--filter=<filter>:: 63--filter=<filter>::
59 Event filter. 64 Event filter.
60 65
@@ -62,9 +67,6 @@ OPTIONS
62--all-cpus:: 67--all-cpus::
63 System-wide collection from all CPUs. 68 System-wide collection from all CPUs.
64 69
65-l::
66 Scale counter values.
67
68-p:: 70-p::
69--pid=:: 71--pid=::
70 Record events on existing process ID (comma separated list). 72 Record events on existing process ID (comma separated list).
@@ -107,6 +109,10 @@ OPTIONS
107 specification with appended unit character - B/K/M/G. The 109 specification with appended unit character - B/K/M/G. The
108 size is rounded up to have nearest pages power of two value. 110 size is rounded up to have nearest pages power of two value.
109 111
112--group::
113 Put all events in a single event group. This precedes the --event
114 option and remains only for backward compatibility. See --event.
115
110-g:: 116-g::
111 Enables call-graph (stack chain/backtrace) recording. 117 Enables call-graph (stack chain/backtrace) recording.
112 118
@@ -115,13 +121,19 @@ OPTIONS
115 implies -g. 121 implies -g.
116 122
117 Allows specifying "fp" (frame pointer) or "dwarf" 123 Allows specifying "fp" (frame pointer) or "dwarf"
118 (DWARF's CFI - Call Frame Information) as the method to collect 124 (DWARF's CFI - Call Frame Information) or "lbr"
125 (Hardware Last Branch Record facility) as the method to collect
119 the information used to show the call graphs. 126 the information used to show the call graphs.
120 127
121 In some systems, where binaries are build with gcc 128 In some systems, where binaries are build with gcc
122 --fomit-frame-pointer, using the "fp" method will produce bogus 129 --fomit-frame-pointer, using the "fp" method will produce bogus
123 call graphs, using "dwarf", if available (perf tools linked to 130 call graphs, using "dwarf", if available (perf tools linked to
124 the libunwind library) should be used instead. 131 the libunwind library) should be used instead.
132 Using the "lbr" method doesn't require any compiler options. It
133 will produce call graphs from the hardware LBR registers. The
134 main limition is that it is only available on new Intel
135 platforms, such as Haswell. It can only get user call chain. It
136 doesn't work with branch stack sampling at the same time.
125 137
126-q:: 138-q::
127--quiet:: 139--quiet::
@@ -235,6 +247,16 @@ Capture machine state (registers) at interrupt, i.e., on counter overflows for
235each sample. List of captured registers depends on the architecture. This option 247each sample. List of captured registers depends on the architecture. This option
236is off by default. 248is off by default.
237 249
250--running-time::
251Record running and enabled time for read events (:S)
252
253-k::
254--clockid::
255Sets the clock id to use for the various time fields in the perf_event_type
256records. See clock_gettime(). In particular CLOCK_MONOTONIC and
257CLOCK_MONOTONIC_RAW are supported, some events might also allow
258CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
259
238SEE ALSO 260SEE ALSO
239-------- 261--------
240linkperf:perf-stat[1], linkperf:perf-list[1] 262linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index dd7cccdde498..4879cf638824 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -40,6 +40,11 @@ OPTIONS
40 Only consider symbols in these comms. CSV that understands 40 Only consider symbols in these comms. CSV that understands
41 file://filename entries. This option will affect the percentage of 41 file://filename entries. This option will affect the percentage of
42 the overhead column. See --percentage for more info. 42 the overhead column. See --percentage for more info.
43--pid=::
44 Only show events for given process ID (comma separated list).
45
46--tid=::
47 Only show events for given thread ID (comma separated list).
43-d:: 48-d::
44--dsos=:: 49--dsos=::
45 Only consider symbols in these dsos. CSV that understands 50 Only consider symbols in these dsos. CSV that understands
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index a21eec05bc42..79445750fcb3 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -193,6 +193,12 @@ OPTIONS
193 Only display events for these comms. CSV that understands 193 Only display events for these comms. CSV that understands
194 file://filename entries. 194 file://filename entries.
195 195
196--pid=::
197 Only show events for given process ID (comma separated list).
198
199--tid=::
200 Only show events for given thread ID (comma separated list).
201
196-I:: 202-I::
197--show-info:: 203--show-info::
198 Display extended information about the perf.data file. This adds 204 Display extended information about the perf.data file. This adds
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 7e1b1f2bb83c..ba03fd5d1a54 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -55,6 +55,9 @@ OPTIONS
55--uid=:: 55--uid=::
56 Record events in threads owned by uid. Name or number. 56 Record events in threads owned by uid. Name or number.
57 57
58--filter-pids=::
59 Filter out events for these pids and for 'trace' itself (comma separated list).
60
58-v:: 61-v::
59--verbose=:: 62--verbose=::
60 Verbosity level. 63 Verbosity level.
@@ -115,6 +118,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
115--syscalls:: 118--syscalls::
116 Trace system calls. This options is enabled by default. 119 Trace system calls. This options is enabled by default.
117 120
121--event::
122 Trace other events, see 'perf list' for a complete list.
123
118PAGEFAULTS 124PAGEFAULTS
119---------- 125----------
120 126
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt
index 1e8e400b4493..2b131776363e 100644
--- a/tools/perf/Documentation/perf.txt
+++ b/tools/perf/Documentation/perf.txt
@@ -13,11 +13,16 @@ SYNOPSIS
13OPTIONS 13OPTIONS
14------- 14-------
15--debug:: 15--debug::
16 Setup debug variable (just verbose for now) in value 16 Setup debug variable (see list below) in value
17 range (0, 10). Use like: 17 range (0, 10). Use like:
18 --debug verbose # sets verbose = 1 18 --debug verbose # sets verbose = 1
19 --debug verbose=2 # sets verbose = 2 19 --debug verbose=2 # sets verbose = 2
20 20
21 List of debug variables allowed to set:
22 verbose - general debug messages
23 ordered-events - ordered events object debug messages
24 data-convert - data convert command debug messages
25
21--buildid-dir:: 26--buildid-dir::
22 Setup buildid cache directory. It has higher priority than 27 Setup buildid cache directory. It has higher priority than
23 buildid.dir config file option. 28 buildid.dir config file option.
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index fbbfdc39271d..11ccbb22ea2b 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,5 +1,6 @@
1tools/perf 1tools/perf
2tools/scripts 2tools/scripts
3tools/build
3tools/lib/traceevent 4tools/lib/traceevent
4tools/lib/api 5tools/lib/api
5tools/lib/symbol/kallsyms.c 6tools/lib/symbol/kallsyms.c
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index cb2e5868c8e8..c699dc35eef9 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -24,8 +24,8 @@ unexport MAKEFLAGS
24# (To override it, run 'make JOBS=1' and similar.) 24# (To override it, run 'make JOBS=1' and similar.)
25# 25#
26ifeq ($(JOBS),) 26ifeq ($(JOBS),)
27 JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null) 27 JOBS := $(shell egrep -c '^processor|^CPU' /proc/cpuinfo 2>/dev/null)
28 ifeq ($(JOBS),) 28 ifeq ($(JOBS),0)
29 JOBS := 1 29 JOBS := 1
30 endif 30 endif
31endif 31endif
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index aa6a50447c32..c43a20517591 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -68,7 +68,11 @@ include config/utilities.mak
68# for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode 68# for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode
69# 69#
70# Define NO_ZLIB if you do not want to support compressed kernel modules 70# Define NO_ZLIB if you do not want to support compressed kernel modules
71 71#
72# Define LIBBABELTRACE if you DO want libbabeltrace support
73# for CTF data format.
74#
75# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
72 76
73ifeq ($(srctree),) 77ifeq ($(srctree),)
74srctree := $(patsubst %/,%,$(dir $(shell pwd))) 78srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -82,13 +86,29 @@ endif
82 86
83ifneq ($(OUTPUT),) 87ifneq ($(OUTPUT),)
84#$(info Determined 'OUTPUT' to be $(OUTPUT)) 88#$(info Determined 'OUTPUT' to be $(OUTPUT))
89# Adding $(OUTPUT) as a directory to look for source files,
90# because use generated output files as sources dependency
91# for flex/bison parsers.
92VPATH += $(OUTPUT)
93export VPATH
85endif 94endif
86 95
96ifeq ($(V),1)
97 Q =
98else
99 Q = @
100endif
101
102# Do not use make's built-in rules
103# (this improves performance and avoids hard-to-debug behaviour);
104MAKEFLAGS += -r
105
87$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD 106$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
88 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) 107 $(Q)$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
89 @touch $(OUTPUT)PERF-VERSION-FILE 108 $(Q)touch $(OUTPUT)PERF-VERSION-FILE
90 109
91CC = $(CROSS_COMPILE)gcc 110CC = $(CROSS_COMPILE)gcc
111LD = $(CROSS_COMPILE)ld
92AR = $(CROSS_COMPILE)ar 112AR = $(CROSS_COMPILE)ar
93PKG_CONFIG = $(CROSS_COMPILE)pkg-config 113PKG_CONFIG = $(CROSS_COMPILE)pkg-config
94 114
@@ -127,10 +147,6 @@ export prefix bindir sharedir sysconfdir DESTDIR
127SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 147SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
128 148
129# Guard against environment variables 149# Guard against environment variables
130BUILTIN_OBJS =
131LIB_H =
132LIB_OBJS =
133GTK_OBJS =
134PYRF_OBJS = 150PYRF_OBJS =
135SCRIPT_SH = 151SCRIPT_SH =
136 152
@@ -155,8 +171,8 @@ endif
155LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 171LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
156export LIBTRACEEVENT 172export LIBTRACEEVENT
157 173
158LIBAPIKFS = $(LIB_PATH)libapikfs.a 174LIBAPI = $(LIB_PATH)libapi.a
159export LIBAPIKFS 175export LIBAPI
160 176
161# python extension build directories 177# python extension build directories
162PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ 178PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
@@ -167,7 +183,7 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
167python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 183python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
168 184
169PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 185PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
170PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPIKFS) 186PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
171 187
172$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 188$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
173 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ 189 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
@@ -206,297 +222,9 @@ endif
206 222
207export PERL_PATH 223export PERL_PATH
208 224
209$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
210 $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
211
212$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
213 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
214
215$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
216 $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
217
218$(OUTPUT)util/pmu-bison.c: util/pmu.y
219 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
220
221$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
222$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
223
224LIB_FILE=$(OUTPUT)libperf.a 225LIB_FILE=$(OUTPUT)libperf.a
225 226
226LIB_H += ../lib/symbol/kallsyms.h 227PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
227LIB_H += ../../include/uapi/linux/perf_event.h
228LIB_H += ../../include/linux/rbtree.h
229LIB_H += ../../include/linux/list.h
230LIB_H += ../../include/uapi/linux/const.h
231LIB_H += ../include/linux/hash.h
232LIB_H += ../../include/linux/stringify.h
233LIB_H += util/include/linux/bitmap.h
234LIB_H += ../include/linux/bitops.h
235LIB_H += ../include/asm-generic/bitops/arch_hweight.h
236LIB_H += ../include/asm-generic/bitops/atomic.h
237LIB_H += ../include/asm-generic/bitops/const_hweight.h
238LIB_H += ../include/asm-generic/bitops/find.h
239LIB_H += ../include/asm-generic/bitops/fls64.h
240LIB_H += ../include/asm-generic/bitops/fls.h
241LIB_H += ../include/asm-generic/bitops/__ffs.h
242LIB_H += ../include/asm-generic/bitops/__fls.h
243LIB_H += ../include/asm-generic/bitops/hweight.h
244LIB_H += ../include/asm-generic/bitops.h
245LIB_H += ../include/linux/compiler.h
246LIB_H += ../include/linux/log2.h
247LIB_H += util/include/linux/const.h
248LIB_H += util/include/linux/ctype.h
249LIB_H += util/include/linux/kernel.h
250LIB_H += util/include/linux/list.h
251LIB_H += ../include/linux/export.h
252LIB_H += util/include/linux/poison.h
253LIB_H += util/include/linux/rbtree.h
254LIB_H += util/include/linux/rbtree_augmented.h
255LIB_H += util/include/linux/string.h
256LIB_H += ../include/linux/types.h
257LIB_H += util/include/linux/linkage.h
258LIB_H += util/include/asm/asm-offsets.h
259LIB_H += ../include/asm/bug.h
260LIB_H += util/include/asm/byteorder.h
261LIB_H += util/include/asm/swab.h
262LIB_H += util/include/asm/system.h
263LIB_H += util/include/asm/uaccess.h
264LIB_H += util/include/dwarf-regs.h
265LIB_H += util/include/asm/dwarf2.h
266LIB_H += util/include/asm/cpufeature.h
267LIB_H += util/include/asm/unistd_32.h
268LIB_H += util/include/asm/unistd_64.h
269LIB_H += perf.h
270LIB_H += util/annotate.h
271LIB_H += util/cache.h
272LIB_H += util/callchain.h
273LIB_H += util/build-id.h
274LIB_H += util/db-export.h
275LIB_H += util/debug.h
276LIB_H += util/pmu.h
277LIB_H += util/event.h
278LIB_H += util/evsel.h
279LIB_H += util/evlist.h
280LIB_H += util/exec_cmd.h
281LIB_H += util/find-vdso-map.c
282LIB_H += util/levenshtein.h
283LIB_H += util/machine.h
284LIB_H += util/map.h
285LIB_H += util/parse-options.h
286LIB_H += util/parse-events.h
287LIB_H += util/quote.h
288LIB_H += util/util.h
289LIB_H += util/xyarray.h
290LIB_H += util/header.h
291LIB_H += util/help.h
292LIB_H += util/session.h
293LIB_H += util/ordered-events.h
294LIB_H += util/strbuf.h
295LIB_H += util/strlist.h
296LIB_H += util/strfilter.h
297LIB_H += util/svghelper.h
298LIB_H += util/tool.h
299LIB_H += util/run-command.h
300LIB_H += util/sigchain.h
301LIB_H += util/dso.h
302LIB_H += util/symbol.h
303LIB_H += util/color.h
304LIB_H += util/values.h
305LIB_H += util/sort.h
306LIB_H += util/hist.h
307LIB_H += util/comm.h
308LIB_H += util/thread.h
309LIB_H += util/thread_map.h
310LIB_H += util/trace-event.h
311LIB_H += util/probe-finder.h
312LIB_H += util/dwarf-aux.h
313LIB_H += util/probe-event.h
314LIB_H += util/pstack.h
315LIB_H += util/cpumap.h
316LIB_H += util/top.h
317LIB_H += $(ARCH_INCLUDE)
318LIB_H += util/cgroup.h
319LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
320LIB_H += util/target.h
321LIB_H += util/rblist.h
322LIB_H += util/intlist.h
323LIB_H += util/perf_regs.h
324LIB_H += util/unwind.h
325LIB_H += util/vdso.h
326LIB_H += util/tsc.h
327LIB_H += ui/helpline.h
328LIB_H += ui/progress.h
329LIB_H += ui/util.h
330LIB_H += ui/ui.h
331LIB_H += util/data.h
332LIB_H += util/kvm-stat.h
333LIB_H += util/thread-stack.h
334
335LIB_OBJS += $(OUTPUT)util/abspath.o
336LIB_OBJS += $(OUTPUT)util/alias.o
337LIB_OBJS += $(OUTPUT)util/annotate.o
338LIB_OBJS += $(OUTPUT)util/build-id.o
339LIB_OBJS += $(OUTPUT)util/config.o
340LIB_OBJS += $(OUTPUT)util/ctype.o
341LIB_OBJS += $(OUTPUT)util/db-export.o
342LIB_OBJS += $(OUTPUT)util/pmu.o
343LIB_OBJS += $(OUTPUT)util/environment.o
344LIB_OBJS += $(OUTPUT)util/event.o
345LIB_OBJS += $(OUTPUT)util/evlist.o
346LIB_OBJS += $(OUTPUT)util/evsel.o
347LIB_OBJS += $(OUTPUT)util/exec_cmd.o
348LIB_OBJS += $(OUTPUT)util/find_next_bit.o
349LIB_OBJS += $(OUTPUT)util/help.o
350LIB_OBJS += $(OUTPUT)util/kallsyms.o
351LIB_OBJS += $(OUTPUT)util/levenshtein.o
352LIB_OBJS += $(OUTPUT)util/parse-options.o
353LIB_OBJS += $(OUTPUT)util/parse-events.o
354LIB_OBJS += $(OUTPUT)util/path.o
355LIB_OBJS += $(OUTPUT)util/rbtree.o
356LIB_OBJS += $(OUTPUT)util/bitmap.o
357LIB_OBJS += $(OUTPUT)util/hweight.o
358LIB_OBJS += $(OUTPUT)util/run-command.o
359LIB_OBJS += $(OUTPUT)util/quote.o
360LIB_OBJS += $(OUTPUT)util/strbuf.o
361LIB_OBJS += $(OUTPUT)util/string.o
362LIB_OBJS += $(OUTPUT)util/strlist.o
363LIB_OBJS += $(OUTPUT)util/strfilter.o
364LIB_OBJS += $(OUTPUT)util/top.o
365LIB_OBJS += $(OUTPUT)util/usage.o
366LIB_OBJS += $(OUTPUT)util/wrapper.o
367LIB_OBJS += $(OUTPUT)util/sigchain.o
368LIB_OBJS += $(OUTPUT)util/dso.o
369LIB_OBJS += $(OUTPUT)util/symbol.o
370LIB_OBJS += $(OUTPUT)util/symbol-elf.o
371LIB_OBJS += $(OUTPUT)util/color.o
372LIB_OBJS += $(OUTPUT)util/pager.o
373LIB_OBJS += $(OUTPUT)util/header.o
374LIB_OBJS += $(OUTPUT)util/callchain.o
375LIB_OBJS += $(OUTPUT)util/values.o
376LIB_OBJS += $(OUTPUT)util/debug.o
377LIB_OBJS += $(OUTPUT)util/machine.o
378LIB_OBJS += $(OUTPUT)util/map.o
379LIB_OBJS += $(OUTPUT)util/pstack.o
380LIB_OBJS += $(OUTPUT)util/session.o
381LIB_OBJS += $(OUTPUT)util/ordered-events.o
382LIB_OBJS += $(OUTPUT)util/comm.o
383LIB_OBJS += $(OUTPUT)util/thread.o
384LIB_OBJS += $(OUTPUT)util/thread_map.o
385LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
386LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
387LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
388LIB_OBJS += $(OUTPUT)util/pmu-flex.o
389LIB_OBJS += $(OUTPUT)util/pmu-bison.o
390LIB_OBJS += $(OUTPUT)util/trace-event-read.o
391LIB_OBJS += $(OUTPUT)util/trace-event-info.o
392LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
393LIB_OBJS += $(OUTPUT)util/trace-event.o
394LIB_OBJS += $(OUTPUT)util/svghelper.o
395LIB_OBJS += $(OUTPUT)util/sort.o
396LIB_OBJS += $(OUTPUT)util/hist.o
397LIB_OBJS += $(OUTPUT)util/probe-event.o
398LIB_OBJS += $(OUTPUT)util/util.o
399LIB_OBJS += $(OUTPUT)util/xyarray.o
400LIB_OBJS += $(OUTPUT)util/cpumap.o
401LIB_OBJS += $(OUTPUT)util/cgroup.o
402LIB_OBJS += $(OUTPUT)util/target.o
403LIB_OBJS += $(OUTPUT)util/rblist.o
404LIB_OBJS += $(OUTPUT)util/intlist.o
405LIB_OBJS += $(OUTPUT)util/vdso.o
406LIB_OBJS += $(OUTPUT)util/stat.o
407LIB_OBJS += $(OUTPUT)util/record.o
408LIB_OBJS += $(OUTPUT)util/srcline.o
409LIB_OBJS += $(OUTPUT)util/data.o
410LIB_OBJS += $(OUTPUT)util/tsc.o
411LIB_OBJS += $(OUTPUT)util/cloexec.o
412LIB_OBJS += $(OUTPUT)util/thread-stack.o
413
414LIB_OBJS += $(OUTPUT)ui/setup.o
415LIB_OBJS += $(OUTPUT)ui/helpline.o
416LIB_OBJS += $(OUTPUT)ui/progress.o
417LIB_OBJS += $(OUTPUT)ui/util.o
418LIB_OBJS += $(OUTPUT)ui/hist.o
419LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
420
421LIB_OBJS += $(OUTPUT)arch/common.o
422
423LIB_OBJS += $(OUTPUT)tests/parse-events.o
424LIB_OBJS += $(OUTPUT)tests/dso-data.o
425LIB_OBJS += $(OUTPUT)tests/attr.o
426LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
427LIB_OBJS += $(OUTPUT)tests/open-syscall.o
428LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
429LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
430LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
431LIB_OBJS += $(OUTPUT)tests/perf-record.o
432LIB_OBJS += $(OUTPUT)tests/rdpmc.o
433LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
434LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
435LIB_OBJS += $(OUTPUT)tests/fdarray.o
436LIB_OBJS += $(OUTPUT)tests/pmu.o
437LIB_OBJS += $(OUTPUT)tests/hists_common.o
438LIB_OBJS += $(OUTPUT)tests/hists_link.o
439LIB_OBJS += $(OUTPUT)tests/hists_filter.o
440LIB_OBJS += $(OUTPUT)tests/hists_output.o
441LIB_OBJS += $(OUTPUT)tests/hists_cumulate.o
442LIB_OBJS += $(OUTPUT)tests/python-use.o
443LIB_OBJS += $(OUTPUT)tests/bp_signal.o
444LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
445LIB_OBJS += $(OUTPUT)tests/task-exit.o
446LIB_OBJS += $(OUTPUT)tests/sw-clock.o
447ifeq ($(ARCH),x86)
448LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
449endif
450LIB_OBJS += $(OUTPUT)tests/code-reading.o
451LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
452LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
453ifndef NO_DWARF_UNWIND
454ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
455LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
456endif
457endif
458LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
459LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
460LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
461
462BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
463BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
464# Benchmark modules
465BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
466BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
467ifeq ($(ARCH), x86)
468ifeq ($(IS_64_BIT), 1)
469BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
470BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
471endif
472endif
473BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
474BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
475BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
476BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
477
478BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
479BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
480BUILTIN_OBJS += $(OUTPUT)builtin-help.o
481BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
482BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
483BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
484BUILTIN_OBJS += $(OUTPUT)builtin-list.o
485BUILTIN_OBJS += $(OUTPUT)builtin-record.o
486BUILTIN_OBJS += $(OUTPUT)builtin-report.o
487BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
488BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
489BUILTIN_OBJS += $(OUTPUT)builtin-top.o
490BUILTIN_OBJS += $(OUTPUT)builtin-script.o
491BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
492BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
493BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
494BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
495BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
496BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
497BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
498
499PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT)
500 228
501# We choose to avoid "if .. else if .. else .. endif endif" 229# We choose to avoid "if .. else if .. else .. endif endif"
502# because maintaining the nesting to match is a pain. If 230# because maintaining the nesting to match is a pain. If
@@ -508,67 +236,9 @@ ifneq ($(OUTPUT),)
508 CFLAGS += -I$(OUTPUT) 236 CFLAGS += -I$(OUTPUT)
509endif 237endif
510 238
511ifdef NO_LIBELF
512# Remove ELF/DWARF dependent codes
513LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
514LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
515LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
516LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
517
518BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
519
520# Use minimal symbol handling
521LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
522
523else # NO_LIBELF
524ifndef NO_DWARF
525 LIB_OBJS += $(OUTPUT)util/probe-finder.o
526 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
527endif # NO_DWARF
528endif # NO_LIBELF
529
530ifndef NO_LIBDW_DWARF_UNWIND
531 LIB_OBJS += $(OUTPUT)util/unwind-libdw.o
532 LIB_H += util/unwind-libdw.h
533endif
534
535ifndef NO_LIBUNWIND
536 LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o
537endif
538LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
539
540ifndef NO_LIBAUDIT
541 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
542endif
543
544ifndef NO_SLANG
545 LIB_OBJS += $(OUTPUT)ui/browser.o
546 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
547 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
548 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
549 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
550 LIB_OBJS += $(OUTPUT)ui/browsers/header.o
551 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
552 LIB_OBJS += $(OUTPUT)ui/tui/util.o
553 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
554 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
555 LIB_H += ui/tui/tui.h
556 LIB_H += ui/browser.h
557 LIB_H += ui/browsers/map.h
558 LIB_H += ui/keysyms.h
559 LIB_H += ui/libslang.h
560endif
561
562ifndef NO_GTK2 239ifndef NO_GTK2
563 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so 240 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
564 241 GTK_IN := $(OUTPUT)gtk-in.o
565 GTK_OBJS += $(OUTPUT)ui/gtk/browser.o
566 GTK_OBJS += $(OUTPUT)ui/gtk/hists.o
567 GTK_OBJS += $(OUTPUT)ui/gtk/setup.o
568 GTK_OBJS += $(OUTPUT)ui/gtk/util.o
569 GTK_OBJS += $(OUTPUT)ui/gtk/helpline.o
570 GTK_OBJS += $(OUTPUT)ui/gtk/progress.o
571 GTK_OBJS += $(OUTPUT)ui/gtk/annotate.o
572 242
573install-gtk: $(OUTPUT)libperf-gtk.so 243install-gtk: $(OUTPUT)libperf-gtk.so
574 $(call QUIET_INSTALL, 'GTK UI') \ 244 $(call QUIET_INSTALL, 'GTK UI') \
@@ -576,31 +246,6 @@ install-gtk: $(OUTPUT)libperf-gtk.so
576 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)' 246 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
577endif 247endif
578 248
579ifndef NO_LIBPERL
580 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
581 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
582endif
583
584ifndef NO_LIBPYTHON
585 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
586 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
587endif
588
589ifeq ($(NO_PERF_REGS),0)
590 ifeq ($(ARCH),x86)
591 LIB_H += arch/x86/include/perf_regs.h
592 endif
593 LIB_OBJS += $(OUTPUT)util/perf_regs.o
594endif
595
596ifndef NO_LIBNUMA
597 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
598endif
599
600ifndef NO_ZLIB
601 LIB_OBJS += $(OUTPUT)util/zlib.o
602endif
603
604ifdef ASCIIDOC8 249ifdef ASCIIDOC8
605 export ASCIIDOC8 250 export ASCIIDOC8
606endif 251endif
@@ -616,39 +261,29 @@ SHELL = $(SHELL_PATH)
616all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) 261all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
617 262
618please_set_SHELL_PATH_to_a_more_modern_shell: 263please_set_SHELL_PATH_to_a_more_modern_shell:
619 @$$(:) 264 $(Q)$$(:)
620 265
621shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell 266shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
622 267
623strip: $(PROGRAMS) $(OUTPUT)perf 268strip: $(PROGRAMS) $(OUTPUT)perf
624 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf 269 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
625 270
626$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 271PERF_IN := $(OUTPUT)perf-in.o
627 $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
628 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
629 $(CFLAGS) -c $(filter %.c,$^) -o $@
630 272
631$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS) 273export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX
632 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \ 274build := -f $(srctree)/tools/build/Makefile.build dir=. obj
633 $(BUILTIN_OBJS) $(LIBS) -o $@
634 275
635$(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H) 276$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
636 $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $< 277 $(Q)$(MAKE) $(build)=perf
637 278
638$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS) 279$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN)
639 $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS) 280 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(PERF_IN) $(LIBS) -o $@
640 281
641$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 282$(GTK_IN): FORCE
642 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ 283 $(Q)$(MAKE) $(build)=gtk
643 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
644 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
645 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
646 284
647$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 285$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS)
648 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ 286 $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
649 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
650 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
651 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
652 287
653$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt 288$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
654 289
@@ -659,8 +294,7 @@ $(SCRIPTS) : % : %.sh
659 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@' 294 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
660 295
661# These can record PERF_VERSION 296# These can record PERF_VERSION
662$(OUTPUT)perf.o perf.spec \ 297perf.spec $(SCRIPTS) \
663 $(SCRIPTS) \
664 : $(OUTPUT)PERF-VERSION-FILE 298 : $(OUTPUT)PERF-VERSION-FILE
665 299
666.SUFFIXES: 300.SUFFIXES:
@@ -683,90 +317,33 @@ endif
683# These two need to be here so that when O= is not used they take precedence 317# These two need to be here so that when O= is not used they take precedence
684# over the general rule for .o 318# over the general rule for .o
685 319
686$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS 320# get relative building directory (to $(OUTPUT))
687 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $< 321# and '.' if it's $(OUTPUT) itself
688 322__build-dir = $(subst $(OUTPUT),,$(dir $@))
689$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS 323build-dir = $(if $(__build-dir),$(__build-dir),.)
690 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
691
692$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
693 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
694$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
695 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
696$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
697 $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
698$(OUTPUT)%.o: %.S
699 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
700$(OUTPUT)%.s: %.S
701 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
702
703$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
704 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
705 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
706 '-DPREFIX="$(prefix_SQ)"' \
707 $<
708
709$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
710 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
711 '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
712 $<
713
714$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
715 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
716 -DPYTHONPATH='"$(OUTPUT)python"' \
717 -DPYTHON='"$(PYTHON_WORD)"' \
718 $<
719
720$(OUTPUT)tests/dwarf-unwind.o: tests/dwarf-unwind.c
721 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -fno-optimize-sibling-calls $<
722 324
723$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS 325single_dep: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
724 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
725 326
726$(OUTPUT)ui/setup.o: ui/setup.c $(OUTPUT)PERF-CFLAGS 327$(OUTPUT)%.o: %.c single_dep FORCE
727 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DLIBDIR='"$(libdir_SQ)"' $< 328 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
728 329
729$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS 330$(OUTPUT)%.i: %.c single_dep FORCE
730 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 331 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
731 332
732$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS 333$(OUTPUT)%.s: %.c single_dep FORCE
733 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 334 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
734 335
735$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 336$(OUTPUT)%-bison.o: %.c single_dep FORCE
736 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 337 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
737 338
738$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 339$(OUTPUT)%-flex.o: %.c single_dep FORCE
739 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 340 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
740 341
741$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS 342$(OUTPUT)%.o: %.S single_dep FORCE
742 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 343 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
743 344
744$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS 345$(OUTPUT)%.i: %.S single_dep FORCE
745 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $< 346 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
746
747$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
748 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
749
750$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS
751 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
752
753$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS
754 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
755
756$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
757 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
758
759$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
760 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
761
762$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
763 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
764
765$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
766 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
767
768$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
769 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
770 347
771$(OUTPUT)perf-%: %.o $(PERFLIBS) 348$(OUTPUT)perf-%: %.o $(PERFLIBS)
772 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS) 349 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
@@ -781,58 +358,34 @@ $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
781 $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c 358 $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
782endif 359endif
783 360
784$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) 361$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
785$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
786 362
787# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So 363LIBPERF_IN := $(OUTPUT)libperf-in.o
788# we depend the various files onto their directories.
789DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
790DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
791# no need to add flex objects, because they depend on bison ones
792DIRECTORY_DEPS += $(OUTPUT)util/parse-events-bison.c
793DIRECTORY_DEPS += $(OUTPUT)util/pmu-bison.c
794 364
795OUTPUT_DIRECTORIES := $(sort $(dir $(DIRECTORY_DEPS))) 365$(LIBPERF_IN): FORCE
366 $(Q)$(MAKE) $(build)=libperf
796 367
797$(DIRECTORY_DEPS): | $(OUTPUT_DIRECTORIES) 368$(LIB_FILE): $(LIBPERF_IN)
798# In the second step, we make a rule to actually create these directories 369 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS)
799$(OUTPUT_DIRECTORIES):
800 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
801 370
802$(LIB_FILE): $(LIB_OBJS)
803 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
804
805# libtraceevent.a
806TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
807
808LIBTRACEEVENT_FLAGS = $(QUIET_SUBDIR1) O=$(OUTPUT)
809LIBTRACEEVENT_FLAGS += CFLAGS="-g -Wall $(EXTRA_CFLAGS)"
810LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 371LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
811 372
812$(LIBTRACEEVENT): $(TE_SOURCES) $(OUTPUT)PERF-CFLAGS 373$(LIBTRACEEVENT): FORCE
813 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) libtraceevent.a plugins 374 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a plugins
814 375
815$(LIBTRACEEVENT)-clean: 376$(LIBTRACEEVENT)-clean:
816 $(call QUIET_CLEAN, libtraceevent) 377 $(call QUIET_CLEAN, libtraceevent)
817 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null 378 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
818 379
819install-traceevent-plugins: $(LIBTRACEEVENT) 380install-traceevent-plugins: $(LIBTRACEEVENT)
820 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins 381 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins
821 382
822LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch] $(LIB_PATH)fd/*.[ch]) 383$(LIBAPI): FORCE
823 384 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a
824# if subdir is set, we've been called from above so target has been built
825# already
826$(LIBAPIKFS): $(LIBAPIKFS_SOURCES)
827ifeq ($(subdir),)
828 $(QUIET_SUBDIR0)$(LIB_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libapikfs.a
829endif
830 385
831$(LIBAPIKFS)-clean: 386$(LIBAPI)-clean:
832ifeq ($(subdir),) 387 $(call QUIET_CLEAN, libapi)
833 $(call QUIET_CLEAN, libapikfs) 388 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
834 @$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
835endif
836 389
837help: 390help:
838 @echo 'Perf make targets:' 391 @echo 'Perf make targets:'
@@ -888,17 +441,6 @@ cscope:
888 $(QUIET_GEN)$(RM) cscope*; \ 441 $(QUIET_GEN)$(RM) cscope*; \
889 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES) 442 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES)
890 443
891### Detect prefix changes
892TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
893 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):$(plugindir_SQ)
894
895$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
896 @FLAGS='$(TRACK_CFLAGS)'; \
897 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
898 echo 1>&2 " FLAGS: * new build flags or prefix"; \
899 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
900 fi
901
902### Testing rules 444### Testing rules
903 445
904# GNU make supports exporting all variables by "export" without parameters. 446# GNU make supports exporting all variables by "export" without parameters.
@@ -981,12 +523,14 @@ $(INSTALL_DOC_TARGETS):
981# 523#
982config-clean: 524config-clean:
983 $(call QUIET_CLEAN, config) 525 $(call QUIET_CLEAN, config)
984 @$(MAKE) -C config/feature-checks clean >/dev/null 526 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
985 527
986clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 528clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
987 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 529 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
530 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
531 $(Q)$(RM) .config-detected
988 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 532 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
989 $(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* 533 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
990 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 534 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
991 $(python-clean) 535 $(python-clean)
992 536
@@ -1000,7 +544,9 @@ else
1000 GIT-HEAD-PHONY = 544 GIT-HEAD-PHONY =
1001endif 545endif
1002 546
547FORCE:
548
1003.PHONY: all install clean config-clean strip install-gtk 549.PHONY: all install clean config-clean strip install-gtk
1004.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 550.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
1005.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope .FORCE-PERF-CFLAGS 551.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep
1006 552
diff --git a/tools/perf/arch/Build b/tools/perf/arch/Build
new file mode 100644
index 000000000000..109eb75cf7de
--- /dev/null
+++ b/tools/perf/arch/Build
@@ -0,0 +1,2 @@
1libperf-y += common.o
2libperf-y += $(ARCH)/
diff --git a/tools/perf/arch/arm/Build b/tools/perf/arch/arm/Build
new file mode 100644
index 000000000000..41bf61da476a
--- /dev/null
+++ b/tools/perf/arch/arm/Build
@@ -0,0 +1,2 @@
1libperf-y += util/
2libperf-$(CONFIG_DWARF_UNWIND) += tests/
diff --git a/tools/perf/arch/arm/Makefile b/tools/perf/arch/arm/Makefile
index 09d62153d384..7fbca175099e 100644
--- a/tools/perf/arch/arm/Makefile
+++ b/tools/perf/arch/arm/Makefile
@@ -1,14 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif
5ifndef NO_LIBUNWIND
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
14endif 3endif
diff --git a/tools/perf/arch/arm/tests/Build b/tools/perf/arch/arm/tests/Build
new file mode 100644
index 000000000000..b30eff9bcc83
--- /dev/null
+++ b/tools/perf/arch/arm/tests/Build
@@ -0,0 +1,2 @@
1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
new file mode 100644
index 000000000000..d22e3d07de3d
--- /dev/null
+++ b/tools/perf/arch/arm/util/Build
@@ -0,0 +1,4 @@
1libperf-$(CONFIG_DWARF) += dwarf-regs.o
2
3libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
4libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/arm64/Build b/tools/perf/arch/arm64/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/arm64/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/arm64/Makefile b/tools/perf/arch/arm64/Makefile
index 67e9b3d38e89..7fbca175099e 100644
--- a/tools/perf/arch/arm64/Makefile
+++ b/tools/perf/arch/arm64/Makefile
@@ -1,7 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif
5ifndef NO_LIBUNWIND
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
7endif 3endif
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
new file mode 100644
index 000000000000..e58123a8912b
--- /dev/null
+++ b/tools/perf/arch/arm64/util/Build
@@ -0,0 +1,2 @@
1libperf-$(CONFIG_DWARF) += dwarf-regs.o
2libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
diff --git a/tools/perf/arch/powerpc/Build b/tools/perf/arch/powerpc/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/powerpc/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 6f7782bea5dd..7fbca175099e 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -1,6 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
5endif 3endif
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
new file mode 100644
index 000000000000..0af6e9b3f728
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/Build
@@ -0,0 +1,4 @@
1libperf-y += header.o
2
3libperf-$(CONFIG_DWARF) += dwarf-regs.o
4libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/s390/Build b/tools/perf/arch/s390/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/s390/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile
index 798ac7379c5f..21322e0385b8 100644
--- a/tools/perf/arch/s390/Makefile
+++ b/tools/perf/arch/s390/Makefile
@@ -1,7 +1,4 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 3endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
6HAVE_KVM_STAT_SUPPORT := 1 4HAVE_KVM_STAT_SUPPORT := 1
7LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
new file mode 100644
index 000000000000..8a61372bb47a
--- /dev/null
+++ b/tools/perf/arch/s390/util/Build
@@ -0,0 +1,4 @@
1libperf-y += header.o
2libperf-y += kvm-stat.o
3
4libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/sh/Build b/tools/perf/arch/sh/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/sh/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/sh/Makefile b/tools/perf/arch/sh/Makefile
index 15130b50dfe3..7fbca175099e 100644
--- a/tools/perf/arch/sh/Makefile
+++ b/tools/perf/arch/sh/Makefile
@@ -1,4 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 3endif
diff --git a/tools/perf/arch/sh/util/Build b/tools/perf/arch/sh/util/Build
new file mode 100644
index 000000000000..954e287bbb89
--- /dev/null
+++ b/tools/perf/arch/sh/util/Build
@@ -0,0 +1 @@
libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/sparc/Build b/tools/perf/arch/sparc/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/sparc/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/sparc/Makefile b/tools/perf/arch/sparc/Makefile
index 15130b50dfe3..7fbca175099e 100644
--- a/tools/perf/arch/sparc/Makefile
+++ b/tools/perf/arch/sparc/Makefile
@@ -1,4 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 3endif
diff --git a/tools/perf/arch/sparc/util/Build b/tools/perf/arch/sparc/util/Build
new file mode 100644
index 000000000000..954e287bbb89
--- /dev/null
+++ b/tools/perf/arch/sparc/util/Build
@@ -0,0 +1 @@
libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/x86/Build b/tools/perf/arch/x86/Build
new file mode 100644
index 000000000000..41bf61da476a
--- /dev/null
+++ b/tools/perf/arch/x86/Build
@@ -0,0 +1,2 @@
1libperf-y += util/
2libperf-$(CONFIG_DWARF_UNWIND) += tests/
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 9b21881db52f..21322e0385b8 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -1,19 +1,4 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 3endif
5ifndef NO_LIBUNWIND
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
14endif
15LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
16LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
17LIB_H += arch/$(ARCH)/util/tsc.h
18HAVE_KVM_STAT_SUPPORT := 1 4HAVE_KVM_STAT_SUPPORT := 1
19LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
new file mode 100644
index 000000000000..b30eff9bcc83
--- /dev/null
+++ b/tools/perf/arch/x86/tests/Build
@@ -0,0 +1,2 @@
1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
new file mode 100644
index 000000000000..cfbccc4e3187
--- /dev/null
+++ b/tools/perf/arch/x86/util/Build
@@ -0,0 +1,8 @@
1libperf-y += header.o
2libperf-y += tsc.o
3libperf-y += kvm-stat.o
4
5libperf-$(CONFIG_DWARF) += dwarf-regs.o
6
7libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
8libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build
new file mode 100644
index 000000000000..5ce98023d518
--- /dev/null
+++ b/tools/perf/bench/Build
@@ -0,0 +1,11 @@
1perf-y += sched-messaging.o
2perf-y += sched-pipe.o
3perf-y += mem-memcpy.o
4perf-y += futex-hash.o
5perf-y += futex-wake.o
6perf-y += futex-requeue.o
7
8perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o
9perf-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o
10
11perf-$(CONFIG_NUMA) += numa.o
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
index d66ab799b35f..8c0c1a2770c8 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -1,12 +1,12 @@
1 1
2MEMCPY_FN(__memcpy, 2MEMCPY_FN(memcpy_orig,
3 "x86-64-unrolled", 3 "x86-64-unrolled",
4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S") 4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S")
5 5
6MEMCPY_FN(memcpy_c, 6MEMCPY_FN(__memcpy,
7 "x86-64-movsq", 7 "x86-64-movsq",
8 "movsq-based memcpy() in arch/x86/lib/memcpy_64.S") 8 "movsq-based memcpy() in arch/x86/lib/memcpy_64.S")
9 9
10MEMCPY_FN(memcpy_c_e, 10MEMCPY_FN(memcpy_erms,
11 "x86-64-movsb", 11 "x86-64-movsb",
12 "movsb-based memcpy() in arch/x86/lib/memcpy_64.S") 12 "movsb-based memcpy() in arch/x86/lib/memcpy_64.S")
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index fcd9cf00600a..e4c2c30143b9 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,8 +1,6 @@
1#define memcpy MEMCPY /* don't hide glibc's memcpy() */ 1#define memcpy MEMCPY /* don't hide glibc's memcpy() */
2#define altinstr_replacement text 2#define altinstr_replacement text
3#define globl p2align 4; .globl 3#define globl p2align 4; .globl
4#define Lmemcpy_c globl memcpy_c; memcpy_c
5#define Lmemcpy_c_e globl memcpy_c_e; memcpy_c_e
6#include "../../../arch/x86/lib/memcpy_64.S" 4#include "../../../arch/x86/lib/memcpy_64.S"
7/* 5/*
8 * We need to provide note.GNU-stack section, saying that we want 6 * We need to provide note.GNU-stack section, saying that we want
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 6c14afe8c1b1..d3dfb7936dcd 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -36,7 +36,7 @@ static const struct option options[] = {
36 "Specify length of memory to copy. " 36 "Specify length of memory to copy. "
37 "Available units: B, KB, MB, GB and TB (upper and lower)"), 37 "Available units: B, KB, MB, GB and TB (upper and lower)"),
38 OPT_STRING('r', "routine", &routine, "default", 38 OPT_STRING('r', "routine", &routine, "default",
39 "Specify routine to copy"), 39 "Specify routine to copy, \"all\" runs all available routines"),
40 OPT_INTEGER('i', "iterations", &iterations, 40 OPT_INTEGER('i', "iterations", &iterations,
41 "repeat memcpy() invocation this number of times"), 41 "repeat memcpy() invocation this number of times"),
42 OPT_BOOLEAN('c', "cycle", &use_cycle, 42 OPT_BOOLEAN('c', "cycle", &use_cycle,
@@ -135,55 +135,16 @@ struct bench_mem_info {
135 const char *const *usage; 135 const char *const *usage;
136}; 136};
137 137
138static int bench_mem_common(int argc, const char **argv, 138static void __bench_mem_routine(struct bench_mem_info *info, int r_idx, size_t len, double totallen)
139 const char *prefix __maybe_unused,
140 struct bench_mem_info *info)
141{ 139{
142 int i; 140 const struct routine *r = &info->routines[r_idx];
143 size_t len;
144 double totallen;
145 double result_bps[2]; 141 double result_bps[2];
146 u64 result_cycle[2]; 142 u64 result_cycle[2];
147 143
148 argc = parse_options(argc, argv, options,
149 info->usage, 0);
150
151 if (no_prefault && only_prefault) {
152 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
153 return 1;
154 }
155
156 if (use_cycle)
157 init_cycle();
158
159 len = (size_t)perf_atoll((char *)length_str);
160 totallen = (double)len * iterations;
161
162 result_cycle[0] = result_cycle[1] = 0ULL; 144 result_cycle[0] = result_cycle[1] = 0ULL;
163 result_bps[0] = result_bps[1] = 0.0; 145 result_bps[0] = result_bps[1] = 0.0;
164 146
165 if ((s64)len <= 0) { 147 printf("Routine %s (%s)\n", r->name, r->desc);
166 fprintf(stderr, "Invalid length:%s\n", length_str);
167 return 1;
168 }
169
170 /* same to without specifying either of prefault and no-prefault */
171 if (only_prefault && no_prefault)
172 only_prefault = no_prefault = false;
173
174 for (i = 0; info->routines[i].name; i++) {
175 if (!strcmp(info->routines[i].name, routine))
176 break;
177 }
178 if (!info->routines[i].name) {
179 printf("Unknown routine:%s\n", routine);
180 printf("Available routines...\n");
181 for (i = 0; info->routines[i].name; i++) {
182 printf("\t%s ... %s\n",
183 info->routines[i].name, info->routines[i].desc);
184 }
185 return 1;
186 }
187 148
188 if (bench_format == BENCH_FORMAT_DEFAULT) 149 if (bench_format == BENCH_FORMAT_DEFAULT)
189 printf("# Copying %s Bytes ...\n\n", length_str); 150 printf("# Copying %s Bytes ...\n\n", length_str);
@@ -191,28 +152,17 @@ static int bench_mem_common(int argc, const char **argv,
191 if (!only_prefault && !no_prefault) { 152 if (!only_prefault && !no_prefault) {
192 /* show both of results */ 153 /* show both of results */
193 if (use_cycle) { 154 if (use_cycle) {
194 result_cycle[0] = 155 result_cycle[0] = info->do_cycle(r, len, false);
195 info->do_cycle(&info->routines[i], len, false); 156 result_cycle[1] = info->do_cycle(r, len, true);
196 result_cycle[1] =
197 info->do_cycle(&info->routines[i], len, true);
198 } else { 157 } else {
199 result_bps[0] = 158 result_bps[0] = info->do_gettimeofday(r, len, false);
200 info->do_gettimeofday(&info->routines[i], 159 result_bps[1] = info->do_gettimeofday(r, len, true);
201 len, false);
202 result_bps[1] =
203 info->do_gettimeofday(&info->routines[i],
204 len, true);
205 } 160 }
206 } else { 161 } else {
207 if (use_cycle) { 162 if (use_cycle)
208 result_cycle[pf] = 163 result_cycle[pf] = info->do_cycle(r, len, only_prefault);
209 info->do_cycle(&info->routines[i], 164 else
210 len, only_prefault); 165 result_bps[pf] = info->do_gettimeofday(r, len, only_prefault);
211 } else {
212 result_bps[pf] =
213 info->do_gettimeofday(&info->routines[i],
214 len, only_prefault);
215 }
216 } 166 }
217 167
218 switch (bench_format) { 168 switch (bench_format) {
@@ -265,6 +215,60 @@ static int bench_mem_common(int argc, const char **argv,
265 die("unknown format: %d\n", bench_format); 215 die("unknown format: %d\n", bench_format);
266 break; 216 break;
267 } 217 }
218}
219
220static int bench_mem_common(int argc, const char **argv,
221 const char *prefix __maybe_unused,
222 struct bench_mem_info *info)
223{
224 int i;
225 size_t len;
226 double totallen;
227
228 argc = parse_options(argc, argv, options,
229 info->usage, 0);
230
231 if (no_prefault && only_prefault) {
232 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
233 return 1;
234 }
235
236 if (use_cycle)
237 init_cycle();
238
239 len = (size_t)perf_atoll((char *)length_str);
240 totallen = (double)len * iterations;
241
242 if ((s64)len <= 0) {
243 fprintf(stderr, "Invalid length:%s\n", length_str);
244 return 1;
245 }
246
247 /* same to without specifying either of prefault and no-prefault */
248 if (only_prefault && no_prefault)
249 only_prefault = no_prefault = false;
250
251 if (!strncmp(routine, "all", 3)) {
252 for (i = 0; info->routines[i].name; i++)
253 __bench_mem_routine(info, i, len, totallen);
254 return 0;
255 }
256
257 for (i = 0; info->routines[i].name; i++) {
258 if (!strcmp(info->routines[i].name, routine))
259 break;
260 }
261 if (!info->routines[i].name) {
262 printf("Unknown routine:%s\n", routine);
263 printf("Available routines...\n");
264 for (i = 0; info->routines[i].name; i++) {
265 printf("\t%s ... %s\n",
266 info->routines[i].name, info->routines[i].desc);
267 }
268 return 1;
269 }
270
271 __bench_mem_routine(info, i, len, totallen);
268 272
269 return 0; 273 return 0;
270} 274}
@@ -289,7 +293,7 @@ static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault)
289 memcpy_t fn = r->fn.memcpy; 293 memcpy_t fn = r->fn.memcpy;
290 int i; 294 int i;
291 295
292 memcpy_alloc_mem(&src, &dst, len); 296 memcpy_alloc_mem(&dst, &src, len);
293 297
294 if (prefault) 298 if (prefault)
295 fn(dst, src, len); 299 fn(dst, src, len);
@@ -312,7 +316,7 @@ static double do_memcpy_gettimeofday(const struct routine *r, size_t len,
312 void *src = NULL, *dst = NULL; 316 void *src = NULL, *dst = NULL;
313 int i; 317 int i;
314 318
315 memcpy_alloc_mem(&src, &dst, len); 319 memcpy_alloc_mem(&dst, &src, len);
316 320
317 if (prefault) 321 if (prefault)
318 fn(dst, src, len); 322 fn(dst, src, len);
diff --git a/tools/perf/bench/mem-memset-x86-64-asm-def.h b/tools/perf/bench/mem-memset-x86-64-asm-def.h
index a71dff97c1f5..f02d028771d9 100644
--- a/tools/perf/bench/mem-memset-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memset-x86-64-asm-def.h
@@ -1,12 +1,12 @@
1 1
2MEMSET_FN(__memset, 2MEMSET_FN(memset_orig,
3 "x86-64-unrolled", 3 "x86-64-unrolled",
4 "unrolled memset() in arch/x86/lib/memset_64.S") 4 "unrolled memset() in arch/x86/lib/memset_64.S")
5 5
6MEMSET_FN(memset_c, 6MEMSET_FN(__memset,
7 "x86-64-stosq", 7 "x86-64-stosq",
8 "movsq-based memset() in arch/x86/lib/memset_64.S") 8 "movsq-based memset() in arch/x86/lib/memset_64.S")
9 9
10MEMSET_FN(memset_c_e, 10MEMSET_FN(memset_erms,
11 "x86-64-stosb", 11 "x86-64-stosb",
12 "movsb-based memset() in arch/x86/lib/memset_64.S") 12 "movsb-based memset() in arch/x86/lib/memset_64.S")
diff --git a/tools/perf/bench/mem-memset-x86-64-asm.S b/tools/perf/bench/mem-memset-x86-64-asm.S
index 9e5af89ed13a..de278784c866 100644
--- a/tools/perf/bench/mem-memset-x86-64-asm.S
+++ b/tools/perf/bench/mem-memset-x86-64-asm.S
@@ -1,8 +1,6 @@
1#define memset MEMSET /* don't hide glibc's memset() */ 1#define memset MEMSET /* don't hide glibc's memset() */
2#define altinstr_replacement text 2#define altinstr_replacement text
3#define globl p2align 4; .globl 3#define globl p2align 4; .globl
4#define Lmemset_c globl memset_c; memset_c
5#define Lmemset_c_e globl memset_c_e; memset_c_e
6#include "../../../arch/x86/lib/memset_64.S" 4#include "../../../arch/x86/lib/memset_64.S"
7 5
8/* 6/*
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 747f86103599..71bf7451c0ca 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -208,7 +208,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
208 goto out; 208 goto out;
209 } 209 }
210 210
211 ret = perf_session__process_events(session, &ann->tool); 211 ret = perf_session__process_events(session);
212 if (ret) 212 if (ret)
213 goto out; 213 goto out;
214 214
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 50e6b66aea1f..d47a0cdc71c9 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -125,8 +125,7 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
125 return ret; 125 return ret;
126} 126}
127 127
128static int build_id_cache__add_kcore(const char *filename, const char *debugdir, 128static int build_id_cache__add_kcore(const char *filename, bool force)
129 bool force)
130{ 129{
131 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1]; 130 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
132 char from_dir[PATH_MAX], to_dir[PATH_MAX]; 131 char from_dir[PATH_MAX], to_dir[PATH_MAX];
@@ -143,7 +142,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
143 return -1; 142 return -1;
144 143
145 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", 144 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
146 debugdir, sbuildid); 145 buildid_dir, sbuildid);
147 146
148 if (!force && 147 if (!force &&
149 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { 148 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
@@ -155,7 +154,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
155 return -1; 154 return -1;
156 155
157 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s", 156 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
158 debugdir, sbuildid, dir); 157 buildid_dir, sbuildid, dir);
159 158
160 if (mkdir_p(to_dir, 0755)) 159 if (mkdir_p(to_dir, 0755))
161 return -1; 160 return -1;
@@ -183,7 +182,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
183 return 0; 182 return 0;
184} 183}
185 184
186static int build_id_cache__add_file(const char *filename, const char *debugdir) 185static int build_id_cache__add_file(const char *filename)
187{ 186{
188 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 187 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
189 u8 build_id[BUILD_ID_SIZE]; 188 u8 build_id[BUILD_ID_SIZE];
@@ -195,16 +194,14 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
195 } 194 }
196 195
197 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 196 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
198 err = build_id_cache__add_s(sbuild_id, debugdir, filename, 197 err = build_id_cache__add_s(sbuild_id, filename,
199 false, false); 198 false, false);
200 if (verbose) 199 pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
201 pr_info("Adding %s %s: %s\n", sbuild_id, filename, 200 err ? "FAIL" : "Ok");
202 err ? "FAIL" : "Ok");
203 return err; 201 return err;
204} 202}
205 203
206static int build_id_cache__remove_file(const char *filename, 204static int build_id_cache__remove_file(const char *filename)
207 const char *debugdir)
208{ 205{
209 u8 build_id[BUILD_ID_SIZE]; 206 u8 build_id[BUILD_ID_SIZE];
210 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 207 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -217,10 +214,34 @@ static int build_id_cache__remove_file(const char *filename,
217 } 214 }
218 215
219 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 216 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
220 err = build_id_cache__remove_s(sbuild_id, debugdir); 217 err = build_id_cache__remove_s(sbuild_id);
221 if (verbose) 218 pr_debug("Removing %s %s: %s\n", sbuild_id, filename,
222 pr_info("Removing %s %s: %s\n", sbuild_id, filename, 219 err ? "FAIL" : "Ok");
223 err ? "FAIL" : "Ok"); 220
221 return err;
222}
223
224static int build_id_cache__purge_path(const char *pathname)
225{
226 struct strlist *list;
227 struct str_node *pos;
228 int err;
229
230 err = build_id_cache__list_build_ids(pathname, &list);
231 if (err)
232 goto out;
233
234 strlist__for_each(pos, list) {
235 err = build_id_cache__remove_s(pos->s);
236 pr_debug("Removing %s %s: %s\n", pos->s, pathname,
237 err ? "FAIL" : "Ok");
238 if (err)
239 break;
240 }
241 strlist__delete(list);
242
243out:
244 pr_debug("Purging %s: %s\n", pathname, err ? "FAIL" : "Ok");
224 245
225 return err; 246 return err;
226} 247}
@@ -252,13 +273,12 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
252 return 0; 273 return 0;
253} 274}
254 275
255static int build_id_cache__update_file(const char *filename, 276static int build_id_cache__update_file(const char *filename)
256 const char *debugdir)
257{ 277{
258 u8 build_id[BUILD_ID_SIZE]; 278 u8 build_id[BUILD_ID_SIZE];
259 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 279 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
260 280
261 int err; 281 int err = 0;
262 282
263 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 283 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
264 pr_debug("Couldn't read a build-id in %s\n", filename); 284 pr_debug("Couldn't read a build-id in %s\n", filename);
@@ -266,14 +286,14 @@ static int build_id_cache__update_file(const char *filename,
266 } 286 }
267 287
268 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 288 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
269 err = build_id_cache__remove_s(sbuild_id, debugdir); 289 if (build_id_cache__cached(sbuild_id))
270 if (!err) { 290 err = build_id_cache__remove_s(sbuild_id);
271 err = build_id_cache__add_s(sbuild_id, debugdir, filename, 291
272 false, false); 292 if (!err)
273 } 293 err = build_id_cache__add_s(sbuild_id, filename, false, false);
274 if (verbose) 294
275 pr_info("Updating %s %s: %s\n", sbuild_id, filename, 295 pr_debug("Updating %s %s: %s\n", sbuild_id, filename,
276 err ? "FAIL" : "Ok"); 296 err ? "FAIL" : "Ok");
277 297
278 return err; 298 return err;
279} 299}
@@ -287,6 +307,7 @@ int cmd_buildid_cache(int argc, const char **argv,
287 bool force = false; 307 bool force = false;
288 char const *add_name_list_str = NULL, 308 char const *add_name_list_str = NULL,
289 *remove_name_list_str = NULL, 309 *remove_name_list_str = NULL,
310 *purge_name_list_str = NULL,
290 *missing_filename = NULL, 311 *missing_filename = NULL,
291 *update_name_list_str = NULL, 312 *update_name_list_str = NULL,
292 *kcore_filename = NULL; 313 *kcore_filename = NULL;
@@ -304,6 +325,8 @@ int cmd_buildid_cache(int argc, const char **argv,
304 "file", "kcore file to add"), 325 "file", "kcore file to add"),
305 OPT_STRING('r', "remove", &remove_name_list_str, "file list", 326 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
306 "file(s) to remove"), 327 "file(s) to remove"),
328 OPT_STRING('p', "purge", &purge_name_list_str, "path list",
329 "path(s) to remove (remove old caches too)"),
307 OPT_STRING('M', "missing", &missing_filename, "file", 330 OPT_STRING('M', "missing", &missing_filename, "file",
308 "to find missing build ids in the cache"), 331 "to find missing build ids in the cache"),
309 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 332 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -320,6 +343,11 @@ int cmd_buildid_cache(int argc, const char **argv,
320 argc = parse_options(argc, argv, buildid_cache_options, 343 argc = parse_options(argc, argv, buildid_cache_options,
321 buildid_cache_usage, 0); 344 buildid_cache_usage, 0);
322 345
346 if (argc || (!add_name_list_str && !kcore_filename &&
347 !remove_name_list_str && !purge_name_list_str &&
348 !missing_filename && !update_name_list_str))
349 usage_with_options(buildid_cache_usage, buildid_cache_options);
350
323 if (missing_filename) { 351 if (missing_filename) {
324 file.path = missing_filename; 352 file.path = missing_filename;
325 file.force = force; 353 file.force = force;
@@ -338,7 +366,7 @@ int cmd_buildid_cache(int argc, const char **argv,
338 list = strlist__new(true, add_name_list_str); 366 list = strlist__new(true, add_name_list_str);
339 if (list) { 367 if (list) {
340 strlist__for_each(pos, list) 368 strlist__for_each(pos, list)
341 if (build_id_cache__add_file(pos->s, buildid_dir)) { 369 if (build_id_cache__add_file(pos->s)) {
342 if (errno == EEXIST) { 370 if (errno == EEXIST) {
343 pr_debug("%s already in the cache\n", 371 pr_debug("%s already in the cache\n",
344 pos->s); 372 pos->s);
@@ -356,7 +384,25 @@ int cmd_buildid_cache(int argc, const char **argv,
356 list = strlist__new(true, remove_name_list_str); 384 list = strlist__new(true, remove_name_list_str);
357 if (list) { 385 if (list) {
358 strlist__for_each(pos, list) 386 strlist__for_each(pos, list)
359 if (build_id_cache__remove_file(pos->s, buildid_dir)) { 387 if (build_id_cache__remove_file(pos->s)) {
388 if (errno == ENOENT) {
389 pr_debug("%s wasn't in the cache\n",
390 pos->s);
391 continue;
392 }
393 pr_warning("Couldn't remove %s: %s\n",
394 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
395 }
396
397 strlist__delete(list);
398 }
399 }
400
401 if (purge_name_list_str) {
402 list = strlist__new(true, purge_name_list_str);
403 if (list) {
404 strlist__for_each(pos, list)
405 if (build_id_cache__purge_path(pos->s)) {
360 if (errno == ENOENT) { 406 if (errno == ENOENT) {
361 pr_debug("%s wasn't in the cache\n", 407 pr_debug("%s wasn't in the cache\n",
362 pos->s); 408 pos->s);
@@ -377,7 +423,7 @@ int cmd_buildid_cache(int argc, const char **argv,
377 list = strlist__new(true, update_name_list_str); 423 list = strlist__new(true, update_name_list_str);
378 if (list) { 424 if (list) {
379 strlist__for_each(pos, list) 425 strlist__for_each(pos, list)
380 if (build_id_cache__update_file(pos->s, buildid_dir)) { 426 if (build_id_cache__update_file(pos->s)) {
381 if (errno == ENOENT) { 427 if (errno == ENOENT) {
382 pr_debug("%s wasn't in the cache\n", 428 pr_debug("%s wasn't in the cache\n",
383 pos->s); 429 pos->s);
@@ -391,8 +437,7 @@ int cmd_buildid_cache(int argc, const char **argv,
391 } 437 }
392 } 438 }
393 439
394 if (kcore_filename && 440 if (kcore_filename && build_id_cache__add_kcore(kcore_filename, force))
395 build_id_cache__add_kcore(kcore_filename, buildid_dir, force))
396 pr_warning("Couldn't add %s\n", kcore_filename); 441 pr_warning("Couldn't add %s\n", kcore_filename);
397 442
398out: 443out:
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index ed3873b3e238..feb420f74c2d 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -74,7 +74,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
74 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID 74 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
75 */ 75 */
76 if (with_hits || perf_data_file__is_pipe(&file)) 76 if (with_hits || perf_data_file__is_pipe(&file))
77 perf_session__process_events(session, &build_id__mark_dso_hit_ops); 77 perf_session__process_events(session);
78 78
79 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); 79 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
80 perf_session__delete(session); 80 perf_session__delete(session);
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
new file mode 100644
index 000000000000..d6525bc54d13
--- /dev/null
+++ b/tools/perf/builtin-data.c
@@ -0,0 +1,123 @@
1#include <linux/compiler.h>
2#include "builtin.h"
3#include "perf.h"
4#include "debug.h"
5#include "parse-options.h"
6#include "data-convert-bt.h"
7
8typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
9
10struct data_cmd {
11 const char *name;
12 const char *summary;
13 data_cmd_fn_t fn;
14};
15
16static struct data_cmd data_cmds[];
17
18#define for_each_cmd(cmd) \
19 for (cmd = data_cmds; cmd && cmd->name; cmd++)
20
21static const struct option data_options[] = {
22 OPT_END()
23};
24
25static const char * const data_subcommands[] = { "convert", NULL };
26
27static const char *data_usage[] = {
28 "perf data [<common options>] <command> [<options>]",
29 NULL
30};
31
32static void print_usage(void)
33{
34 struct data_cmd *cmd;
35
36 printf("Usage:\n");
37 printf("\t%s\n\n", data_usage[0]);
38 printf("\tAvailable commands:\n");
39
40 for_each_cmd(cmd) {
41 printf("\t %s\t- %s\n", cmd->name, cmd->summary);
42 }
43
44 printf("\n");
45}
46
47static const char * const data_convert_usage[] = {
48 "perf data convert [<options>]",
49 NULL
50};
51
52static int cmd_data_convert(int argc, const char **argv,
53 const char *prefix __maybe_unused)
54{
55 const char *to_ctf = NULL;
56 bool force = false;
57 const struct option options[] = {
58 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
59 OPT_STRING('i', "input", &input_name, "file", "input file name"),
60#ifdef HAVE_LIBBABELTRACE_SUPPORT
61 OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
62#endif
63 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
64 OPT_END()
65 };
66
67#ifndef HAVE_LIBBABELTRACE_SUPPORT
68 pr_err("No conversion support compiled in.\n");
69 return -1;
70#endif
71
72 argc = parse_options(argc, argv, options,
73 data_convert_usage, 0);
74 if (argc) {
75 usage_with_options(data_convert_usage, options);
76 return -1;
77 }
78
79 if (to_ctf) {
80#ifdef HAVE_LIBBABELTRACE_SUPPORT
81 return bt_convert__perf2ctf(input_name, to_ctf, force);
82#else
83 pr_err("The libbabeltrace support is not compiled in.\n");
84 return -1;
85#endif
86 }
87
88 return 0;
89}
90
91static struct data_cmd data_cmds[] = {
92 { "convert", "converts data file between formats", cmd_data_convert },
93 { .name = NULL, },
94};
95
96int cmd_data(int argc, const char **argv, const char *prefix)
97{
98 struct data_cmd *cmd;
99 const char *cmdstr;
100
101 /* No command specified. */
102 if (argc < 2)
103 goto usage;
104
105 argc = parse_options_subcommand(argc, argv, data_options, data_subcommands, data_usage,
106 PARSE_OPT_STOP_AT_NON_OPTION);
107 if (argc < 1)
108 goto usage;
109
110 cmdstr = argv[0];
111
112 for_each_cmd(cmd) {
113 if (strcmp(cmd->name, cmdstr))
114 continue;
115
116 return cmd->fn(argc, argv, prefix);
117 }
118
119 pr_err("Unknown command: %s\n", cmdstr);
120usage:
121 print_usage();
122 return -1;
123}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 74aada554b12..df6307b4050a 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -747,7 +747,7 @@ static int __cmd_diff(void)
747 goto out_delete; 747 goto out_delete;
748 } 748 }
749 749
750 ret = perf_session__process_events(d->session, &tool); 750 ret = perf_session__process_events(d->session);
751 if (ret) { 751 if (ret) {
752 pr_err("Failed to process %s\n", d->file.path); 752 pr_err("Failed to process %s\n", d->file.path);
753 goto out_delete; 753 goto out_delete;
@@ -791,6 +791,8 @@ static const struct option options[] = {
791 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 791 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
792 "dump raw trace in ASCII"), 792 "dump raw trace in ASCII"),
793 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 793 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
794 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
795 "file", "kallsyms pathname"),
794 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 796 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
795 "load module symbols - WARNING: use only with -k and LIVE kernel"), 797 "load module symbols - WARNING: use only with -k and LIVE kernel"),
796 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 798 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -802,7 +804,7 @@ static const struct option options[] = {
802 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 804 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
803 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." 805 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
804 " Please refer the man page for the complete list."), 806 " Please refer the man page for the complete list."),
805 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 807 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
806 "separator for columns, no spaces will be added between " 808 "separator for columns, no spaces will be added between "
807 "columns '.' is reserved."), 809 "columns '.' is reserved."),
808 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 810 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 0f93f859b782..695ec5a50cf2 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -24,6 +24,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
24 struct perf_data_file file = { 24 struct perf_data_file file = {
25 .path = file_name, 25 .path = file_name,
26 .mode = PERF_DATA_MODE_READ, 26 .mode = PERF_DATA_MODE_READ,
27 .force = details->force,
27 }; 28 };
28 29
29 session = perf_session__new(&file, 0, NULL); 30 session = perf_session__new(&file, 0, NULL);
@@ -47,6 +48,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
47 "Show all event attr details"), 48 "Show all event attr details"),
48 OPT_BOOLEAN('g', "group", &details.event_group, 49 OPT_BOOLEAN('g', "group", &details.event_group,
49 "Show event group information"), 50 "Show event group information"),
51 OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
50 OPT_END() 52 OPT_END()
51 }; 53 };
52 const char * const evlist_usage[] = { 54 const char * const evlist_usage[] = {
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 25d20628212e..36486eade1ef 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -437,7 +437,18 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
437 HELP_FORMAT_INFO), 437 HELP_FORMAT_INFO),
438 OPT_END(), 438 OPT_END(),
439 }; 439 };
440 const char * const builtin_help_usage[] = { 440 const char * const builtin_help_subcommands[] = {
441 "buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
442 "record", "report", "bench", "stat", "timechart", "top", "annotate",
443 "script", "sched", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
444#ifdef HAVE_LIBELF_SUPPORT
445 "probe",
446#endif
447#ifdef HAVE_LIBAUDIT_SUPPORT
448 "trace",
449#endif
450 NULL };
451 const char *builtin_help_usage[] = {
441 "perf help [--all] [--man|--web|--info] [command]", 452 "perf help [--all] [--man|--web|--info] [command]",
442 NULL 453 NULL
443 }; 454 };
@@ -448,8 +459,8 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
448 459
449 perf_config(perf_help_config, &help_format); 460 perf_config(perf_help_config, &help_format);
450 461
451 argc = parse_options(argc, argv, builtin_help_options, 462 argc = parse_options_subcommand(argc, argv, builtin_help_options,
452 builtin_help_usage, 0); 463 builtin_help_subcommands, builtin_help_usage, 0);
453 464
454 if (show_all) { 465 if (show_all) {
455 printf("\n usage: %s\n\n", perf_usage_string); 466 printf("\n usage: %s\n\n", perf_usage_string);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index a13641e066f5..40a33d7334cc 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -53,6 +53,13 @@ static int perf_event__repipe_synth(struct perf_tool *tool,
53 return 0; 53 return 0;
54} 54}
55 55
56static int perf_event__repipe_oe_synth(struct perf_tool *tool,
57 union perf_event *event,
58 struct ordered_events *oe __maybe_unused)
59{
60 return perf_event__repipe_synth(tool, event);
61}
62
56static int perf_event__repipe_op2_synth(struct perf_tool *tool, 63static int perf_event__repipe_op2_synth(struct perf_tool *tool,
57 union perf_event *event, 64 union perf_event *event,
58 struct perf_session *session 65 struct perf_session *session
@@ -359,8 +366,6 @@ static int __cmd_inject(struct perf_inject *inject)
359 } else if (inject->sched_stat) { 366 } else if (inject->sched_stat) {
360 struct perf_evsel *evsel; 367 struct perf_evsel *evsel;
361 368
362 inject->tool.ordered_events = true;
363
364 evlist__for_each(session->evlist, evsel) { 369 evlist__for_each(session->evlist, evsel) {
365 const char *name = perf_evsel__name(evsel); 370 const char *name = perf_evsel__name(evsel);
366 371
@@ -379,7 +384,7 @@ static int __cmd_inject(struct perf_inject *inject)
379 if (!file_out->is_pipe) 384 if (!file_out->is_pipe)
380 lseek(fd, session->header.data_offset, SEEK_SET); 385 lseek(fd, session->header.data_offset, SEEK_SET);
381 386
382 ret = perf_session__process_events(session, &inject->tool); 387 ret = perf_session__process_events(session);
383 388
384 if (!file_out->is_pipe) { 389 if (!file_out->is_pipe) {
385 if (inject->build_ids) 390 if (inject->build_ids)
@@ -408,7 +413,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
408 .unthrottle = perf_event__repipe, 413 .unthrottle = perf_event__repipe,
409 .attr = perf_event__repipe_attr, 414 .attr = perf_event__repipe_attr,
410 .tracing_data = perf_event__repipe_op2_synth, 415 .tracing_data = perf_event__repipe_op2_synth,
411 .finished_round = perf_event__repipe_op2_synth, 416 .finished_round = perf_event__repipe_oe_synth,
412 .build_id = perf_event__repipe_op2_synth, 417 .build_id = perf_event__repipe_op2_synth,
413 .id_index = perf_event__repipe_op2_synth, 418 .id_index = perf_event__repipe_op2_synth,
414 }, 419 },
@@ -438,6 +443,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
438 "be more verbose (show build ids, etc)"), 443 "be more verbose (show build ids, etc)"),
439 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", 444 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
440 "kallsyms pathname"), 445 "kallsyms pathname"),
446 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
441 OPT_END() 447 OPT_END()
442 }; 448 };
443 const char * const inject_usage[] = { 449 const char * const inject_usage[] = {
@@ -458,6 +464,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
458 return -1; 464 return -1;
459 } 465 }
460 466
467 inject.tool.ordered_events = inject.sched_stat;
468
461 file.path = inject.input_name; 469 file.path = inject.input_name;
462 inject.session = perf_session__new(&file, true, &inject.tool); 470 inject.session = perf_session__new(&file, true, &inject.tool);
463 if (inject.session == NULL) 471 if (inject.session == NULL)
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index f295141025bc..63ea01349b6e 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -20,6 +20,12 @@
20 20
21#include <linux/rbtree.h> 21#include <linux/rbtree.h>
22#include <linux/string.h> 22#include <linux/string.h>
23#include <locale.h>
24
25static int kmem_slab;
26static int kmem_page;
27
28static long kmem_page_size;
23 29
24struct alloc_stat; 30struct alloc_stat;
25typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 31typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
@@ -225,6 +231,244 @@ static int perf_evsel__process_free_event(struct perf_evsel *evsel,
225 return 0; 231 return 0;
226} 232}
227 233
234static u64 total_page_alloc_bytes;
235static u64 total_page_free_bytes;
236static u64 total_page_nomatch_bytes;
237static u64 total_page_fail_bytes;
238static unsigned long nr_page_allocs;
239static unsigned long nr_page_frees;
240static unsigned long nr_page_fails;
241static unsigned long nr_page_nomatch;
242
243static bool use_pfn;
244
245#define MAX_MIGRATE_TYPES 6
246#define MAX_PAGE_ORDER 11
247
248static int order_stats[MAX_PAGE_ORDER][MAX_MIGRATE_TYPES];
249
250struct page_stat {
251 struct rb_node node;
252 u64 page;
253 int order;
254 unsigned gfp_flags;
255 unsigned migrate_type;
256 u64 alloc_bytes;
257 u64 free_bytes;
258 int nr_alloc;
259 int nr_free;
260};
261
262static struct rb_root page_tree;
263static struct rb_root page_alloc_tree;
264static struct rb_root page_alloc_sorted;
265
266static struct page_stat *search_page(unsigned long page, bool create)
267{
268 struct rb_node **node = &page_tree.rb_node;
269 struct rb_node *parent = NULL;
270 struct page_stat *data;
271
272 while (*node) {
273 s64 cmp;
274
275 parent = *node;
276 data = rb_entry(*node, struct page_stat, node);
277
278 cmp = data->page - page;
279 if (cmp < 0)
280 node = &parent->rb_left;
281 else if (cmp > 0)
282 node = &parent->rb_right;
283 else
284 return data;
285 }
286
287 if (!create)
288 return NULL;
289
290 data = zalloc(sizeof(*data));
291 if (data != NULL) {
292 data->page = page;
293
294 rb_link_node(&data->node, parent, node);
295 rb_insert_color(&data->node, &page_tree);
296 }
297
298 return data;
299}
300
301static int page_stat_cmp(struct page_stat *a, struct page_stat *b)
302{
303 if (a->page > b->page)
304 return -1;
305 if (a->page < b->page)
306 return 1;
307 if (a->order > b->order)
308 return -1;
309 if (a->order < b->order)
310 return 1;
311 if (a->migrate_type > b->migrate_type)
312 return -1;
313 if (a->migrate_type < b->migrate_type)
314 return 1;
315 if (a->gfp_flags > b->gfp_flags)
316 return -1;
317 if (a->gfp_flags < b->gfp_flags)
318 return 1;
319 return 0;
320}
321
322static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool create)
323{
324 struct rb_node **node = &page_alloc_tree.rb_node;
325 struct rb_node *parent = NULL;
326 struct page_stat *data;
327
328 while (*node) {
329 s64 cmp;
330
331 parent = *node;
332 data = rb_entry(*node, struct page_stat, node);
333
334 cmp = page_stat_cmp(data, stat);
335 if (cmp < 0)
336 node = &parent->rb_left;
337 else if (cmp > 0)
338 node = &parent->rb_right;
339 else
340 return data;
341 }
342
343 if (!create)
344 return NULL;
345
346 data = zalloc(sizeof(*data));
347 if (data != NULL) {
348 data->page = stat->page;
349 data->order = stat->order;
350 data->gfp_flags = stat->gfp_flags;
351 data->migrate_type = stat->migrate_type;
352
353 rb_link_node(&data->node, parent, node);
354 rb_insert_color(&data->node, &page_alloc_tree);
355 }
356
357 return data;
358}
359
360static bool valid_page(u64 pfn_or_page)
361{
362 if (use_pfn && pfn_or_page == -1UL)
363 return false;
364 if (!use_pfn && pfn_or_page == 0)
365 return false;
366 return true;
367}
368
369static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
370 struct perf_sample *sample)
371{
372 u64 page;
373 unsigned int order = perf_evsel__intval(evsel, sample, "order");
374 unsigned int gfp_flags = perf_evsel__intval(evsel, sample, "gfp_flags");
375 unsigned int migrate_type = perf_evsel__intval(evsel, sample,
376 "migratetype");
377 u64 bytes = kmem_page_size << order;
378 struct page_stat *stat;
379 struct page_stat this = {
380 .order = order,
381 .gfp_flags = gfp_flags,
382 .migrate_type = migrate_type,
383 };
384
385 if (use_pfn)
386 page = perf_evsel__intval(evsel, sample, "pfn");
387 else
388 page = perf_evsel__intval(evsel, sample, "page");
389
390 nr_page_allocs++;
391 total_page_alloc_bytes += bytes;
392
393 if (!valid_page(page)) {
394 nr_page_fails++;
395 total_page_fail_bytes += bytes;
396
397 return 0;
398 }
399
400 /*
401 * This is to find the current page (with correct gfp flags and
402 * migrate type) at free event.
403 */
404 stat = search_page(page, true);
405 if (stat == NULL)
406 return -ENOMEM;
407
408 stat->order = order;
409 stat->gfp_flags = gfp_flags;
410 stat->migrate_type = migrate_type;
411
412 this.page = page;
413 stat = search_page_alloc_stat(&this, true);
414 if (stat == NULL)
415 return -ENOMEM;
416
417 stat->nr_alloc++;
418 stat->alloc_bytes += bytes;
419
420 order_stats[order][migrate_type]++;
421
422 return 0;
423}
424
425static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
426 struct perf_sample *sample)
427{
428 u64 page;
429 unsigned int order = perf_evsel__intval(evsel, sample, "order");
430 u64 bytes = kmem_page_size << order;
431 struct page_stat *stat;
432 struct page_stat this = {
433 .order = order,
434 };
435
436 if (use_pfn)
437 page = perf_evsel__intval(evsel, sample, "pfn");
438 else
439 page = perf_evsel__intval(evsel, sample, "page");
440
441 nr_page_frees++;
442 total_page_free_bytes += bytes;
443
444 stat = search_page(page, false);
445 if (stat == NULL) {
446 pr_debug2("missing free at page %"PRIx64" (order: %d)\n",
447 page, order);
448
449 nr_page_nomatch++;
450 total_page_nomatch_bytes += bytes;
451
452 return 0;
453 }
454
455 this.page = page;
456 this.gfp_flags = stat->gfp_flags;
457 this.migrate_type = stat->migrate_type;
458
459 rb_erase(&stat->node, &page_tree);
460 free(stat);
461
462 stat = search_page_alloc_stat(&this, false);
463 if (stat == NULL)
464 return -ENOENT;
465
466 stat->nr_free++;
467 stat->free_bytes += bytes;
468
469 return 0;
470}
471
228typedef int (*tracepoint_handler)(struct perf_evsel *evsel, 472typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
229 struct perf_sample *sample); 473 struct perf_sample *sample);
230 474
@@ -269,16 +513,17 @@ static double fragmentation(unsigned long n_req, unsigned long n_alloc)
269 return 100.0 - (100.0 * n_req / n_alloc); 513 return 100.0 - (100.0 * n_req / n_alloc);
270} 514}
271 515
272static void __print_result(struct rb_root *root, struct perf_session *session, 516static void __print_slab_result(struct rb_root *root,
273 int n_lines, int is_caller) 517 struct perf_session *session,
518 int n_lines, int is_caller)
274{ 519{
275 struct rb_node *next; 520 struct rb_node *next;
276 struct machine *machine = &session->machines.host; 521 struct machine *machine = &session->machines.host;
277 522
278 printf("%.102s\n", graph_dotted_line); 523 printf("%.105s\n", graph_dotted_line);
279 printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); 524 printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr");
280 printf(" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n"); 525 printf(" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n");
281 printf("%.102s\n", graph_dotted_line); 526 printf("%.105s\n", graph_dotted_line);
282 527
283 next = rb_first(root); 528 next = rb_first(root);
284 529
@@ -304,7 +549,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
304 snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr); 549 snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
305 printf(" %-34s |", buf); 550 printf(" %-34s |", buf);
306 551
307 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n", 552 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %9lu | %6.3f%%\n",
308 (unsigned long long)data->bytes_alloc, 553 (unsigned long long)data->bytes_alloc,
309 (unsigned long)data->bytes_alloc / data->hit, 554 (unsigned long)data->bytes_alloc / data->hit,
310 (unsigned long long)data->bytes_req, 555 (unsigned long long)data->bytes_req,
@@ -317,30 +562,137 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
317 } 562 }
318 563
319 if (n_lines == -1) 564 if (n_lines == -1)
320 printf(" ... | ... | ... | ... | ... | ... \n"); 565 printf(" ... | ... | ... | ... | ... | ... \n");
321 566
322 printf("%.102s\n", graph_dotted_line); 567 printf("%.105s\n", graph_dotted_line);
323} 568}
324 569
325static void print_summary(void) 570static const char * const migrate_type_str[] = {
571 "UNMOVABL",
572 "RECLAIM",
573 "MOVABLE",
574 "RESERVED",
575 "CMA/ISLT",
576 "UNKNOWN",
577};
578
579static void __print_page_result(struct rb_root *root,
580 struct perf_session *session __maybe_unused,
581 int n_lines)
326{ 582{
327 printf("\nSUMMARY\n=======\n"); 583 struct rb_node *next = rb_first(root);
328 printf("Total bytes requested: %lu\n", total_requested); 584 const char *format;
329 printf("Total bytes allocated: %lu\n", total_allocated); 585
330 printf("Total bytes wasted on internal fragmentation: %lu\n", 586 printf("\n%.80s\n", graph_dotted_line);
587 printf(" %-16s | Total alloc (KB) | Hits | Order | Mig.type | GFP flags\n",
588 use_pfn ? "PFN" : "Page");
589 printf("%.80s\n", graph_dotted_line);
590
591 if (use_pfn)
592 format = " %16llu | %'16llu | %'9d | %5d | %8s | %08lx\n";
593 else
594 format = " %016llx | %'16llu | %'9d | %5d | %8s | %08lx\n";
595
596 while (next && n_lines--) {
597 struct page_stat *data;
598
599 data = rb_entry(next, struct page_stat, node);
600
601 printf(format, (unsigned long long)data->page,
602 (unsigned long long)data->alloc_bytes / 1024,
603 data->nr_alloc, data->order,
604 migrate_type_str[data->migrate_type],
605 (unsigned long)data->gfp_flags);
606
607 next = rb_next(next);
608 }
609
610 if (n_lines == -1)
611 printf(" ... | ... | ... | ... | ... | ... \n");
612
613 printf("%.80s\n", graph_dotted_line);
614}
615
616static void print_slab_summary(void)
617{
618 printf("\nSUMMARY (SLAB allocator)");
619 printf("\n========================\n");
620 printf("Total bytes requested: %'lu\n", total_requested);
621 printf("Total bytes allocated: %'lu\n", total_allocated);
622 printf("Total bytes wasted on internal fragmentation: %'lu\n",
331 total_allocated - total_requested); 623 total_allocated - total_requested);
332 printf("Internal fragmentation: %f%%\n", 624 printf("Internal fragmentation: %f%%\n",
333 fragmentation(total_requested, total_allocated)); 625 fragmentation(total_requested, total_allocated));
334 printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs); 626 printf("Cross CPU allocations: %'lu/%'lu\n", nr_cross_allocs, nr_allocs);
335} 627}
336 628
337static void print_result(struct perf_session *session) 629static void print_page_summary(void)
630{
631 int o, m;
632 u64 nr_alloc_freed = nr_page_frees - nr_page_nomatch;
633 u64 total_alloc_freed_bytes = total_page_free_bytes - total_page_nomatch_bytes;
634
635 printf("\nSUMMARY (page allocator)");
636 printf("\n========================\n");
637 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total allocation requests",
638 nr_page_allocs, total_page_alloc_bytes / 1024);
639 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total free requests",
640 nr_page_frees, total_page_free_bytes / 1024);
641 printf("\n");
642
643 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total alloc+freed requests",
644 nr_alloc_freed, (total_alloc_freed_bytes) / 1024);
645 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total alloc-only requests",
646 nr_page_allocs - nr_alloc_freed,
647 (total_page_alloc_bytes - total_alloc_freed_bytes) / 1024);
648 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total free-only requests",
649 nr_page_nomatch, total_page_nomatch_bytes / 1024);
650 printf("\n");
651
652 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total allocation failures",
653 nr_page_fails, total_page_fail_bytes / 1024);
654 printf("\n");
655
656 printf("%5s %12s %12s %12s %12s %12s\n", "Order", "Unmovable",
657 "Reclaimable", "Movable", "Reserved", "CMA/Isolated");
658 printf("%.5s %.12s %.12s %.12s %.12s %.12s\n", graph_dotted_line,
659 graph_dotted_line, graph_dotted_line, graph_dotted_line,
660 graph_dotted_line, graph_dotted_line);
661
662 for (o = 0; o < MAX_PAGE_ORDER; o++) {
663 printf("%5d", o);
664 for (m = 0; m < MAX_MIGRATE_TYPES - 1; m++) {
665 if (order_stats[o][m])
666 printf(" %'12d", order_stats[o][m]);
667 else
668 printf(" %12c", '.');
669 }
670 printf("\n");
671 }
672}
673
674static void print_slab_result(struct perf_session *session)
338{ 675{
339 if (caller_flag) 676 if (caller_flag)
340 __print_result(&root_caller_sorted, session, caller_lines, 1); 677 __print_slab_result(&root_caller_sorted, session, caller_lines, 1);
341 if (alloc_flag) 678 if (alloc_flag)
342 __print_result(&root_alloc_sorted, session, alloc_lines, 0); 679 __print_slab_result(&root_alloc_sorted, session, alloc_lines, 0);
343 print_summary(); 680 print_slab_summary();
681}
682
683static void print_page_result(struct perf_session *session)
684{
685 if (alloc_flag)
686 __print_page_result(&page_alloc_sorted, session, alloc_lines);
687 print_page_summary();
688}
689
690static void print_result(struct perf_session *session)
691{
692 if (kmem_slab)
693 print_slab_result(session);
694 if (kmem_page)
695 print_page_result(session);
344} 696}
345 697
346struct sort_dimension { 698struct sort_dimension {
@@ -352,8 +704,8 @@ struct sort_dimension {
352static LIST_HEAD(caller_sort); 704static LIST_HEAD(caller_sort);
353static LIST_HEAD(alloc_sort); 705static LIST_HEAD(alloc_sort);
354 706
355static void sort_insert(struct rb_root *root, struct alloc_stat *data, 707static void sort_slab_insert(struct rb_root *root, struct alloc_stat *data,
356 struct list_head *sort_list) 708 struct list_head *sort_list)
357{ 709{
358 struct rb_node **new = &(root->rb_node); 710 struct rb_node **new = &(root->rb_node);
359 struct rb_node *parent = NULL; 711 struct rb_node *parent = NULL;
@@ -382,8 +734,8 @@ static void sort_insert(struct rb_root *root, struct alloc_stat *data,
382 rb_insert_color(&data->node, root); 734 rb_insert_color(&data->node, root);
383} 735}
384 736
385static void __sort_result(struct rb_root *root, struct rb_root *root_sorted, 737static void __sort_slab_result(struct rb_root *root, struct rb_root *root_sorted,
386 struct list_head *sort_list) 738 struct list_head *sort_list)
387{ 739{
388 struct rb_node *node; 740 struct rb_node *node;
389 struct alloc_stat *data; 741 struct alloc_stat *data;
@@ -395,26 +747,79 @@ static void __sort_result(struct rb_root *root, struct rb_root *root_sorted,
395 747
396 rb_erase(node, root); 748 rb_erase(node, root);
397 data = rb_entry(node, struct alloc_stat, node); 749 data = rb_entry(node, struct alloc_stat, node);
398 sort_insert(root_sorted, data, sort_list); 750 sort_slab_insert(root_sorted, data, sort_list);
751 }
752}
753
754static void sort_page_insert(struct rb_root *root, struct page_stat *data)
755{
756 struct rb_node **new = &root->rb_node;
757 struct rb_node *parent = NULL;
758
759 while (*new) {
760 struct page_stat *this;
761 int cmp = 0;
762
763 this = rb_entry(*new, struct page_stat, node);
764 parent = *new;
765
766 /* TODO: support more sort key */
767 cmp = data->alloc_bytes - this->alloc_bytes;
768
769 if (cmp > 0)
770 new = &parent->rb_left;
771 else
772 new = &parent->rb_right;
773 }
774
775 rb_link_node(&data->node, parent, new);
776 rb_insert_color(&data->node, root);
777}
778
779static void __sort_page_result(struct rb_root *root, struct rb_root *root_sorted)
780{
781 struct rb_node *node;
782 struct page_stat *data;
783
784 for (;;) {
785 node = rb_first(root);
786 if (!node)
787 break;
788
789 rb_erase(node, root);
790 data = rb_entry(node, struct page_stat, node);
791 sort_page_insert(root_sorted, data);
399 } 792 }
400} 793}
401 794
402static void sort_result(void) 795static void sort_result(void)
403{ 796{
404 __sort_result(&root_alloc_stat, &root_alloc_sorted, &alloc_sort); 797 if (kmem_slab) {
405 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 798 __sort_slab_result(&root_alloc_stat, &root_alloc_sorted,
799 &alloc_sort);
800 __sort_slab_result(&root_caller_stat, &root_caller_sorted,
801 &caller_sort);
802 }
803 if (kmem_page) {
804 __sort_page_result(&page_alloc_tree, &page_alloc_sorted);
805 }
406} 806}
407 807
408static int __cmd_kmem(struct perf_session *session) 808static int __cmd_kmem(struct perf_session *session)
409{ 809{
410 int err = -EINVAL; 810 int err = -EINVAL;
811 struct perf_evsel *evsel;
411 const struct perf_evsel_str_handler kmem_tracepoints[] = { 812 const struct perf_evsel_str_handler kmem_tracepoints[] = {
813 /* slab allocator */
412 { "kmem:kmalloc", perf_evsel__process_alloc_event, }, 814 { "kmem:kmalloc", perf_evsel__process_alloc_event, },
413 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, 815 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, },
414 { "kmem:kmalloc_node", perf_evsel__process_alloc_node_event, }, 816 { "kmem:kmalloc_node", perf_evsel__process_alloc_node_event, },
415 { "kmem:kmem_cache_alloc_node", perf_evsel__process_alloc_node_event, }, 817 { "kmem:kmem_cache_alloc_node", perf_evsel__process_alloc_node_event, },
416 { "kmem:kfree", perf_evsel__process_free_event, }, 818 { "kmem:kfree", perf_evsel__process_free_event, },
417 { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, 819 { "kmem:kmem_cache_free", perf_evsel__process_free_event, },
820 /* page allocator */
821 { "kmem:mm_page_alloc", perf_evsel__process_page_alloc_event, },
822 { "kmem:mm_page_free", perf_evsel__process_page_free_event, },
418 }; 823 };
419 824
420 if (!perf_session__has_traces(session, "kmem record")) 825 if (!perf_session__has_traces(session, "kmem record"))
@@ -425,10 +830,20 @@ static int __cmd_kmem(struct perf_session *session)
425 goto out; 830 goto out;
426 } 831 }
427 832
833 evlist__for_each(session->evlist, evsel) {
834 if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") &&
835 perf_evsel__field(evsel, "pfn")) {
836 use_pfn = true;
837 break;
838 }
839 }
840
428 setup_pager(); 841 setup_pager();
429 err = perf_session__process_events(session, &perf_kmem); 842 err = perf_session__process_events(session);
430 if (err != 0) 843 if (err != 0) {
844 pr_err("error during process events: %d\n", err);
431 goto out; 845 goto out;
846 }
432 sort_result(); 847 sort_result();
433 print_result(session); 848 print_result(session);
434out: 849out:
@@ -559,6 +974,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
559{ 974{
560 char *tok; 975 char *tok;
561 char *str = strdup(arg); 976 char *str = strdup(arg);
977 char *pos = str;
562 978
563 if (!str) { 979 if (!str) {
564 pr_err("%s: strdup failed\n", __func__); 980 pr_err("%s: strdup failed\n", __func__);
@@ -566,7 +982,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
566 } 982 }
567 983
568 while (true) { 984 while (true) {
569 tok = strsep(&str, ","); 985 tok = strsep(&pos, ",");
570 if (!tok) 986 if (!tok)
571 break; 987 break;
572 if (sort_dimension__add(tok, sort_list) < 0) { 988 if (sort_dimension__add(tok, sort_list) < 0) {
@@ -610,6 +1026,22 @@ static int parse_alloc_opt(const struct option *opt __maybe_unused,
610 return 0; 1026 return 0;
611} 1027}
612 1028
1029static int parse_slab_opt(const struct option *opt __maybe_unused,
1030 const char *arg __maybe_unused,
1031 int unset __maybe_unused)
1032{
1033 kmem_slab = (kmem_page + 1);
1034 return 0;
1035}
1036
1037static int parse_page_opt(const struct option *opt __maybe_unused,
1038 const char *arg __maybe_unused,
1039 int unset __maybe_unused)
1040{
1041 kmem_page = (kmem_slab + 1);
1042 return 0;
1043}
1044
613static int parse_line_opt(const struct option *opt __maybe_unused, 1045static int parse_line_opt(const struct option *opt __maybe_unused,
614 const char *arg, int unset __maybe_unused) 1046 const char *arg, int unset __maybe_unused)
615{ 1047{
@@ -632,6 +1064,8 @@ static int __cmd_record(int argc, const char **argv)
632{ 1064{
633 const char * const record_args[] = { 1065 const char * const record_args[] = {
634 "record", "-a", "-R", "-c", "1", 1066 "record", "-a", "-R", "-c", "1",
1067 };
1068 const char * const slab_events[] = {
635 "-e", "kmem:kmalloc", 1069 "-e", "kmem:kmalloc",
636 "-e", "kmem:kmalloc_node", 1070 "-e", "kmem:kmalloc_node",
637 "-e", "kmem:kfree", 1071 "-e", "kmem:kfree",
@@ -639,10 +1073,19 @@ static int __cmd_record(int argc, const char **argv)
639 "-e", "kmem:kmem_cache_alloc_node", 1073 "-e", "kmem:kmem_cache_alloc_node",
640 "-e", "kmem:kmem_cache_free", 1074 "-e", "kmem:kmem_cache_free",
641 }; 1075 };
1076 const char * const page_events[] = {
1077 "-e", "kmem:mm_page_alloc",
1078 "-e", "kmem:mm_page_free",
1079 };
642 unsigned int rec_argc, i, j; 1080 unsigned int rec_argc, i, j;
643 const char **rec_argv; 1081 const char **rec_argv;
644 1082
645 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 1083 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
1084 if (kmem_slab)
1085 rec_argc += ARRAY_SIZE(slab_events);
1086 if (kmem_page)
1087 rec_argc += ARRAY_SIZE(page_events);
1088
646 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1089 rec_argv = calloc(rec_argc + 1, sizeof(char *));
647 1090
648 if (rec_argv == NULL) 1091 if (rec_argv == NULL)
@@ -651,6 +1094,15 @@ static int __cmd_record(int argc, const char **argv)
651 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1094 for (i = 0; i < ARRAY_SIZE(record_args); i++)
652 rec_argv[i] = strdup(record_args[i]); 1095 rec_argv[i] = strdup(record_args[i]);
653 1096
1097 if (kmem_slab) {
1098 for (j = 0; j < ARRAY_SIZE(slab_events); j++, i++)
1099 rec_argv[i] = strdup(slab_events[j]);
1100 }
1101 if (kmem_page) {
1102 for (j = 0; j < ARRAY_SIZE(page_events); j++, i++)
1103 rec_argv[i] = strdup(page_events[j]);
1104 }
1105
654 for (j = 1; j < (unsigned int)argc; j++, i++) 1106 for (j = 1; j < (unsigned int)argc; j++, i++)
655 rec_argv[i] = argv[j]; 1107 rec_argv[i] = argv[j];
656 1108
@@ -660,8 +1112,13 @@ static int __cmd_record(int argc, const char **argv)
660int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 1112int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
661{ 1113{
662 const char * const default_sort_order = "frag,hit,bytes"; 1114 const char * const default_sort_order = "frag,hit,bytes";
1115 struct perf_data_file file = {
1116 .mode = PERF_DATA_MODE_READ,
1117 };
663 const struct option kmem_options[] = { 1118 const struct option kmem_options[] = {
664 OPT_STRING('i', "input", &input_name, "file", "input file name"), 1119 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1120 OPT_INCR('v', "verbose", &verbose,
1121 "be more verbose (show symbol address, etc)"),
665 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, 1122 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
666 "show per-callsite statistics", parse_caller_opt), 1123 "show per-callsite statistics", parse_caller_opt),
667 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL, 1124 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
@@ -671,6 +1128,11 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
671 parse_sort_opt), 1128 parse_sort_opt),
672 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt), 1129 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
673 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), 1130 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
1131 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
1132 OPT_CALLBACK_NOOPT(0, "slab", NULL, NULL, "Analyze slab allocator",
1133 parse_slab_opt),
1134 OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator",
1135 parse_page_opt),
674 OPT_END() 1136 OPT_END()
675 }; 1137 };
676 const char *const kmem_subcommands[] = { "record", "stat", NULL }; 1138 const char *const kmem_subcommands[] = { "record", "stat", NULL };
@@ -679,10 +1141,6 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
679 NULL 1141 NULL
680 }; 1142 };
681 struct perf_session *session; 1143 struct perf_session *session;
682 struct perf_data_file file = {
683 .path = input_name,
684 .mode = PERF_DATA_MODE_READ,
685 };
686 int ret = -1; 1144 int ret = -1;
687 1145
688 argc = parse_options_subcommand(argc, argv, kmem_options, 1146 argc = parse_options_subcommand(argc, argv, kmem_options,
@@ -691,18 +1149,36 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
691 if (!argc) 1149 if (!argc)
692 usage_with_options(kmem_usage, kmem_options); 1150 usage_with_options(kmem_usage, kmem_options);
693 1151
1152 if (kmem_slab == 0 && kmem_page == 0)
1153 kmem_slab = 1; /* for backward compatibility */
1154
694 if (!strncmp(argv[0], "rec", 3)) { 1155 if (!strncmp(argv[0], "rec", 3)) {
695 symbol__init(NULL); 1156 symbol__init(NULL);
696 return __cmd_record(argc, argv); 1157 return __cmd_record(argc, argv);
697 } 1158 }
698 1159
1160 file.path = input_name;
1161
699 session = perf_session__new(&file, false, &perf_kmem); 1162 session = perf_session__new(&file, false, &perf_kmem);
700 if (session == NULL) 1163 if (session == NULL)
701 return -1; 1164 return -1;
702 1165
1166 if (kmem_page) {
1167 struct perf_evsel *evsel = perf_evlist__first(session->evlist);
1168
1169 if (evsel == NULL || evsel->tp_format == NULL) {
1170 pr_err("invalid event found.. aborting\n");
1171 return -1;
1172 }
1173
1174 kmem_page_size = pevent_get_page_size(evsel->tp_format->pevent);
1175 }
1176
703 symbol__init(&session->header.env); 1177 symbol__init(&session->header.env);
704 1178
705 if (!strcmp(argv[0], "stat")) { 1179 if (!strcmp(argv[0], "stat")) {
1180 setlocale(LC_ALL, "");
1181
706 if (cpu__setup_cpunode_map()) 1182 if (cpu__setup_cpunode_map())
707 goto out_delete; 1183 goto out_delete;
708 1184
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 0894a817f67e..1f9338f6109c 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -18,6 +18,7 @@
18#include "util/stat.h" 18#include "util/stat.h"
19#include "util/top.h" 19#include "util/top.h"
20#include "util/data.h" 20#include "util/data.h"
21#include "util/ordered-events.h"
21 22
22#include <sys/prctl.h> 23#include <sys/prctl.h>
23#ifdef HAVE_TIMERFD_SUPPORT 24#ifdef HAVE_TIMERFD_SUPPORT
@@ -730,9 +731,9 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
730 return -1; 731 return -1;
731 } 732 }
732 733
733 err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0); 734 err = perf_session__queue_event(kvm->session, event, &sample, 0);
734 /* 735 /*
735 * FIXME: Here we can't consume the event, as perf_session_queue_event will 736 * FIXME: Here we can't consume the event, as perf_session__queue_event will
736 * point to it, and it'll get possibly overwritten by the kernel. 737 * point to it, and it'll get possibly overwritten by the kernel.
737 */ 738 */
738 perf_evlist__mmap_consume(kvm->evlist, idx); 739 perf_evlist__mmap_consume(kvm->evlist, idx);
@@ -783,8 +784,10 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
783 784
784 /* flush queue after each round in which we processed events */ 785 /* flush queue after each round in which we processed events */
785 if (ntotal) { 786 if (ntotal) {
786 kvm->session->ordered_events.next_flush = flush_time; 787 struct ordered_events *oe = &kvm->session->ordered_events;
787 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session); 788
789 oe->next_flush = flush_time;
790 err = ordered_events__flush(oe, OE_FLUSH__ROUND);
788 if (err) { 791 if (err) {
789 if (kvm->lost_events) 792 if (kvm->lost_events)
790 pr_info("\nLost events: %" PRIu64 "\n\n", 793 pr_info("\nLost events: %" PRIu64 "\n\n",
@@ -1044,6 +1047,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1044 struct perf_data_file file = { 1047 struct perf_data_file file = {
1045 .path = kvm->file_name, 1048 .path = kvm->file_name,
1046 .mode = PERF_DATA_MODE_READ, 1049 .mode = PERF_DATA_MODE_READ,
1050 .force = kvm->force,
1047 }; 1051 };
1048 1052
1049 kvm->tool = eops; 1053 kvm->tool = eops;
@@ -1066,7 +1070,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1066 if (ret < 0) 1070 if (ret < 0)
1067 return ret; 1071 return ret;
1068 1072
1069 return perf_session__process_events(kvm->session, &kvm->tool); 1073 return perf_session__process_events(kvm->session);
1070} 1074}
1071 1075
1072static int parse_target_str(struct perf_kvm_stat *kvm) 1076static int parse_target_str(struct perf_kvm_stat *kvm)
@@ -1201,6 +1205,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1201 " time (sort by avg time)"), 1205 " time (sort by avg time)"),
1202 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", 1206 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1203 "analyze events only for given process id(s)"), 1207 "analyze events only for given process id(s)"),
1208 OPT_BOOLEAN('f', "force", &kvm->force, "don't complain, do it"),
1204 OPT_END() 1209 OPT_END()
1205 }; 1210 };
1206 1211
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 198f3c3aff95..af5bd0514108 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -36,38 +36,36 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
36 36
37 setup_pager(); 37 setup_pager();
38 38
39 if (raw_dump) { 39 if (!raw_dump)
40 print_events(NULL, true); 40 printf("\nList of pre-defined events (to be used in -e):\n\n");
41 return 0;
42 }
43 41
44 if (argc == 0) { 42 if (argc == 0) {
45 print_events(NULL, false); 43 print_events(NULL, raw_dump);
46 return 0; 44 return 0;
47 } 45 }
48 46
49 for (i = 0; i < argc; ++i) { 47 for (i = 0; i < argc; ++i) {
50 if (i) 48 if (strcmp(argv[i], "tracepoint") == 0)
51 putchar('\n'); 49 print_tracepoint_events(NULL, NULL, raw_dump);
52 if (strncmp(argv[i], "tracepoint", 10) == 0)
53 print_tracepoint_events(NULL, NULL, false);
54 else if (strcmp(argv[i], "hw") == 0 || 50 else if (strcmp(argv[i], "hw") == 0 ||
55 strcmp(argv[i], "hardware") == 0) 51 strcmp(argv[i], "hardware") == 0)
56 print_events_type(PERF_TYPE_HARDWARE); 52 print_symbol_events(NULL, PERF_TYPE_HARDWARE,
53 event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump);
57 else if (strcmp(argv[i], "sw") == 0 || 54 else if (strcmp(argv[i], "sw") == 0 ||
58 strcmp(argv[i], "software") == 0) 55 strcmp(argv[i], "software") == 0)
59 print_events_type(PERF_TYPE_SOFTWARE); 56 print_symbol_events(NULL, PERF_TYPE_SOFTWARE,
57 event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump);
60 else if (strcmp(argv[i], "cache") == 0 || 58 else if (strcmp(argv[i], "cache") == 0 ||
61 strcmp(argv[i], "hwcache") == 0) 59 strcmp(argv[i], "hwcache") == 0)
62 print_hwcache_events(NULL, false); 60 print_hwcache_events(NULL, raw_dump);
63 else if (strcmp(argv[i], "pmu") == 0) 61 else if (strcmp(argv[i], "pmu") == 0)
64 print_pmu_events(NULL, false); 62 print_pmu_events(NULL, raw_dump);
65 else { 63 else {
66 char *sep = strchr(argv[i], ':'), *s; 64 char *sep = strchr(argv[i], ':'), *s;
67 int sep_idx; 65 int sep_idx;
68 66
69 if (sep == NULL) { 67 if (sep == NULL) {
70 print_events(argv[i], false); 68 print_events(argv[i], raw_dump);
71 continue; 69 continue;
72 } 70 }
73 sep_idx = sep - argv[i]; 71 sep_idx = sep - argv[i];
@@ -76,7 +74,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
76 return -1; 74 return -1;
77 75
78 s[sep_idx] = '\0'; 76 s[sep_idx] = '\0';
79 print_tracepoint_events(s, s + sep_idx + 1, false); 77 print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
80 free(s); 78 free(s);
81 } 79 }
82 } 80 }
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index e7ec71589da6..d49c2ab85fc2 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -846,6 +846,8 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
846 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */ 846 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */
847}; 847};
848 848
849static bool force;
850
849static int __cmd_report(bool display_info) 851static int __cmd_report(bool display_info)
850{ 852{
851 int err = -EINVAL; 853 int err = -EINVAL;
@@ -857,6 +859,7 @@ static int __cmd_report(bool display_info)
857 struct perf_data_file file = { 859 struct perf_data_file file = {
858 .path = input_name, 860 .path = input_name,
859 .mode = PERF_DATA_MODE_READ, 861 .mode = PERF_DATA_MODE_READ,
862 .force = force,
860 }; 863 };
861 864
862 session = perf_session__new(&file, false, &eops); 865 session = perf_session__new(&file, false, &eops);
@@ -878,7 +881,7 @@ static int __cmd_report(bool display_info)
878 if (select_key()) 881 if (select_key())
879 goto out_delete; 882 goto out_delete;
880 883
881 err = perf_session__process_events(session, &eops); 884 err = perf_session__process_events(session);
882 if (err) 885 if (err)
883 goto out_delete; 886 goto out_delete;
884 887
@@ -945,6 +948,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
945 "dump thread list in perf.data"), 948 "dump thread list in perf.data"),
946 OPT_BOOLEAN('m', "map", &info_map, 949 OPT_BOOLEAN('m', "map", &info_map,
947 "map of lock instances (address:name table)"), 950 "map of lock instances (address:name table)"),
951 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
948 OPT_END() 952 OPT_END()
949 }; 953 };
950 const struct option lock_options[] = { 954 const struct option lock_options[] = {
@@ -956,6 +960,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
956 const struct option report_options[] = { 960 const struct option report_options[] = {
957 OPT_STRING('k', "key", &sort_key, "acquired", 961 OPT_STRING('k', "key", &sort_key, "acquired",
958 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"), 962 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
963 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
959 /* TODO: type */ 964 /* TODO: type */
960 OPT_END() 965 OPT_END()
961 }; 966 };
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 9b5663950a4d..675216e08bfc 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -15,6 +15,7 @@ struct perf_mem {
15 char const *input_name; 15 char const *input_name;
16 bool hide_unresolved; 16 bool hide_unresolved;
17 bool dump_raw; 17 bool dump_raw;
18 bool force;
18 int operation; 19 int operation;
19 const char *cpu_list; 20 const char *cpu_list;
20 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 21 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -120,6 +121,7 @@ static int report_raw_events(struct perf_mem *mem)
120 struct perf_data_file file = { 121 struct perf_data_file file = {
121 .path = input_name, 122 .path = input_name,
122 .mode = PERF_DATA_MODE_READ, 123 .mode = PERF_DATA_MODE_READ,
124 .force = mem->force,
123 }; 125 };
124 int err = -EINVAL; 126 int err = -EINVAL;
125 int ret; 127 int ret;
@@ -141,7 +143,7 @@ static int report_raw_events(struct perf_mem *mem)
141 143
142 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 144 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
143 145
144 err = perf_session__process_events(session, &mem->tool); 146 err = perf_session__process_events(session);
145 if (err) 147 if (err)
146 return err; 148 return err;
147 149
@@ -286,10 +288,11 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
286 "input file name"), 288 "input file name"),
287 OPT_STRING('C', "cpu", &mem.cpu_list, "cpu", 289 OPT_STRING('C', "cpu", &mem.cpu_list, "cpu",
288 "list of cpus to profile"), 290 "list of cpus to profile"),
289 OPT_STRING('x', "field-separator", &symbol_conf.field_sep, 291 OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep,
290 "separator", 292 "separator",
291 "separator for columns, no spaces will be added" 293 "separator for columns, no spaces will be added"
292 " between columns '.' is reserved."), 294 " between columns '.' is reserved."),
295 OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"),
293 OPT_END() 296 OPT_END()
294 }; 297 };
295 const char *const mem_subcommands[] = { "record", "report", NULL }; 298 const char *const mem_subcommands[] = { "record", "report", NULL };
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 921bb6942503..f7b1af67e9f6 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -56,6 +56,7 @@ static struct {
56 bool mod_events; 56 bool mod_events;
57 bool uprobes; 57 bool uprobes;
58 bool quiet; 58 bool quiet;
59 bool target_used;
59 int nevents; 60 int nevents;
60 struct perf_probe_event events[MAX_PROBES]; 61 struct perf_probe_event events[MAX_PROBES];
61 struct strlist *dellist; 62 struct strlist *dellist;
@@ -78,6 +79,12 @@ static int parse_probe_event(const char *str)
78 } 79 }
79 80
80 pev->uprobes = params.uprobes; 81 pev->uprobes = params.uprobes;
82 if (params.target) {
83 pev->target = strdup(params.target);
84 if (!pev->target)
85 return -ENOMEM;
86 params.target_used = true;
87 }
81 88
82 /* Parse a perf-probe command into event */ 89 /* Parse a perf-probe command into event */
83 ret = parse_perf_probe_command(str, pev); 90 ret = parse_perf_probe_command(str, pev);
@@ -102,6 +109,7 @@ static int set_target(const char *ptr)
102 params.target = strdup(ptr); 109 params.target = strdup(ptr);
103 if (!params.target) 110 if (!params.target)
104 return -ENOMEM; 111 return -ENOMEM;
112 params.target_used = false;
105 113
106 found = 1; 114 found = 1;
107 buf = ptr + (strlen(ptr) - 3); 115 buf = ptr + (strlen(ptr) - 3);
@@ -178,7 +186,7 @@ static int opt_set_target(const struct option *opt, const char *str,
178 int ret = -ENOENT; 186 int ret = -ENOENT;
179 char *tmp; 187 char *tmp;
180 188
181 if (str && !params.target) { 189 if (str) {
182 if (!strcmp(opt->long_name, "exec")) 190 if (!strcmp(opt->long_name, "exec"))
183 params.uprobes = true; 191 params.uprobes = true;
184#ifdef HAVE_DWARF_SUPPORT 192#ifdef HAVE_DWARF_SUPPORT
@@ -200,7 +208,9 @@ static int opt_set_target(const struct option *opt, const char *str,
200 if (!tmp) 208 if (!tmp)
201 return -ENOMEM; 209 return -ENOMEM;
202 } 210 }
211 free(params.target);
203 params.target = tmp; 212 params.target = tmp;
213 params.target_used = false;
204 ret = 0; 214 ret = 0;
205 } 215 }
206 216
@@ -485,9 +495,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
485 } 495 }
486 496
487 if (params.nevents) { 497 if (params.nevents) {
498 /* Ensure the last given target is used */
499 if (params.target && !params.target_used) {
500 pr_warning(" Error: -x/-m must follow the probe definitions.\n");
501 usage_with_options(probe_usage, options);
502 }
503
488 ret = add_perf_probe_events(params.events, params.nevents, 504 ret = add_perf_probe_events(params.events, params.nevents,
489 params.max_probe_points, 505 params.max_probe_points,
490 params.target,
491 params.force_add); 506 params.force_add);
492 if (ret < 0) { 507 if (ret < 0) {
493 pr_err_with_code(" Error: Failed to add events.", ret); 508 pr_err_with_code(" Error: Failed to add events.", ret);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 404ab3434052..c3efdfb630b5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -70,8 +70,8 @@ static int process_synthesized_event(struct perf_tool *tool,
70static int record__mmap_read(struct record *rec, int idx) 70static int record__mmap_read(struct record *rec, int idx)
71{ 71{
72 struct perf_mmap *md = &rec->evlist->mmap[idx]; 72 struct perf_mmap *md = &rec->evlist->mmap[idx];
73 unsigned int head = perf_mmap__read_head(md); 73 u64 head = perf_mmap__read_head(md);
74 unsigned int old = md->prev; 74 u64 old = md->prev;
75 unsigned char *data = md->base + page_size; 75 unsigned char *data = md->base + page_size;
76 unsigned long size; 76 unsigned long size;
77 void *buf; 77 void *buf;
@@ -161,8 +161,9 @@ try_again:
161 } 161 }
162 } 162 }
163 163
164 if (perf_evlist__apply_filters(evlist)) { 164 if (perf_evlist__apply_filters(evlist, &pos)) {
165 error("failed to set filter with %d (%s)\n", errno, 165 error("failed to set filter \"%s\" on event %s with %d (%s)\n",
166 pos->filter, perf_evsel__name(pos), errno,
166 strerror_r(errno, msg, sizeof(msg))); 167 strerror_r(errno, msg, sizeof(msg)));
167 rc = -1; 168 rc = -1;
168 goto out; 169 goto out;
@@ -225,7 +226,7 @@ static int process_buildids(struct record *rec)
225 */ 226 */
226 symbol_conf.ignore_vmlinux_buildid = true; 227 symbol_conf.ignore_vmlinux_buildid = true;
227 228
228 return perf_session__process_events(session, &rec->tool); 229 return perf_session__process_events(session);
229} 230}
230 231
231static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 232static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
@@ -343,7 +344,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
343 signal(SIGINT, sig_handler); 344 signal(SIGINT, sig_handler);
344 signal(SIGTERM, sig_handler); 345 signal(SIGTERM, sig_handler);
345 346
346 session = perf_session__new(file, false, NULL); 347 session = perf_session__new(file, false, tool);
347 if (session == NULL) { 348 if (session == NULL) {
348 pr_err("Perf session creation failed.\n"); 349 pr_err("Perf session creation failed.\n");
349 return -1; 350 return -1;
@@ -658,7 +659,7 @@ error:
658 659
659static void callchain_debug(void) 660static void callchain_debug(void)
660{ 661{
661 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" }; 662 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
662 663
663 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 664 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
664 665
@@ -710,6 +711,90 @@ static int perf_record_config(const char *var, const char *value, void *cb)
710 return perf_default_config(var, value, cb); 711 return perf_default_config(var, value, cb);
711} 712}
712 713
714struct clockid_map {
715 const char *name;
716 int clockid;
717};
718
719#define CLOCKID_MAP(n, c) \
720 { .name = n, .clockid = (c), }
721
722#define CLOCKID_END { .name = NULL, }
723
724
725/*
726 * Add the missing ones, we need to build on many distros...
727 */
728#ifndef CLOCK_MONOTONIC_RAW
729#define CLOCK_MONOTONIC_RAW 4
730#endif
731#ifndef CLOCK_BOOTTIME
732#define CLOCK_BOOTTIME 7
733#endif
734#ifndef CLOCK_TAI
735#define CLOCK_TAI 11
736#endif
737
738static const struct clockid_map clockids[] = {
739 /* available for all events, NMI safe */
740 CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
741 CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
742
743 /* available for some events */
744 CLOCKID_MAP("realtime", CLOCK_REALTIME),
745 CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
746 CLOCKID_MAP("tai", CLOCK_TAI),
747
748 /* available for the lazy */
749 CLOCKID_MAP("mono", CLOCK_MONOTONIC),
750 CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
751 CLOCKID_MAP("real", CLOCK_REALTIME),
752 CLOCKID_MAP("boot", CLOCK_BOOTTIME),
753
754 CLOCKID_END,
755};
756
757static int parse_clockid(const struct option *opt, const char *str, int unset)
758{
759 struct record_opts *opts = (struct record_opts *)opt->value;
760 const struct clockid_map *cm;
761 const char *ostr = str;
762
763 if (unset) {
764 opts->use_clockid = 0;
765 return 0;
766 }
767
768 /* no arg passed */
769 if (!str)
770 return 0;
771
772 /* no setting it twice */
773 if (opts->use_clockid)
774 return -1;
775
776 opts->use_clockid = true;
777
778 /* if its a number, we're done */
779 if (sscanf(str, "%d", &opts->clockid) == 1)
780 return 0;
781
782 /* allow a "CLOCK_" prefix to the name */
783 if (!strncasecmp(str, "CLOCK_", 6))
784 str += 6;
785
786 for (cm = clockids; cm->name; cm++) {
787 if (!strcasecmp(str, cm->name)) {
788 opts->clockid = cm->clockid;
789 return 0;
790 }
791 }
792
793 opts->use_clockid = false;
794 ui__warning("unknown clockid %s, check man page\n", ostr);
795 return -1;
796}
797
713static const char * const __record_usage[] = { 798static const char * const __record_usage[] = {
714 "perf record [<options>] [<command>]", 799 "perf record [<options>] [<command>]",
715 "perf record [<options>] -- <command> [<options>]", 800 "perf record [<options>] -- <command> [<options>]",
@@ -751,9 +836,9 @@ static struct record record = {
751#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 836#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
752 837
753#ifdef HAVE_DWARF_UNWIND_SUPPORT 838#ifdef HAVE_DWARF_UNWIND_SUPPORT
754const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 839const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
755#else 840#else
756const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 841const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
757#endif 842#endif
758 843
759/* 844/*
@@ -839,6 +924,11 @@ struct option __record_options[] = {
839 "use per-thread mmaps"), 924 "use per-thread mmaps"),
840 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, 925 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
841 "Sample machine registers on interrupt"), 926 "Sample machine registers on interrupt"),
927 OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
928 "Record running/enabled time of read (:S) events"),
929 OPT_CALLBACK('k', "clockid", &record.opts,
930 "clockid", "clockid to use for events, see clock_gettime()",
931 parse_clockid),
842 OPT_END() 932 OPT_END()
843}; 933};
844 934
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2f91094e228b..476cdf7afcca 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -249,6 +249,8 @@ static int report__setup_sample_type(struct report *rep)
249 if ((sample_type & PERF_SAMPLE_REGS_USER) && 249 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
250 (sample_type & PERF_SAMPLE_STACK_USER)) 250 (sample_type & PERF_SAMPLE_STACK_USER))
251 callchain_param.record_mode = CALLCHAIN_DWARF; 251 callchain_param.record_mode = CALLCHAIN_DWARF;
252 else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
253 callchain_param.record_mode = CALLCHAIN_LBR;
252 else 254 else
253 callchain_param.record_mode = CALLCHAIN_FP; 255 callchain_param.record_mode = CALLCHAIN_FP;
254 } 256 }
@@ -302,7 +304,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
302 304
303 if (rep->mem_mode) { 305 if (rep->mem_mode) {
304 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events); 306 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
305 ret += fprintf(fp, "\n# Sort order : %s", sort_order); 307 ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order);
306 } else 308 } else
307 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); 309 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
308 return ret + fprintf(fp, "\n#\n"); 310 return ret + fprintf(fp, "\n#\n");
@@ -345,7 +347,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
345static void report__warn_kptr_restrict(const struct report *rep) 347static void report__warn_kptr_restrict(const struct report *rep)
346{ 348{
347 struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; 349 struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
348 struct kmap *kernel_kmap = map__kmap(kernel_map); 350 struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
349 351
350 if (kernel_map == NULL || 352 if (kernel_map == NULL ||
351 (kernel_map->dso->hit && 353 (kernel_map->dso->hit &&
@@ -480,7 +482,7 @@ static int __cmd_report(struct report *rep)
480 if (ret) 482 if (ret)
481 return ret; 483 return ret;
482 484
483 ret = perf_session__process_events(session, &rep->tool); 485 ret = perf_session__process_events(session);
484 if (ret) 486 if (ret)
485 return ret; 487 return ret;
486 488
@@ -667,6 +669,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
667 "only consider symbols in these dsos"), 669 "only consider symbols in these dsos"),
668 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 670 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
669 "only consider symbols in these comms"), 671 "only consider symbols in these comms"),
672 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
673 "only consider symbols in these pids"),
674 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
675 "only consider symbols in these tids"),
670 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 676 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
671 "only consider these symbols"), 677 "only consider these symbols"),
672 OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter", 678 OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
@@ -674,7 +680,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
674 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str, 680 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
675 "width[,width...]", 681 "width[,width...]",
676 "don't try to adjust column width, use these fixed values"), 682 "don't try to adjust column width, use these fixed values"),
677 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 683 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
678 "separator for columns, no spaces will be added between " 684 "separator for columns, no spaces will be added between "
679 "columns '.' is reserved."), 685 "columns '.' is reserved."),
680 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved, 686 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
@@ -766,7 +772,7 @@ repeat:
766 * 0/1 means the user chose a mode. 772 * 0/1 means the user chose a mode.
767 */ 773 */
768 if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) && 774 if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
769 branch_call_mode == -1) { 775 !branch_call_mode) {
770 sort__mode = SORT_MODE__BRANCH; 776 sort__mode = SORT_MODE__BRANCH;
771 symbol_conf.cumulate_callchain = false; 777 symbol_conf.cumulate_callchain = false;
772 } 778 }
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 891c3930080e..5275bab70313 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -23,12 +23,13 @@
23#include <semaphore.h> 23#include <semaphore.h>
24#include <pthread.h> 24#include <pthread.h>
25#include <math.h> 25#include <math.h>
26#include <api/fs/fs.h>
26 27
27#define PR_SET_NAME 15 /* Set process name */ 28#define PR_SET_NAME 15 /* Set process name */
28#define MAX_CPUS 4096 29#define MAX_CPUS 4096
29#define COMM_LEN 20 30#define COMM_LEN 20
30#define SYM_LEN 129 31#define SYM_LEN 129
31#define MAX_PID 65536 32#define MAX_PID 1024000
32 33
33struct sched_atom; 34struct sched_atom;
34 35
@@ -124,7 +125,7 @@ struct perf_sched {
124 struct perf_tool tool; 125 struct perf_tool tool;
125 const char *sort_order; 126 const char *sort_order;
126 unsigned long nr_tasks; 127 unsigned long nr_tasks;
127 struct task_desc *pid_to_task[MAX_PID]; 128 struct task_desc **pid_to_task;
128 struct task_desc **tasks; 129 struct task_desc **tasks;
129 const struct trace_sched_handler *tp_handler; 130 const struct trace_sched_handler *tp_handler;
130 pthread_mutex_t start_work_mutex; 131 pthread_mutex_t start_work_mutex;
@@ -169,6 +170,7 @@ struct perf_sched {
169 u64 cpu_last_switched[MAX_CPUS]; 170 u64 cpu_last_switched[MAX_CPUS];
170 struct rb_root atom_root, sorted_atom_root; 171 struct rb_root atom_root, sorted_atom_root;
171 struct list_head sort_list, cmp_pid; 172 struct list_head sort_list, cmp_pid;
173 bool force;
172}; 174};
173 175
174static u64 get_nsecs(void) 176static u64 get_nsecs(void)
@@ -326,8 +328,19 @@ static struct task_desc *register_pid(struct perf_sched *sched,
326 unsigned long pid, const char *comm) 328 unsigned long pid, const char *comm)
327{ 329{
328 struct task_desc *task; 330 struct task_desc *task;
331 static int pid_max;
329 332
330 BUG_ON(pid >= MAX_PID); 333 if (sched->pid_to_task == NULL) {
334 if (sysctl__read_int("kernel/pid_max", &pid_max) < 0)
335 pid_max = MAX_PID;
336 BUG_ON((sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *))) == NULL);
337 }
338 if (pid >= (unsigned long)pid_max) {
339 BUG_ON((sched->pid_to_task = realloc(sched->pid_to_task, (pid + 1) *
340 sizeof(struct task_desc *))) == NULL);
341 while (pid >= (unsigned long)pid_max)
342 sched->pid_to_task[pid_max++] = NULL;
343 }
331 344
332 task = sched->pid_to_task[pid]; 345 task = sched->pid_to_task[pid];
333 346
@@ -346,7 +359,7 @@ static struct task_desc *register_pid(struct perf_sched *sched,
346 359
347 sched->pid_to_task[pid] = task; 360 sched->pid_to_task[pid] = task;
348 sched->nr_tasks++; 361 sched->nr_tasks++;
349 sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_task *)); 362 sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_desc *));
350 BUG_ON(!sched->tasks); 363 BUG_ON(!sched->tasks);
351 sched->tasks[task->nr] = task; 364 sched->tasks[task->nr] = task;
352 365
@@ -425,24 +438,45 @@ static u64 get_cpu_usage_nsec_parent(void)
425 return sum; 438 return sum;
426} 439}
427 440
428static int self_open_counters(void) 441static int self_open_counters(struct perf_sched *sched, unsigned long cur_task)
429{ 442{
430 struct perf_event_attr attr; 443 struct perf_event_attr attr;
431 char sbuf[STRERR_BUFSIZE]; 444 char sbuf[STRERR_BUFSIZE], info[STRERR_BUFSIZE];
432 int fd; 445 int fd;
446 struct rlimit limit;
447 bool need_privilege = false;
433 448
434 memset(&attr, 0, sizeof(attr)); 449 memset(&attr, 0, sizeof(attr));
435 450
436 attr.type = PERF_TYPE_SOFTWARE; 451 attr.type = PERF_TYPE_SOFTWARE;
437 attr.config = PERF_COUNT_SW_TASK_CLOCK; 452 attr.config = PERF_COUNT_SW_TASK_CLOCK;
438 453
454force_again:
439 fd = sys_perf_event_open(&attr, 0, -1, -1, 455 fd = sys_perf_event_open(&attr, 0, -1, -1,
440 perf_event_open_cloexec_flag()); 456 perf_event_open_cloexec_flag());
441 457
442 if (fd < 0) 458 if (fd < 0) {
459 if (errno == EMFILE) {
460 if (sched->force) {
461 BUG_ON(getrlimit(RLIMIT_NOFILE, &limit) == -1);
462 limit.rlim_cur += sched->nr_tasks - cur_task;
463 if (limit.rlim_cur > limit.rlim_max) {
464 limit.rlim_max = limit.rlim_cur;
465 need_privilege = true;
466 }
467 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
468 if (need_privilege && errno == EPERM)
469 strcpy(info, "Need privilege\n");
470 } else
471 goto force_again;
472 } else
473 strcpy(info, "Have a try with -f option\n");
474 }
443 pr_err("Error: sys_perf_event_open() syscall returned " 475 pr_err("Error: sys_perf_event_open() syscall returned "
444 "with %d (%s)\n", fd, 476 "with %d (%s)\n%s", fd,
445 strerror_r(errno, sbuf, sizeof(sbuf))); 477 strerror_r(errno, sbuf, sizeof(sbuf)), info);
478 exit(EXIT_FAILURE);
479 }
446 return fd; 480 return fd;
447} 481}
448 482
@@ -460,6 +494,7 @@ static u64 get_cpu_usage_nsec_self(int fd)
460struct sched_thread_parms { 494struct sched_thread_parms {
461 struct task_desc *task; 495 struct task_desc *task;
462 struct perf_sched *sched; 496 struct perf_sched *sched;
497 int fd;
463}; 498};
464 499
465static void *thread_func(void *ctx) 500static void *thread_func(void *ctx)
@@ -470,13 +505,12 @@ static void *thread_func(void *ctx)
470 u64 cpu_usage_0, cpu_usage_1; 505 u64 cpu_usage_0, cpu_usage_1;
471 unsigned long i, ret; 506 unsigned long i, ret;
472 char comm2[22]; 507 char comm2[22];
473 int fd; 508 int fd = parms->fd;
474 509
475 zfree(&parms); 510 zfree(&parms);
476 511
477 sprintf(comm2, ":%s", this_task->comm); 512 sprintf(comm2, ":%s", this_task->comm);
478 prctl(PR_SET_NAME, comm2); 513 prctl(PR_SET_NAME, comm2);
479 fd = self_open_counters();
480 if (fd < 0) 514 if (fd < 0)
481 return NULL; 515 return NULL;
482again: 516again:
@@ -528,6 +562,7 @@ static void create_tasks(struct perf_sched *sched)
528 BUG_ON(parms == NULL); 562 BUG_ON(parms == NULL);
529 parms->task = task = sched->tasks[i]; 563 parms->task = task = sched->tasks[i];
530 parms->sched = sched; 564 parms->sched = sched;
565 parms->fd = self_open_counters(sched, i);
531 sem_init(&task->sleep_sem, 0, 0); 566 sem_init(&task->sleep_sem, 0, 0);
532 sem_init(&task->ready_for_work, 0, 0); 567 sem_init(&task->ready_for_work, 0, 0);
533 sem_init(&task->work_done_sem, 0, 0); 568 sem_init(&task->work_done_sem, 0, 0);
@@ -572,13 +607,13 @@ static void wait_for_tasks(struct perf_sched *sched)
572 cpu_usage_1 = get_cpu_usage_nsec_parent(); 607 cpu_usage_1 = get_cpu_usage_nsec_parent();
573 if (!sched->runavg_cpu_usage) 608 if (!sched->runavg_cpu_usage)
574 sched->runavg_cpu_usage = sched->cpu_usage; 609 sched->runavg_cpu_usage = sched->cpu_usage;
575 sched->runavg_cpu_usage = (sched->runavg_cpu_usage * 9 + sched->cpu_usage) / 10; 610 sched->runavg_cpu_usage = (sched->runavg_cpu_usage * (sched->replay_repeat - 1) + sched->cpu_usage) / sched->replay_repeat;
576 611
577 sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0; 612 sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0;
578 if (!sched->runavg_parent_cpu_usage) 613 if (!sched->runavg_parent_cpu_usage)
579 sched->runavg_parent_cpu_usage = sched->parent_cpu_usage; 614 sched->runavg_parent_cpu_usage = sched->parent_cpu_usage;
580 sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 + 615 sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * (sched->replay_repeat - 1) +
581 sched->parent_cpu_usage)/10; 616 sched->parent_cpu_usage)/sched->replay_repeat;
582 617
583 ret = pthread_mutex_lock(&sched->start_work_mutex); 618 ret = pthread_mutex_lock(&sched->start_work_mutex);
584 BUG_ON(ret); 619 BUG_ON(ret);
@@ -610,7 +645,7 @@ static void run_one_test(struct perf_sched *sched)
610 sched->sum_fluct += fluct; 645 sched->sum_fluct += fluct;
611 if (!sched->run_avg) 646 if (!sched->run_avg)
612 sched->run_avg = delta; 647 sched->run_avg = delta;
613 sched->run_avg = (sched->run_avg * 9 + delta) / 10; 648 sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat;
614 649
615 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); 650 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0);
616 651
@@ -831,7 +866,7 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
831 return -1; 866 return -1;
832 } 867 }
833 868
834 atoms->thread = thread; 869 atoms->thread = thread__get(thread);
835 INIT_LIST_HEAD(&atoms->work_list); 870 INIT_LIST_HEAD(&atoms->work_list);
836 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid); 871 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid);
837 return 0; 872 return 0;
@@ -1439,8 +1474,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1439 return err; 1474 return err;
1440} 1475}
1441 1476
1442static int perf_sched__read_events(struct perf_sched *sched, 1477static int perf_sched__read_events(struct perf_sched *sched)
1443 struct perf_session **psession)
1444{ 1478{
1445 const struct perf_evsel_str_handler handlers[] = { 1479 const struct perf_evsel_str_handler handlers[] = {
1446 { "sched:sched_switch", process_sched_switch_event, }, 1480 { "sched:sched_switch", process_sched_switch_event, },
@@ -1453,7 +1487,9 @@ static int perf_sched__read_events(struct perf_sched *sched,
1453 struct perf_data_file file = { 1487 struct perf_data_file file = {
1454 .path = input_name, 1488 .path = input_name,
1455 .mode = PERF_DATA_MODE_READ, 1489 .mode = PERF_DATA_MODE_READ,
1490 .force = sched->force,
1456 }; 1491 };
1492 int rc = -1;
1457 1493
1458 session = perf_session__new(&file, false, &sched->tool); 1494 session = perf_session__new(&file, false, &sched->tool);
1459 if (session == NULL) { 1495 if (session == NULL) {
@@ -1467,27 +1503,21 @@ static int perf_sched__read_events(struct perf_sched *sched,
1467 goto out_delete; 1503 goto out_delete;
1468 1504
1469 if (perf_session__has_traces(session, "record -R")) { 1505 if (perf_session__has_traces(session, "record -R")) {
1470 int err = perf_session__process_events(session, &sched->tool); 1506 int err = perf_session__process_events(session);
1471 if (err) { 1507 if (err) {
1472 pr_err("Failed to process events, error %d", err); 1508 pr_err("Failed to process events, error %d", err);
1473 goto out_delete; 1509 goto out_delete;
1474 } 1510 }
1475 1511
1476 sched->nr_events = session->stats.nr_events[0]; 1512 sched->nr_events = session->evlist->stats.nr_events[0];
1477 sched->nr_lost_events = session->stats.total_lost; 1513 sched->nr_lost_events = session->evlist->stats.total_lost;
1478 sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; 1514 sched->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
1479 } 1515 }
1480 1516
1481 if (psession) 1517 rc = 0;
1482 *psession = session;
1483 else
1484 perf_session__delete(session);
1485
1486 return 0;
1487
1488out_delete: 1518out_delete:
1489 perf_session__delete(session); 1519 perf_session__delete(session);
1490 return -1; 1520 return rc;
1491} 1521}
1492 1522
1493static void print_bad_events(struct perf_sched *sched) 1523static void print_bad_events(struct perf_sched *sched)
@@ -1515,12 +1545,10 @@ static void print_bad_events(struct perf_sched *sched)
1515static int perf_sched__lat(struct perf_sched *sched) 1545static int perf_sched__lat(struct perf_sched *sched)
1516{ 1546{
1517 struct rb_node *next; 1547 struct rb_node *next;
1518 struct perf_session *session;
1519 1548
1520 setup_pager(); 1549 setup_pager();
1521 1550
1522 /* save session -- references to threads are held in work_list */ 1551 if (perf_sched__read_events(sched))
1523 if (perf_sched__read_events(sched, &session))
1524 return -1; 1552 return -1;
1525 1553
1526 perf_sched__sort_lat(sched); 1554 perf_sched__sort_lat(sched);
@@ -1537,6 +1565,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1537 work_list = rb_entry(next, struct work_atoms, node); 1565 work_list = rb_entry(next, struct work_atoms, node);
1538 output_lat_thread(sched, work_list); 1566 output_lat_thread(sched, work_list);
1539 next = rb_next(next); 1567 next = rb_next(next);
1568 thread__zput(work_list->thread);
1540 } 1569 }
1541 1570
1542 printf(" -----------------------------------------------------------------------------------------------------------------\n"); 1571 printf(" -----------------------------------------------------------------------------------------------------------------\n");
@@ -1548,7 +1577,6 @@ static int perf_sched__lat(struct perf_sched *sched)
1548 print_bad_events(sched); 1577 print_bad_events(sched);
1549 printf("\n"); 1578 printf("\n");
1550 1579
1551 perf_session__delete(session);
1552 return 0; 1580 return 0;
1553} 1581}
1554 1582
@@ -1557,7 +1585,7 @@ static int perf_sched__map(struct perf_sched *sched)
1557 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1585 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1558 1586
1559 setup_pager(); 1587 setup_pager();
1560 if (perf_sched__read_events(sched, NULL)) 1588 if (perf_sched__read_events(sched))
1561 return -1; 1589 return -1;
1562 print_bad_events(sched); 1590 print_bad_events(sched);
1563 return 0; 1591 return 0;
@@ -1572,7 +1600,7 @@ static int perf_sched__replay(struct perf_sched *sched)
1572 1600
1573 test_calibrations(sched); 1601 test_calibrations(sched);
1574 1602
1575 if (perf_sched__read_events(sched, NULL)) 1603 if (perf_sched__read_events(sched))
1576 return -1; 1604 return -1;
1577 1605
1578 printf("nr_run_events: %ld\n", sched->nr_run_events); 1606 printf("nr_run_events: %ld\n", sched->nr_run_events);
@@ -1693,6 +1721,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1693 "be more verbose (show symbol address, etc)"), 1721 "be more verbose (show symbol address, etc)"),
1694 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1722 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1695 "dump raw trace in ASCII"), 1723 "dump raw trace in ASCII"),
1724 OPT_BOOLEAN('f', "force", &sched.force, "don't complain, do it"),
1696 OPT_END() 1725 OPT_END()
1697 }; 1726 };
1698 const struct option sched_options[] = { 1727 const struct option sched_options[] = {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ce304dfd962a..58f10b8e6ff2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -446,9 +446,9 @@ static void print_sample_bts(union perf_event *event,
446} 446}
447 447
448static void process_event(union perf_event *event, struct perf_sample *sample, 448static void process_event(union perf_event *event, struct perf_sample *sample,
449 struct perf_evsel *evsel, struct thread *thread, 449 struct perf_evsel *evsel, struct addr_location *al)
450 struct addr_location *al)
451{ 450{
451 struct thread *thread = al->thread;
452 struct perf_event_attr *attr = &evsel->attr; 452 struct perf_event_attr *attr = &evsel->attr;
453 453
454 if (output[attr->type].fields == 0) 454 if (output[attr->type].fields == 0)
@@ -549,14 +549,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
549 struct machine *machine) 549 struct machine *machine)
550{ 550{
551 struct addr_location al; 551 struct addr_location al;
552 struct thread *thread = machine__findnew_thread(machine, sample->pid,
553 sample->tid);
554
555 if (thread == NULL) {
556 pr_debug("problem processing %d event, skipping it.\n",
557 event->header.type);
558 return -1;
559 }
560 552
561 if (debug_mode) { 553 if (debug_mode) {
562 if (sample->time < last_timestamp) { 554 if (sample->time < last_timestamp) {
@@ -581,7 +573,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
581 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 573 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
582 return 0; 574 return 0;
583 575
584 scripting_ops->process_event(event, sample, evsel, thread, &al); 576 scripting_ops->process_event(event, sample, evsel, &al);
585 577
586 return 0; 578 return 0;
587} 579}
@@ -800,7 +792,7 @@ static int __cmd_script(struct perf_script *script)
800 script->tool.mmap2 = process_mmap2_event; 792 script->tool.mmap2 = process_mmap2_event;
801 } 793 }
802 794
803 ret = perf_session__process_events(script->session, &script->tool); 795 ret = perf_session__process_events(script->session);
804 796
805 if (debug_mode) 797 if (debug_mode)
806 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 798 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1523,6 +1515,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1523 .ordering_requires_timestamps = true, 1515 .ordering_requires_timestamps = true,
1524 }, 1516 },
1525 }; 1517 };
1518 struct perf_data_file file = {
1519 .mode = PERF_DATA_MODE_READ,
1520 };
1526 const struct option options[] = { 1521 const struct option options[] = {
1527 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1522 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1528 "dump raw trace in ASCII"), 1523 "dump raw trace in ASCII"),
@@ -1550,7 +1545,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1550 "When printing symbols do not display call chain"), 1545 "When printing symbols do not display call chain"),
1551 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1546 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1552 "Look for files with symbols relative to this directory"), 1547 "Look for files with symbols relative to this directory"),
1553 OPT_CALLBACK('f', "fields", NULL, "str", 1548 OPT_CALLBACK('F', "fields", NULL, "str",
1554 "comma separated output fields prepend with 'type:'. " 1549 "comma separated output fields prepend with 'type:'. "
1555 "Valid types: hw,sw,trace,raw. " 1550 "Valid types: hw,sw,trace,raw. "
1556 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1551 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
@@ -1562,6 +1557,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1562 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1557 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
1563 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 1558 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
1564 "only display events for these comms"), 1559 "only display events for these comms"),
1560 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
1561 "only consider symbols in these pids"),
1562 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
1563 "only consider symbols in these tids"),
1565 OPT_BOOLEAN('I', "show-info", &show_full_info, 1564 OPT_BOOLEAN('I', "show-info", &show_full_info,
1566 "display extended information from perf.data file"), 1565 "display extended information from perf.data file"),
1567 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 1566 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -1570,9 +1569,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1570 "Show the fork/comm/exit events"), 1569 "Show the fork/comm/exit events"),
1571 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events, 1570 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
1572 "Show the mmap events"), 1571 "Show the mmap events"),
1572 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
1573 OPT_END() 1573 OPT_END()
1574 }; 1574 };
1575 const char * const script_usage[] = { 1575 const char * const script_subcommands[] = { "record", "report", NULL };
1576 const char *script_usage[] = {
1576 "perf script [<options>]", 1577 "perf script [<options>]",
1577 "perf script [<options>] record <script> [<record-options>] <command>", 1578 "perf script [<options>] record <script> [<record-options>] <command>",
1578 "perf script [<options>] report <script> [script-args]", 1579 "perf script [<options>] report <script> [script-args]",
@@ -1580,13 +1581,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1580 "perf script [<options>] <top-script> [script-args]", 1581 "perf script [<options>] <top-script> [script-args]",
1581 NULL 1582 NULL
1582 }; 1583 };
1583 struct perf_data_file file = {
1584 .mode = PERF_DATA_MODE_READ,
1585 };
1586 1584
1587 setup_scripting(); 1585 setup_scripting();
1588 1586
1589 argc = parse_options(argc, argv, options, script_usage, 1587 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
1590 PARSE_OPT_STOP_AT_NON_OPTION); 1588 PARSE_OPT_STOP_AT_NON_OPTION);
1591 1589
1592 file.path = input_name; 1590 file.path = input_name;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e598e4e98170..f7b8218785f6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -353,39 +353,40 @@ static struct perf_evsel *nth_evsel(int n)
353 * more semantic information such as miss/hit ratios, 353 * more semantic information such as miss/hit ratios,
354 * instruction rates, etc: 354 * instruction rates, etc:
355 */ 355 */
356static void update_shadow_stats(struct perf_evsel *counter, u64 *count) 356static void update_shadow_stats(struct perf_evsel *counter, u64 *count,
357 int cpu)
357{ 358{
358 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 359 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
359 update_stats(&runtime_nsecs_stats[0], count[0]); 360 update_stats(&runtime_nsecs_stats[cpu], count[0]);
360 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 361 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
361 update_stats(&runtime_cycles_stats[0], count[0]); 362 update_stats(&runtime_cycles_stats[cpu], count[0]);
362 else if (transaction_run && 363 else if (transaction_run &&
363 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX))) 364 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
364 update_stats(&runtime_cycles_in_tx_stats[0], count[0]); 365 update_stats(&runtime_cycles_in_tx_stats[cpu], count[0]);
365 else if (transaction_run && 366 else if (transaction_run &&
366 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START))) 367 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
367 update_stats(&runtime_transaction_stats[0], count[0]); 368 update_stats(&runtime_transaction_stats[cpu], count[0]);
368 else if (transaction_run && 369 else if (transaction_run &&
369 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START))) 370 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
370 update_stats(&runtime_elision_stats[0], count[0]); 371 update_stats(&runtime_elision_stats[cpu], count[0]);
371 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 372 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
372 update_stats(&runtime_stalled_cycles_front_stats[0], count[0]); 373 update_stats(&runtime_stalled_cycles_front_stats[cpu], count[0]);
373 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 374 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
374 update_stats(&runtime_stalled_cycles_back_stats[0], count[0]); 375 update_stats(&runtime_stalled_cycles_back_stats[cpu], count[0]);
375 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 376 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
376 update_stats(&runtime_branches_stats[0], count[0]); 377 update_stats(&runtime_branches_stats[cpu], count[0]);
377 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 378 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
378 update_stats(&runtime_cacherefs_stats[0], count[0]); 379 update_stats(&runtime_cacherefs_stats[cpu], count[0]);
379 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) 380 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
380 update_stats(&runtime_l1_dcache_stats[0], count[0]); 381 update_stats(&runtime_l1_dcache_stats[cpu], count[0]);
381 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) 382 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
382 update_stats(&runtime_l1_icache_stats[0], count[0]); 383 update_stats(&runtime_l1_icache_stats[cpu], count[0]);
383 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) 384 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
384 update_stats(&runtime_ll_cache_stats[0], count[0]); 385 update_stats(&runtime_ll_cache_stats[cpu], count[0]);
385 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) 386 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
386 update_stats(&runtime_dtlb_cache_stats[0], count[0]); 387 update_stats(&runtime_dtlb_cache_stats[cpu], count[0]);
387 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 388 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
388 update_stats(&runtime_itlb_cache_stats[0], count[0]); 389 update_stats(&runtime_itlb_cache_stats[cpu], count[0]);
389} 390}
390 391
391static void zero_per_pkg(struct perf_evsel *counter) 392static void zero_per_pkg(struct perf_evsel *counter)
@@ -447,7 +448,8 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
447 perf_evsel__compute_deltas(evsel, cpu, count); 448 perf_evsel__compute_deltas(evsel, cpu, count);
448 perf_counts_values__scale(count, scale, NULL); 449 perf_counts_values__scale(count, scale, NULL);
449 evsel->counts->cpu[cpu] = *count; 450 evsel->counts->cpu[cpu] = *count;
450 update_shadow_stats(evsel, count->values); 451 if (aggr_mode == AGGR_NONE)
452 update_shadow_stats(evsel, count->values, cpu);
451 break; 453 break;
452 case AGGR_GLOBAL: 454 case AGGR_GLOBAL:
453 aggr->val += count->val; 455 aggr->val += count->val;
@@ -495,7 +497,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
495 /* 497 /*
496 * Save the full runtime - to allow normalization during printout: 498 * Save the full runtime - to allow normalization during printout:
497 */ 499 */
498 update_shadow_stats(counter, count); 500 update_shadow_stats(counter, count, 0);
499 501
500 return 0; 502 return 0;
501} 503}
@@ -510,6 +512,9 @@ static int read_counter(struct perf_evsel *counter)
510 int ncpus = perf_evsel__nr_cpus(counter); 512 int ncpus = perf_evsel__nr_cpus(counter);
511 int cpu, thread; 513 int cpu, thread;
512 514
515 if (!counter->supported)
516 return -ENOENT;
517
513 if (counter->system_wide) 518 if (counter->system_wide)
514 nthreads = 1; 519 nthreads = 1;
515 520
@@ -679,8 +684,9 @@ static int __run_perf_stat(int argc, const char **argv)
679 unit_width = l; 684 unit_width = l;
680 } 685 }
681 686
682 if (perf_evlist__apply_filters(evsel_list)) { 687 if (perf_evlist__apply_filters(evsel_list, &counter)) {
683 error("failed to set filter with %d (%s)\n", errno, 688 error("failed to set filter \"%s\" on event %s with %d (%s)\n",
689 counter->filter, perf_evsel__name(counter), errno,
684 strerror_r(errno, msg, sizeof(msg))); 690 strerror_r(errno, msg, sizeof(msg)));
685 return -1; 691 return -1;
686 } 692 }
@@ -766,6 +772,19 @@ static int run_perf_stat(int argc, const char **argv)
766 return ret; 772 return ret;
767} 773}
768 774
775static void print_running(u64 run, u64 ena)
776{
777 if (csv_output) {
778 fprintf(output, "%s%" PRIu64 "%s%.2f",
779 csv_sep,
780 run,
781 csv_sep,
782 ena ? 100.0 * run / ena : 100.0);
783 } else if (run != ena) {
784 fprintf(output, " (%.2f%%)", 100.0 * run / ena);
785 }
786}
787
769static void print_noise_pct(double total, double avg) 788static void print_noise_pct(double total, double avg)
770{ 789{
771 double pct = rel_stddev_stats(total, avg); 790 double pct = rel_stddev_stats(total, avg);
@@ -1076,6 +1095,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1076 if (total) { 1095 if (total) {
1077 ratio = avg / total; 1096 ratio = avg / total;
1078 fprintf(output, " # %5.2f insns per cycle ", ratio); 1097 fprintf(output, " # %5.2f insns per cycle ", ratio);
1098 } else {
1099 fprintf(output, " ");
1079 } 1100 }
1080 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 1101 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
1081 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 1102 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
@@ -1145,6 +1166,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1145 if (total) { 1166 if (total) {
1146 ratio = avg / total; 1167 ratio = avg / total;
1147 fprintf(output, " # %8.3f GHz ", ratio); 1168 fprintf(output, " # %8.3f GHz ", ratio);
1169 } else {
1170 fprintf(output, " ");
1148 } 1171 }
1149 } else if (transaction_run && 1172 } else if (transaction_run &&
1150 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) { 1173 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
@@ -1249,6 +1272,7 @@ static void print_aggr(char *prefix)
1249 fprintf(output, "%s%s", 1272 fprintf(output, "%s%s",
1250 csv_sep, counter->cgrp->name); 1273 csv_sep, counter->cgrp->name);
1251 1274
1275 print_running(run, ena);
1252 fputc('\n', output); 1276 fputc('\n', output);
1253 continue; 1277 continue;
1254 } 1278 }
@@ -1259,13 +1283,10 @@ static void print_aggr(char *prefix)
1259 else 1283 else
1260 abs_printout(id, nr, counter, uval); 1284 abs_printout(id, nr, counter, uval);
1261 1285
1262 if (!csv_output) { 1286 if (!csv_output)
1263 print_noise(counter, 1.0); 1287 print_noise(counter, 1.0);
1264 1288
1265 if (run != ena) 1289 print_running(run, ena);
1266 fprintf(output, " (%.2f%%)",
1267 100.0 * run / ena);
1268 }
1269 fputc('\n', output); 1290 fputc('\n', output);
1270 } 1291 }
1271 } 1292 }
@@ -1281,11 +1302,15 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1281 double avg = avg_stats(&ps->res_stats[0]); 1302 double avg = avg_stats(&ps->res_stats[0]);
1282 int scaled = counter->counts->scaled; 1303 int scaled = counter->counts->scaled;
1283 double uval; 1304 double uval;
1305 double avg_enabled, avg_running;
1306
1307 avg_enabled = avg_stats(&ps->res_stats[1]);
1308 avg_running = avg_stats(&ps->res_stats[2]);
1284 1309
1285 if (prefix) 1310 if (prefix)
1286 fprintf(output, "%s", prefix); 1311 fprintf(output, "%s", prefix);
1287 1312
1288 if (scaled == -1) { 1313 if (scaled == -1 || !counter->supported) {
1289 fprintf(output, "%*s%s", 1314 fprintf(output, "%*s%s",
1290 csv_output ? 0 : 18, 1315 csv_output ? 0 : 18,
1291 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1316 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
@@ -1300,6 +1325,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1300 if (counter->cgrp) 1325 if (counter->cgrp)
1301 fprintf(output, "%s%s", csv_sep, counter->cgrp->name); 1326 fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
1302 1327
1328 print_running(avg_running, avg_enabled);
1303 fputc('\n', output); 1329 fputc('\n', output);
1304 return; 1330 return;
1305 } 1331 }
@@ -1313,19 +1339,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1313 1339
1314 print_noise(counter, avg); 1340 print_noise(counter, avg);
1315 1341
1316 if (csv_output) { 1342 print_running(avg_running, avg_enabled);
1317 fputc('\n', output);
1318 return;
1319 }
1320
1321 if (scaled) {
1322 double avg_enabled, avg_running;
1323
1324 avg_enabled = avg_stats(&ps->res_stats[1]);
1325 avg_running = avg_stats(&ps->res_stats[2]);
1326
1327 fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled);
1328 }
1329 fprintf(output, "\n"); 1343 fprintf(output, "\n");
1330} 1344}
1331 1345
@@ -1367,6 +1381,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
1367 fprintf(output, "%s%s", 1381 fprintf(output, "%s%s",
1368 csv_sep, counter->cgrp->name); 1382 csv_sep, counter->cgrp->name);
1369 1383
1384 print_running(run, ena);
1370 fputc('\n', output); 1385 fputc('\n', output);
1371 continue; 1386 continue;
1372 } 1387 }
@@ -1378,13 +1393,10 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
1378 else 1393 else
1379 abs_printout(cpu, 0, counter, uval); 1394 abs_printout(cpu, 0, counter, uval);
1380 1395
1381 if (!csv_output) { 1396 if (!csv_output)
1382 print_noise(counter, 1.0); 1397 print_noise(counter, 1.0);
1398 print_running(run, ena);
1383 1399
1384 if (run != ena)
1385 fprintf(output, " (%.2f%%)",
1386 100.0 * run / ena);
1387 }
1388 fputc('\n', output); 1400 fputc('\n', output);
1389 } 1401 }
1390} 1402}
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index f3bb1a4bf060..e50fe1187b0b 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -67,6 +67,7 @@ struct timechart {
67 skip_eagain; 67 skip_eagain;
68 u64 min_time, 68 u64 min_time,
69 merge_dist; 69 merge_dist;
70 bool force;
70}; 71};
71 72
72struct per_pidcomm; 73struct per_pidcomm;
@@ -1598,6 +1599,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1598 struct perf_data_file file = { 1599 struct perf_data_file file = {
1599 .path = input_name, 1600 .path = input_name,
1600 .mode = PERF_DATA_MODE_READ, 1601 .mode = PERF_DATA_MODE_READ,
1602 .force = tchart->force,
1601 }; 1603 };
1602 1604
1603 struct perf_session *session = perf_session__new(&file, false, 1605 struct perf_session *session = perf_session__new(&file, false,
@@ -1623,7 +1625,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1623 goto out_delete; 1625 goto out_delete;
1624 } 1626 }
1625 1627
1626 ret = perf_session__process_events(session, &tchart->tool); 1628 ret = perf_session__process_events(session);
1627 if (ret) 1629 if (ret)
1628 goto out_delete; 1630 goto out_delete;
1629 1631
@@ -1956,9 +1958,11 @@ int cmd_timechart(int argc, const char **argv,
1956 OPT_CALLBACK(0, "io-merge-dist", &tchart.merge_dist, "time", 1958 OPT_CALLBACK(0, "io-merge-dist", &tchart.merge_dist, "time",
1957 "merge events that are merge-dist us apart", 1959 "merge events that are merge-dist us apart",
1958 parse_time), 1960 parse_time),
1961 OPT_BOOLEAN('f', "force", &tchart.force, "don't complain, do it"),
1959 OPT_END() 1962 OPT_END()
1960 }; 1963 };
1961 const char * const timechart_usage[] = { 1964 const char * const timechart_subcommands[] = { "record", NULL };
1965 const char *timechart_usage[] = {
1962 "perf timechart [<options>] {record}", 1966 "perf timechart [<options>] {record}",
1963 NULL 1967 NULL
1964 }; 1968 };
@@ -1976,8 +1980,8 @@ int cmd_timechart(int argc, const char **argv,
1976 "perf timechart record [<options>]", 1980 "perf timechart record [<options>]",
1977 NULL 1981 NULL
1978 }; 1982 };
1979 argc = parse_options(argc, argv, timechart_options, timechart_usage, 1983 argc = parse_options_subcommand(argc, argv, timechart_options, timechart_subcommands,
1980 PARSE_OPT_STOP_AT_NON_OPTION); 1984 timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION);
1981 1985
1982 if (tchart.power_only && tchart.tasks_only) { 1986 if (tchart.power_only && tchart.tasks_only) {
1983 pr_err("-P and -T options cannot be used at the same time.\n"); 1987 pr_err("-P and -T options cannot be used at the same time.\n");
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c4c7eac69de4..1cb3436276d1 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -716,7 +716,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
716 716
717 if (!machine) { 717 if (!machine) {
718 pr_err("%u unprocessable samples recorded.\r", 718 pr_err("%u unprocessable samples recorded.\r",
719 top->session->stats.nr_unprocessable_samples++); 719 top->session->evlist->stats.nr_unprocessable_samples++);
720 return; 720 return;
721 } 721 }
722 722
@@ -757,8 +757,10 @@ static void perf_event__process_sample(struct perf_tool *tool,
757 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 757 al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
758 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 758 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
759 if (symbol_conf.vmlinux_name) { 759 if (symbol_conf.vmlinux_name) {
760 ui__warning("The %s file can't be used.\n%s", 760 char serr[256];
761 symbol_conf.vmlinux_name, msg); 761 dso__strerror_load(al.map->dso, serr, sizeof(serr));
762 ui__warning("The %s file can't be used: %s\n%s",
763 symbol_conf.vmlinux_name, serr, msg);
762 } else { 764 } else {
763 ui__warning("A vmlinux file was not found.\n%s", 765 ui__warning("A vmlinux file was not found.\n%s",
764 msg); 766 msg);
@@ -856,7 +858,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
856 hists__inc_nr_events(evsel__hists(evsel), event->header.type); 858 hists__inc_nr_events(evsel__hists(evsel), event->header.type);
857 machine__process_event(machine, event, &sample); 859 machine__process_event(machine, event, &sample);
858 } else 860 } else
859 ++session->stats.nr_unknown_events; 861 ++session->evlist->stats.nr_unknown_events;
860next_event: 862next_event:
861 perf_evlist__mmap_consume(top->evlist, idx); 863 perf_evlist__mmap_consume(top->evlist, idx);
862 } 864 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 7e935f1083ec..e124741be187 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -52,7 +52,9 @@ struct tp_field {
52#define TP_UINT_FIELD(bits) \ 52#define TP_UINT_FIELD(bits) \
53static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \ 53static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
54{ \ 54{ \
55 return *(u##bits *)(sample->raw_data + field->offset); \ 55 u##bits value; \
56 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
57 return value; \
56} 58}
57 59
58TP_UINT_FIELD(8); 60TP_UINT_FIELD(8);
@@ -63,7 +65,8 @@ TP_UINT_FIELD(64);
63#define TP_UINT_FIELD__SWAPPED(bits) \ 65#define TP_UINT_FIELD__SWAPPED(bits) \
64static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \ 66static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
65{ \ 67{ \
66 u##bits value = *(u##bits *)(sample->raw_data + field->offset); \ 68 u##bits value; \
69 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
67 return bswap_##bits(value);\ 70 return bswap_##bits(value);\
68} 71}
69 72
@@ -1132,6 +1135,8 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
1132 1135
1133struct syscall { 1136struct syscall {
1134 struct event_format *tp_format; 1137 struct event_format *tp_format;
1138 int nr_args;
1139 struct format_field *args;
1135 const char *name; 1140 const char *name;
1136 bool filtered; 1141 bool filtered;
1137 bool is_exit; 1142 bool is_exit;
@@ -1219,7 +1224,9 @@ struct trace {
1219 struct syscall *table; 1224 struct syscall *table;
1220 } syscalls; 1225 } syscalls;
1221 struct record_opts opts; 1226 struct record_opts opts;
1227 struct perf_evlist *evlist;
1222 struct machine *host; 1228 struct machine *host;
1229 struct thread *current;
1223 u64 base_time; 1230 u64 base_time;
1224 FILE *output; 1231 FILE *output;
1225 unsigned long nr_events; 1232 unsigned long nr_events;
@@ -1227,6 +1234,10 @@ struct trace {
1227 const char *last_vfs_getname; 1234 const char *last_vfs_getname;
1228 struct intlist *tid_list; 1235 struct intlist *tid_list;
1229 struct intlist *pid_list; 1236 struct intlist *pid_list;
1237 struct {
1238 size_t nr;
1239 pid_t *entries;
1240 } filter_pids;
1230 double duration_filter; 1241 double duration_filter;
1231 double runtime_ms; 1242 double runtime_ms;
1232 struct { 1243 struct {
@@ -1243,6 +1254,7 @@ struct trace {
1243 bool show_comm; 1254 bool show_comm;
1244 bool show_tool_stats; 1255 bool show_tool_stats;
1245 bool trace_syscalls; 1256 bool trace_syscalls;
1257 bool force;
1246 int trace_pgfaults; 1258 int trace_pgfaults;
1247}; 1259};
1248 1260
@@ -1433,14 +1445,14 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1433 struct format_field *field; 1445 struct format_field *field;
1434 int idx = 0; 1446 int idx = 0;
1435 1447
1436 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *)); 1448 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
1437 if (sc->arg_scnprintf == NULL) 1449 if (sc->arg_scnprintf == NULL)
1438 return -1; 1450 return -1;
1439 1451
1440 if (sc->fmt) 1452 if (sc->fmt)
1441 sc->arg_parm = sc->fmt->arg_parm; 1453 sc->arg_parm = sc->fmt->arg_parm;
1442 1454
1443 for (field = sc->tp_format->format.fields->next; field; field = field->next) { 1455 for (field = sc->args; field; field = field->next) {
1444 if (sc->fmt && sc->fmt->arg_scnprintf[idx]) 1456 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1445 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1457 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1446 else if (field->flags & FIELD_IS_POINTER) 1458 else if (field->flags & FIELD_IS_POINTER)
@@ -1506,18 +1518,37 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1506 if (sc->tp_format == NULL) 1518 if (sc->tp_format == NULL)
1507 return -1; 1519 return -1;
1508 1520
1521 sc->args = sc->tp_format->format.fields;
1522 sc->nr_args = sc->tp_format->format.nr_fields;
1523 /* drop nr field - not relevant here; does not exist on older kernels */
1524 if (sc->args && strcmp(sc->args->name, "nr") == 0) {
1525 sc->args = sc->args->next;
1526 --sc->nr_args;
1527 }
1528
1509 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit"); 1529 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1510 1530
1511 return syscall__set_arg_fmts(sc); 1531 return syscall__set_arg_fmts(sc);
1512} 1532}
1513 1533
1534/*
1535 * args is to be interpreted as a series of longs but we need to handle
1536 * 8-byte unaligned accesses. args points to raw_data within the event
1537 * and raw_data is guaranteed to be 8-byte unaligned because it is
1538 * preceded by raw_size which is a u32. So we need to copy args to a temp
1539 * variable to read it. Most notably this avoids extended load instructions
1540 * on unaligned addresses
1541 */
1542
1514static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1543static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1515 unsigned long *args, struct trace *trace, 1544 unsigned char *args, struct trace *trace,
1516 struct thread *thread) 1545 struct thread *thread)
1517{ 1546{
1518 size_t printed = 0; 1547 size_t printed = 0;
1548 unsigned char *p;
1549 unsigned long val;
1519 1550
1520 if (sc->tp_format != NULL) { 1551 if (sc->args != NULL) {
1521 struct format_field *field; 1552 struct format_field *field;
1522 u8 bit = 1; 1553 u8 bit = 1;
1523 struct syscall_arg arg = { 1554 struct syscall_arg arg = {
@@ -1527,16 +1558,21 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1527 .thread = thread, 1558 .thread = thread,
1528 }; 1559 };
1529 1560
1530 for (field = sc->tp_format->format.fields->next; field; 1561 for (field = sc->args; field;
1531 field = field->next, ++arg.idx, bit <<= 1) { 1562 field = field->next, ++arg.idx, bit <<= 1) {
1532 if (arg.mask & bit) 1563 if (arg.mask & bit)
1533 continue; 1564 continue;
1565
1566 /* special care for unaligned accesses */
1567 p = args + sizeof(unsigned long) * arg.idx;
1568 memcpy(&val, p, sizeof(val));
1569
1534 /* 1570 /*
1535 * Suppress this argument if its value is zero and 1571 * Suppress this argument if its value is zero and
1536 * and we don't have a string associated in an 1572 * and we don't have a string associated in an
1537 * strarray for it. 1573 * strarray for it.
1538 */ 1574 */
1539 if (args[arg.idx] == 0 && 1575 if (val == 0 &&
1540 !(sc->arg_scnprintf && 1576 !(sc->arg_scnprintf &&
1541 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY && 1577 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1542 sc->arg_parm[arg.idx])) 1578 sc->arg_parm[arg.idx]))
@@ -1545,23 +1581,26 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1545 printed += scnprintf(bf + printed, size - printed, 1581 printed += scnprintf(bf + printed, size - printed,
1546 "%s%s: ", printed ? ", " : "", field->name); 1582 "%s%s: ", printed ? ", " : "", field->name);
1547 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) { 1583 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
1548 arg.val = args[arg.idx]; 1584 arg.val = val;
1549 if (sc->arg_parm) 1585 if (sc->arg_parm)
1550 arg.parm = sc->arg_parm[arg.idx]; 1586 arg.parm = sc->arg_parm[arg.idx];
1551 printed += sc->arg_scnprintf[arg.idx](bf + printed, 1587 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1552 size - printed, &arg); 1588 size - printed, &arg);
1553 } else { 1589 } else {
1554 printed += scnprintf(bf + printed, size - printed, 1590 printed += scnprintf(bf + printed, size - printed,
1555 "%ld", args[arg.idx]); 1591 "%ld", val);
1556 } 1592 }
1557 } 1593 }
1558 } else { 1594 } else {
1559 int i = 0; 1595 int i = 0;
1560 1596
1561 while (i < 6) { 1597 while (i < 6) {
1598 /* special care for unaligned accesses */
1599 p = args + sizeof(unsigned long) * i;
1600 memcpy(&val, p, sizeof(val));
1562 printed += scnprintf(bf + printed, size - printed, 1601 printed += scnprintf(bf + printed, size - printed,
1563 "%sarg%d: %ld", 1602 "%sarg%d: %ld",
1564 printed ? ", " : "", i, args[i]); 1603 printed ? ", " : "", i, val);
1565 ++i; 1604 ++i;
1566 } 1605 }
1567 } 1606 }
@@ -1642,6 +1681,29 @@ static void thread__update_stats(struct thread_trace *ttrace,
1642 update_stats(stats, duration); 1681 update_stats(stats, duration);
1643} 1682}
1644 1683
1684static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1685{
1686 struct thread_trace *ttrace;
1687 u64 duration;
1688 size_t printed;
1689
1690 if (trace->current == NULL)
1691 return 0;
1692
1693 ttrace = thread__priv(trace->current);
1694
1695 if (!ttrace->entry_pending)
1696 return 0;
1697
1698 duration = sample->time - ttrace->entry_time;
1699
1700 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1701 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1702 ttrace->entry_pending = false;
1703
1704 return printed;
1705}
1706
1645static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1707static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1646 union perf_event *event __maybe_unused, 1708 union perf_event *event __maybe_unused,
1647 struct perf_sample *sample) 1709 struct perf_sample *sample)
@@ -1673,6 +1735,9 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1673 return -1; 1735 return -1;
1674 } 1736 }
1675 1737
1738 if (!trace->summary_only)
1739 trace__printf_interrupted_entry(trace, sample);
1740
1676 ttrace->entry_time = sample->time; 1741 ttrace->entry_time = sample->time;
1677 msg = ttrace->entry_str; 1742 msg = ttrace->entry_str;
1678 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); 1743 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
@@ -1688,6 +1753,11 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1688 } else 1753 } else
1689 ttrace->entry_pending = true; 1754 ttrace->entry_pending = true;
1690 1755
1756 if (trace->current != thread) {
1757 thread__put(trace->current);
1758 trace->current = thread__get(thread);
1759 }
1760
1691 return 0; 1761 return 0;
1692} 1762}
1693 1763
@@ -1805,6 +1875,28 @@ out_dump:
1805 return 0; 1875 return 0;
1806} 1876}
1807 1877
1878static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1879 union perf_event *event __maybe_unused,
1880 struct perf_sample *sample)
1881{
1882 trace__printf_interrupted_entry(trace, sample);
1883 trace__fprintf_tstamp(trace, sample->time, trace->output);
1884
1885 if (trace->trace_syscalls)
1886 fprintf(trace->output, "( ): ");
1887
1888 fprintf(trace->output, "%s:", evsel->name);
1889
1890 if (evsel->tp_format) {
1891 event_format__fprintf(evsel->tp_format, sample->cpu,
1892 sample->raw_data, sample->raw_size,
1893 trace->output);
1894 }
1895
1896 fprintf(trace->output, ")\n");
1897 return 0;
1898}
1899
1808static void print_location(FILE *f, struct perf_sample *sample, 1900static void print_location(FILE *f, struct perf_sample *sample,
1809 struct addr_location *al, 1901 struct addr_location *al,
1810 bool print_dso, bool print_sym) 1902 bool print_dso, bool print_sym)
@@ -2037,10 +2129,39 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2037 return 0; 2129 return 0;
2038} 2130}
2039 2131
2040static int trace__run(struct trace *trace, int argc, const char **argv) 2132static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2041{ 2133{
2042 struct perf_evlist *evlist = perf_evlist__new(); 2134 const u32 type = event->header.type;
2043 struct perf_evsel *evsel; 2135 struct perf_evsel *evsel;
2136
2137 if (!trace->full_time && trace->base_time == 0)
2138 trace->base_time = sample->time;
2139
2140 if (type != PERF_RECORD_SAMPLE) {
2141 trace__process_event(trace, trace->host, event, sample);
2142 return;
2143 }
2144
2145 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2146 if (evsel == NULL) {
2147 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2148 return;
2149 }
2150
2151 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2152 sample->raw_data == NULL) {
2153 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2154 perf_evsel__name(evsel), sample->tid,
2155 sample->cpu, sample->raw_size);
2156 } else {
2157 tracepoint_handler handler = evsel->handler;
2158 handler(trace, evsel, event, sample);
2159 }
2160}
2161
2162static int trace__run(struct trace *trace, int argc, const char **argv)
2163{
2164 struct perf_evlist *evlist = trace->evlist;
2044 int err = -1, i; 2165 int err = -1, i;
2045 unsigned long before; 2166 unsigned long before;
2046 const bool forks = argc > 0; 2167 const bool forks = argc > 0;
@@ -2048,11 +2169,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2048 2169
2049 trace->live = true; 2170 trace->live = true;
2050 2171
2051 if (evlist == NULL) {
2052 fprintf(trace->output, "Not enough memory to run!\n");
2053 goto out;
2054 }
2055
2056 if (trace->trace_syscalls && 2172 if (trace->trace_syscalls &&
2057 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, 2173 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
2058 trace__sys_exit)) 2174 trace__sys_exit))
@@ -2105,16 +2221,34 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2105 if (err < 0) 2221 if (err < 0)
2106 goto out_error_open; 2222 goto out_error_open;
2107 2223
2224 /*
2225 * Better not use !target__has_task() here because we need to cover the
2226 * case where no threads were specified in the command line, but a
2227 * workload was, and in that case we will fill in the thread_map when
2228 * we fork the workload in perf_evlist__prepare_workload.
2229 */
2230 if (trace->filter_pids.nr > 0)
2231 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
2232 else if (evlist->threads->map[0] == -1)
2233 err = perf_evlist__set_filter_pid(evlist, getpid());
2234
2235 if (err < 0) {
2236 printf("err=%d,%s\n", -err, strerror(-err));
2237 exit(1);
2238 }
2239
2108 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2240 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
2109 if (err < 0) 2241 if (err < 0)
2110 goto out_error_mmap; 2242 goto out_error_mmap;
2111 2243
2112 perf_evlist__enable(evlist);
2113
2114 if (forks) 2244 if (forks)
2115 perf_evlist__start_workload(evlist); 2245 perf_evlist__start_workload(evlist);
2246 else
2247 perf_evlist__enable(evlist);
2116 2248
2117 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1; 2249 trace->multiple_threads = evlist->threads->map[0] == -1 ||
2250 evlist->threads->nr > 1 ||
2251 perf_evlist__first(evlist)->attr.inherit;
2118again: 2252again:
2119 before = trace->nr_events; 2253 before = trace->nr_events;
2120 2254
@@ -2122,8 +2256,6 @@ again:
2122 union perf_event *event; 2256 union perf_event *event;
2123 2257
2124 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 2258 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
2125 const u32 type = event->header.type;
2126 tracepoint_handler handler;
2127 struct perf_sample sample; 2259 struct perf_sample sample;
2128 2260
2129 ++trace->nr_events; 2261 ++trace->nr_events;
@@ -2134,30 +2266,7 @@ again:
2134 goto next_event; 2266 goto next_event;
2135 } 2267 }
2136 2268
2137 if (!trace->full_time && trace->base_time == 0) 2269 trace__handle_event(trace, event, &sample);
2138 trace->base_time = sample.time;
2139
2140 if (type != PERF_RECORD_SAMPLE) {
2141 trace__process_event(trace, trace->host, event, &sample);
2142 continue;
2143 }
2144
2145 evsel = perf_evlist__id2evsel(evlist, sample.id);
2146 if (evsel == NULL) {
2147 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
2148 goto next_event;
2149 }
2150
2151 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2152 sample.raw_data == NULL) {
2153 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2154 perf_evsel__name(evsel), sample.tid,
2155 sample.cpu, sample.raw_size);
2156 goto next_event;
2157 }
2158
2159 handler = evsel->handler;
2160 handler(trace, evsel, event, &sample);
2161next_event: 2270next_event:
2162 perf_evlist__mmap_consume(evlist, i); 2271 perf_evlist__mmap_consume(evlist, i);
2163 2272
@@ -2180,6 +2289,8 @@ next_event:
2180 } 2289 }
2181 2290
2182out_disable: 2291out_disable:
2292 thread__zput(trace->current);
2293
2183 perf_evlist__disable(evlist); 2294 perf_evlist__disable(evlist);
2184 2295
2185 if (!err) { 2296 if (!err) {
@@ -2197,7 +2308,7 @@ out_disable:
2197 2308
2198out_delete_evlist: 2309out_delete_evlist:
2199 perf_evlist__delete(evlist); 2310 perf_evlist__delete(evlist);
2200out: 2311 trace->evlist = NULL;
2201 trace->live = false; 2312 trace->live = false;
2202 return err; 2313 return err;
2203{ 2314{
@@ -2235,6 +2346,7 @@ static int trace__replay(struct trace *trace)
2235 struct perf_data_file file = { 2346 struct perf_data_file file = {
2236 .path = input_name, 2347 .path = input_name,
2237 .mode = PERF_DATA_MODE_READ, 2348 .mode = PERF_DATA_MODE_READ,
2349 .force = trace->force,
2238 }; 2350 };
2239 struct perf_session *session; 2351 struct perf_session *session;
2240 struct perf_evsel *evsel; 2352 struct perf_evsel *evsel;
@@ -2309,7 +2421,7 @@ static int trace__replay(struct trace *trace)
2309 2421
2310 setup_pager(); 2422 setup_pager();
2311 2423
2312 err = perf_session__process_events(session, &trace->tool); 2424 err = perf_session__process_events(session);
2313 if (err) 2425 if (err)
2314 pr_err("Failed to process events, error %d", err); 2426 pr_err("Failed to process events, error %d", err);
2315 2427
@@ -2434,6 +2546,38 @@ static int trace__set_duration(const struct option *opt, const char *str,
2434 return 0; 2546 return 0;
2435} 2547}
2436 2548
2549static int trace__set_filter_pids(const struct option *opt, const char *str,
2550 int unset __maybe_unused)
2551{
2552 int ret = -1;
2553 size_t i;
2554 struct trace *trace = opt->value;
2555 /*
2556 * FIXME: introduce a intarray class, plain parse csv and create a
2557 * { int nr, int entries[] } struct...
2558 */
2559 struct intlist *list = intlist__new(str);
2560
2561 if (list == NULL)
2562 return -1;
2563
2564 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2565 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2566
2567 if (trace->filter_pids.entries == NULL)
2568 goto out;
2569
2570 trace->filter_pids.entries[0] = getpid();
2571
2572 for (i = 1; i < trace->filter_pids.nr; ++i)
2573 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2574
2575 intlist__delete(list);
2576 ret = 0;
2577out:
2578 return ret;
2579}
2580
2437static int trace__open_output(struct trace *trace, const char *filename) 2581static int trace__open_output(struct trace *trace, const char *filename)
2438{ 2582{
2439 struct stat st; 2583 struct stat st;
@@ -2468,9 +2612,17 @@ static int parse_pagefaults(const struct option *opt, const char *str,
2468 return 0; 2612 return 0;
2469} 2613}
2470 2614
2615static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2616{
2617 struct perf_evsel *evsel;
2618
2619 evlist__for_each(evlist, evsel)
2620 evsel->handler = handler;
2621}
2622
2471int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 2623int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2472{ 2624{
2473 const char * const trace_usage[] = { 2625 const char *trace_usage[] = {
2474 "perf trace [<options>] [<command>]", 2626 "perf trace [<options>] [<command>]",
2475 "perf trace [<options>] -- <command> [<options>]", 2627 "perf trace [<options>] -- <command> [<options>]",
2476 "perf trace record [<options>] [<command>]", 2628 "perf trace record [<options>] [<command>]",
@@ -2502,6 +2654,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2502 const char *output_name = NULL; 2654 const char *output_name = NULL;
2503 const char *ev_qualifier_str = NULL; 2655 const char *ev_qualifier_str = NULL;
2504 const struct option trace_options[] = { 2656 const struct option trace_options[] = {
2657 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2658 "event selector. use 'perf list' to list available events",
2659 parse_events_option),
2505 OPT_BOOLEAN(0, "comm", &trace.show_comm, 2660 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2506 "show the thread COMM next to its id"), 2661 "show the thread COMM next to its id"),
2507 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"), 2662 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
@@ -2513,6 +2668,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2513 "trace events on existing process id"), 2668 "trace events on existing process id"),
2514 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid", 2669 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
2515 "trace events on existing thread id"), 2670 "trace events on existing thread id"),
2671 OPT_CALLBACK(0, "filter-pids", &trace, "float",
2672 "show only events with duration > N.M ms", trace__set_filter_pids),
2516 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide, 2673 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
2517 "system-wide collection from all CPUs"), 2674 "system-wide collection from all CPUs"),
2518 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu", 2675 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
@@ -2538,19 +2695,36 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2538 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min", 2695 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
2539 "Trace pagefaults", parse_pagefaults, "maj"), 2696 "Trace pagefaults", parse_pagefaults, "maj"),
2540 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), 2697 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
2698 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
2541 OPT_END() 2699 OPT_END()
2542 }; 2700 };
2701 const char * const trace_subcommands[] = { "record", NULL };
2543 int err; 2702 int err;
2544 char bf[BUFSIZ]; 2703 char bf[BUFSIZ];
2545 2704
2546 argc = parse_options(argc, argv, trace_options, trace_usage, 2705 signal(SIGSEGV, sighandler_dump_stack);
2547 PARSE_OPT_STOP_AT_NON_OPTION); 2706 signal(SIGFPE, sighandler_dump_stack);
2707
2708 trace.evlist = perf_evlist__new();
2709 if (trace.evlist == NULL)
2710 return -ENOMEM;
2711
2712 if (trace.evlist == NULL) {
2713 pr_err("Not enough memory to run!\n");
2714 goto out;
2715 }
2716
2717 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
2718 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
2548 2719
2549 if (trace.trace_pgfaults) { 2720 if (trace.trace_pgfaults) {
2550 trace.opts.sample_address = true; 2721 trace.opts.sample_address = true;
2551 trace.opts.sample_time = true; 2722 trace.opts.sample_time = true;
2552 } 2723 }
2553 2724
2725 if (trace.evlist->nr_entries > 0)
2726 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
2727
2554 if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) 2728 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2555 return trace__record(&trace, argc-1, &argv[1]); 2729 return trace__record(&trace, argc-1, &argv[1]);
2556 2730
@@ -2558,7 +2732,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2558 if (trace.summary_only) 2732 if (trace.summary_only)
2559 trace.summary = trace.summary_only; 2733 trace.summary = trace.summary_only;
2560 2734
2561 if (!trace.trace_syscalls && !trace.trace_pgfaults) { 2735 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
2736 trace.evlist->nr_entries == 0 /* Was --events used? */) {
2562 pr_err("Please specify something to trace.\n"); 2737 pr_err("Please specify something to trace.\n");
2563 return -1; 2738 return -1;
2564 } 2739 }
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index b210d62907e4..3688ad29085f 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -37,6 +37,7 @@ extern int cmd_test(int argc, const char **argv, const char *prefix);
37extern int cmd_trace(int argc, const char **argv, const char *prefix); 37extern int cmd_trace(int argc, const char **argv, const char *prefix);
38extern int cmd_inject(int argc, const char **argv, const char *prefix); 38extern int cmd_inject(int argc, const char **argv, const char *prefix);
39extern int cmd_mem(int argc, const char **argv, const char *prefix); 39extern int cmd_mem(int argc, const char **argv, const char *prefix);
40extern int cmd_data(int argc, const char **argv, const char *prefix);
40 41
41extern int find_scripts(char **scripts_array, char **scripts_path_array); 42extern int find_scripts(char **scripts_array, char **scripts_path_array);
42#endif 43#endif
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 0906fc401c52..00fcaf8a5b8d 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -7,6 +7,7 @@ perf-archive mainporcelain common
7perf-bench mainporcelain common 7perf-bench mainporcelain common
8perf-buildid-cache mainporcelain common 8perf-buildid-cache mainporcelain common
9perf-buildid-list mainporcelain common 9perf-buildid-list mainporcelain common
10perf-data mainporcelain common
10perf-diff mainporcelain common 11perf-diff mainporcelain common
11perf-evlist mainporcelain common 12perf-evlist mainporcelain common
12perf-inject mainporcelain common 13perf-inject mainporcelain common
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index cc224080b525..59a98c643240 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -11,19 +11,26 @@ ifneq ($(obj-perf),)
11obj-perf := $(abspath $(obj-perf))/ 11obj-perf := $(abspath $(obj-perf))/
12endif 12endif
13 13
14LIB_INCLUDE := $(srctree)/tools/lib/ 14$(shell echo -n > .config-detected)
15detected = $(shell echo "$(1)=y" >> .config-detected)
16detected_var = $(shell echo "$(1)=$($(1))" >> .config-detected)
17
15CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS) 18CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
16 19
17include $(src-perf)/config/Makefile.arch 20include $(src-perf)/config/Makefile.arch
18 21
22$(call detected_var,ARCH)
23
19NO_PERF_REGS := 1 24NO_PERF_REGS := 1
20 25
21# Additional ARCH settings for x86 26# Additional ARCH settings for x86
22ifeq ($(ARCH),x86) 27ifeq ($(ARCH),x86)
28 $(call detected,CONFIG_X86)
23 ifeq (${IS_64_BIT}, 1) 29 ifeq (${IS_64_BIT}, 1)
24 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT 30 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
25 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 31 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
26 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
33 $(call detected,CONFIG_X86_64)
27 else 34 else
28 LIBUNWIND_LIBS = -lunwind -lunwind-x86 35 LIBUNWIND_LIBS = -lunwind -lunwind-x86
29 endif 36 endif
@@ -40,6 +47,10 @@ ifeq ($(ARCH),arm64)
40 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 47 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
41endif 48endif
42 49
50ifeq ($(NO_PERF_REGS),0)
51 $(call detected,CONFIG_PERF_REGS)
52endif
53
43# So far there's only x86 and arm libdw unwind support merged in perf. 54# So far there's only x86 and arm libdw unwind support merged in perf.
44# Disable it on all other architectures in case libdw unwind 55# Disable it on all other architectures in case libdw unwind
45# support is detected in system. Add supported architectures 56# support is detected in system. Add supported architectures
@@ -84,6 +95,17 @@ ifndef NO_LIBELF
84 FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw 95 FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
85endif 96endif
86 97
98ifdef LIBBABELTRACE
99 # for linking with debug library, run like:
100 # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
101 ifdef LIBBABELTRACE_DIR
102 LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include
103 LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib
104 endif
105 FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
106 FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
107endif
108
87# include ARCH specific config 109# include ARCH specific config
88-include $(src-perf)/arch/$(ARCH)/Makefile 110-include $(src-perf)/arch/$(ARCH)/Makefile
89 111
@@ -114,6 +136,8 @@ ifdef PARSER_DEBUG
114 PARSER_DEBUG_BISON := -t 136 PARSER_DEBUG_BISON := -t
115 PARSER_DEBUG_FLEX := -d 137 PARSER_DEBUG_FLEX := -d
116 CFLAGS += -DPARSER_DEBUG 138 CFLAGS += -DPARSER_DEBUG
139 $(call detected_var,PARSER_DEBUG_BISON)
140 $(call detected_var,PARSER_DEBUG_FLEX)
117endif 141endif
118 142
119ifndef NO_LIBPYTHON 143ifndef NO_LIBPYTHON
@@ -152,121 +176,7 @@ LDFLAGS += -Wl,-z,noexecstack
152 176
153EXTLIBS = -lpthread -lrt -lm -ldl 177EXTLIBS = -lpthread -lrt -lm -ldl
154 178
155ifneq ($(OUTPUT),) 179include $(srctree)/tools/build/Makefile.feature
156 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
157 $(shell mkdir -p $(OUTPUT_FEATURES))
158endif
159
160feature_check = $(eval $(feature_check_code))
161define feature_check_code
162 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
163endef
164
165feature_set = $(eval $(feature_set_code))
166define feature_set_code
167 feature-$(1) := 1
168endef
169
170#
171# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
172#
173
174#
175# Note that this is not a complete list of all feature tests, just
176# those that are typically built on a fully configured system.
177#
178# [ Feature tests not mentioned here have to be built explicitly in
179# the rule that uses them - an example for that is the 'bionic'
180# feature check. ]
181#
182CORE_FEATURE_TESTS = \
183 backtrace \
184 dwarf \
185 fortify-source \
186 sync-compare-and-swap \
187 glibc \
188 gtk2 \
189 gtk2-infobar \
190 libaudit \
191 libbfd \
192 libelf \
193 libelf-getphdrnum \
194 libelf-mmap \
195 libnuma \
196 libperl \
197 libpython \
198 libpython-version \
199 libslang \
200 libunwind \
201 pthread-attr-setaffinity-np \
202 stackprotector-all \
203 timerfd \
204 libdw-dwarf-unwind \
205 zlib
206
207LIB_FEATURE_TESTS = \
208 dwarf \
209 glibc \
210 gtk2 \
211 libaudit \
212 libbfd \
213 libelf \
214 libnuma \
215 libperl \
216 libpython \
217 libslang \
218 libunwind \
219 libdw-dwarf-unwind \
220 zlib
221
222VF_FEATURE_TESTS = \
223 backtrace \
224 fortify-source \
225 sync-compare-and-swap \
226 gtk2-infobar \
227 libelf-getphdrnum \
228 libelf-mmap \
229 libpython-version \
230 pthread-attr-setaffinity-np \
231 stackprotector-all \
232 timerfd \
233 libunwind-debug-frame \
234 bionic \
235 liberty \
236 liberty-z \
237 cplus-demangle \
238 compile-32 \
239 compile-x32
240
241# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
242# If in the future we need per-feature checks/flags for features not
243# mentioned in this list we need to refactor this ;-).
244set_test_all_flags = $(eval $(set_test_all_flags_code))
245define set_test_all_flags_code
246 FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1))
247 FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
248endef
249
250$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
251
252#
253# Special fast-path for the 'all features are available' case:
254#
255$(call feature_check,all,$(MSG))
256
257#
258# Just in case the build freshly failed, make sure we print the
259# feature matrix:
260#
261ifeq ($(feature-all), 1)
262 #
263 # test-all.c passed - just set all the core feature flags to 1:
264 #
265 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
266else
267 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(CORE_FEATURE_TESTS)) >/dev/null 2>&1)
268 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
269endif
270 180
271ifeq ($(feature-stackprotector-all), 1) 181ifeq ($(feature-stackprotector-all), 1)
272 CFLAGS += -fstack-protector-all 182 CFLAGS += -fstack-protector-all
@@ -295,7 +205,7 @@ endif
295 205
296CFLAGS += -I$(src-perf)/util 206CFLAGS += -I$(src-perf)/util
297CFLAGS += -I$(src-perf) 207CFLAGS += -I$(src-perf)
298CFLAGS += -I$(LIB_INCLUDE) 208CFLAGS += -I$(srctree)/tools/lib/
299 209
300CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 210CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
301 211
@@ -361,6 +271,7 @@ endif # NO_LIBELF
361ifndef NO_LIBELF 271ifndef NO_LIBELF
362 CFLAGS += -DHAVE_LIBELF_SUPPORT 272 CFLAGS += -DHAVE_LIBELF_SUPPORT
363 EXTLIBS += -lelf 273 EXTLIBS += -lelf
274 $(call detected,CONFIG_LIBELF)
364 275
365 ifeq ($(feature-libelf-mmap), 1) 276 ifeq ($(feature-libelf-mmap), 1)
366 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT 277 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
@@ -381,6 +292,7 @@ ifndef NO_LIBELF
381 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) 292 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
382 LDFLAGS += $(LIBDW_LDFLAGS) 293 LDFLAGS += $(LIBDW_LDFLAGS)
383 EXTLIBS += -ldw 294 EXTLIBS += -ldw
295 $(call detected,CONFIG_DWARF)
384 endif # PERF_HAVE_DWARF_REGS 296 endif # PERF_HAVE_DWARF_REGS
385 endif # NO_DWARF 297 endif # NO_DWARF
386endif # NO_LIBELF 298endif # NO_LIBELF
@@ -408,9 +320,11 @@ ifdef NO_LIBUNWIND
408 dwarf-post-unwind := 0 320 dwarf-post-unwind := 0
409 else 321 else
410 dwarf-post-unwind-text := libdw 322 dwarf-post-unwind-text := libdw
323 $(call detected,CONFIG_LIBDW_DWARF_UNWIND)
411 endif 324 endif
412else 325else
413 dwarf-post-unwind-text := libunwind 326 dwarf-post-unwind-text := libunwind
327 $(call detected,CONFIG_LIBUNWIND)
414 # Enable libunwind support by default. 328 # Enable libunwind support by default.
415 ifndef NO_LIBDW_DWARF_UNWIND 329 ifndef NO_LIBDW_DWARF_UNWIND
416 NO_LIBDW_DWARF_UNWIND := 1 330 NO_LIBDW_DWARF_UNWIND := 1
@@ -419,6 +333,7 @@ endif
419 333
420ifeq ($(dwarf-post-unwind),1) 334ifeq ($(dwarf-post-unwind),1)
421 CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT 335 CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT
336 $(call detected,CONFIG_DWARF_UNWIND)
422else 337else
423 NO_DWARF_UNWIND := 1 338 NO_DWARF_UNWIND := 1
424endif 339endif
@@ -447,6 +362,7 @@ ifndef NO_LIBAUDIT
447 else 362 else
448 CFLAGS += -DHAVE_LIBAUDIT_SUPPORT 363 CFLAGS += -DHAVE_LIBAUDIT_SUPPORT
449 EXTLIBS += -laudit 364 EXTLIBS += -laudit
365 $(call detected,CONFIG_AUDIT)
450 endif 366 endif
451endif 367endif
452 368
@@ -463,6 +379,7 @@ ifndef NO_SLANG
463 CFLAGS += -I/usr/include/slang 379 CFLAGS += -I/usr/include/slang
464 CFLAGS += -DHAVE_SLANG_SUPPORT 380 CFLAGS += -DHAVE_SLANG_SUPPORT
465 EXTLIBS += -lslang 381 EXTLIBS += -lslang
382 $(call detected,CONFIG_SLANG)
466 endif 383 endif
467endif 384endif
468 385
@@ -497,10 +414,11 @@ else
497 ifneq ($(feature-libperl), 1) 414 ifneq ($(feature-libperl), 1)
498 CFLAGS += -DNO_LIBPERL 415 CFLAGS += -DNO_LIBPERL
499 NO_LIBPERL := 1 416 NO_LIBPERL := 1
500 msg := $(warning Missing perl devel files. Disabling perl scripting support, consider installing perl-ExtUtils-Embed); 417 msg := $(warning Missing perl devel files. Disabling perl scripting support, please install perl-ExtUtils-Embed/libperl-dev);
501 else 418 else
502 LDFLAGS += $(PERL_EMBED_LDFLAGS) 419 LDFLAGS += $(PERL_EMBED_LDFLAGS)
503 EXTLIBS += $(PERL_EMBED_LIBADD) 420 EXTLIBS += $(PERL_EMBED_LIBADD)
421 $(call detected,CONFIG_LIBPERL)
504 endif 422 endif
505endif 423endif
506 424
@@ -513,22 +431,21 @@ endif
513disable-python = $(eval $(disable-python_code)) 431disable-python = $(eval $(disable-python_code))
514define disable-python_code 432define disable-python_code
515 CFLAGS += -DNO_LIBPYTHON 433 CFLAGS += -DNO_LIBPYTHON
516 $(if $(1),$(warning No $(1) was found)) 434 $(warning $1)
517 $(warning Python support will not be built)
518 NO_LIBPYTHON := 1 435 NO_LIBPYTHON := 1
519endef 436endef
520 437
521ifdef NO_LIBPYTHON 438ifdef NO_LIBPYTHON
522 $(call disable-python) 439 $(call disable-python,Python support disabled by user)
523else 440else
524 441
525 ifndef PYTHON 442 ifndef PYTHON
526 $(call disable-python,python interpreter) 443 $(call disable-python,No python interpreter was found: disables Python support - please install python-devel/python-dev)
527 else 444 else
528 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 445 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
529 446
530 ifndef PYTHON_CONFIG 447 ifndef PYTHON_CONFIG
531 $(call disable-python,python-config tool) 448 $(call disable-python,No 'python-config' tool was found: disables Python support - please install python-devel/python-dev)
532 else 449 else
533 450
534 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) 451 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
@@ -540,7 +457,7 @@ else
540 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 457 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
541 458
542 ifneq ($(feature-libpython), 1) 459 ifneq ($(feature-libpython), 1)
543 $(call disable-python,Python.h (for Python 2.x)) 460 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
544 else 461 else
545 462
546 ifneq ($(feature-libpython-version), 1) 463 ifneq ($(feature-libpython-version), 1)
@@ -560,6 +477,7 @@ else
560 LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 477 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
561 EXTLIBS += $(PYTHON_EMBED_LIBADD) 478 EXTLIBS += $(PYTHON_EMBED_LIBADD)
562 LANG_BINDINGS += $(obj-perf)python/perf.so 479 LANG_BINDINGS += $(obj-perf)python/perf.so
480 $(call detected,CONFIG_LIBPYTHON)
563 endif 481 endif
564 endif 482 endif
565 endif 483 endif
@@ -600,7 +518,7 @@ else
600 EXTLIBS += -liberty 518 EXTLIBS += -liberty
601 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 519 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
602 else 520 else
603 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) 521 msg := $(warning No bfd.h/libbfd found, please install binutils-dev[el]/zlib-static/libiberty-dev to gain symbol demangling)
604 CFLAGS += -DNO_DEMANGLE 522 CFLAGS += -DNO_DEMANGLE
605 endif 523 endif
606 endif 524 endif
@@ -617,11 +535,23 @@ ifndef NO_ZLIB
617 ifeq ($(feature-zlib), 1) 535 ifeq ($(feature-zlib), 1)
618 CFLAGS += -DHAVE_ZLIB_SUPPORT 536 CFLAGS += -DHAVE_ZLIB_SUPPORT
619 EXTLIBS += -lz 537 EXTLIBS += -lz
538 $(call detected,CONFIG_ZLIB)
620 else 539 else
621 NO_ZLIB := 1 540 NO_ZLIB := 1
622 endif 541 endif
623endif 542endif
624 543
544ifndef NO_LZMA
545 ifeq ($(feature-lzma), 1)
546 CFLAGS += -DHAVE_LZMA_SUPPORT
547 EXTLIBS += -llzma
548 $(call detected,CONFIG_LZMA)
549 else
550 msg := $(warning No liblzma found, disables xz kernel module decompression, please install xz-devel/liblzma-dev);
551 NO_LZMA := 1
552 endif
553endif
554
625ifndef NO_BACKTRACE 555ifndef NO_BACKTRACE
626 ifeq ($(feature-backtrace), 1) 556 ifeq ($(feature-backtrace), 1)
627 CFLAGS += -DHAVE_BACKTRACE_SUPPORT 557 CFLAGS += -DHAVE_BACKTRACE_SUPPORT
@@ -635,6 +565,7 @@ ifndef NO_LIBNUMA
635 else 565 else
636 CFLAGS += -DHAVE_LIBNUMA_SUPPORT 566 CFLAGS += -DHAVE_LIBNUMA_SUPPORT
637 EXTLIBS += -lnuma 567 EXTLIBS += -lnuma
568 $(call detected,CONFIG_NUMA)
638 endif 569 endif
639endif 570endif
640 571
@@ -651,7 +582,7 @@ ifeq (${IS_64_BIT}, 1)
651 NO_PERF_READ_VDSO32 := 1 582 NO_PERF_READ_VDSO32 := 1
652 endif 583 endif
653 endif 584 endif
654 ifneq (${IS_X86_64}, 1) 585 ifneq ($(ARCH), x86)
655 NO_PERF_READ_VDSOX32 := 1 586 NO_PERF_READ_VDSOX32 := 1
656 endif 587 endif
657 ifndef NO_PERF_READ_VDSOX32 588 ifndef NO_PERF_READ_VDSOX32
@@ -667,6 +598,18 @@ else
667 NO_PERF_READ_VDSOX32 := 1 598 NO_PERF_READ_VDSOX32 := 1
668endif 599endif
669 600
601ifdef LIBBABELTRACE
602 $(call feature_check,libbabeltrace)
603 ifeq ($(feature-libbabeltrace), 1)
604 CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
605 LDFLAGS += $(LIBBABELTRACE_LDFLAGS)
606 EXTLIBS += -lbabeltrace-ctf
607 $(call detected,CONFIG_LIBBABELTRACE)
608 else
609 msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
610 endif
611endif
612
670# Among the variables below, these: 613# Among the variables below, these:
671# perfexecdir 614# perfexecdir
672# template_dir 615# template_dir
@@ -699,7 +642,7 @@ sysconfdir = $(prefix)/etc
699ETC_PERFCONFIG = etc/perfconfig 642ETC_PERFCONFIG = etc/perfconfig
700endif 643endif
701ifndef lib 644ifndef lib
702ifeq ($(IS_X86_64),1) 645ifeq ($(ARCH)$(IS_64_BIT), x861)
703lib = lib64 646lib = lib64
704else 647else
705lib = lib 648lib = lib
@@ -735,83 +678,33 @@ plugindir=$(libdir)/traceevent/plugins
735plugindir_SQ= $(subst ','\'',$(plugindir)) 678plugindir_SQ= $(subst ','\'',$(plugindir))
736endif 679endif
737 680
738# 681print_var = $(eval $(print_var_code)) $(info $(MSG))
739# Print the result of the feature test: 682define print_var_code
740#
741feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
742
743define feature_print_status_code
744 ifeq ($(feature-$(1)), 1)
745 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
746 else
747 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
748 endif
749endef
750
751feature_print_var = $(eval $(feature_print_var_code)) $(info $(MSG))
752define feature_print_var_code
753 MSG = $(shell printf '...%30s: %s' $(1) $($(1))) 683 MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
754endef 684endef
755 685
756feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
757define feature_print_text_code
758 MSG = $(shell printf '...%30s: %s' $(1) $(2))
759endef
760
761PERF_FEATURES := $(foreach feat,$(LIB_FEATURE_TESTS),feature-$(feat)($(feature-$(feat))))
762PERF_FEATURES_FILE := $(shell touch $(OUTPUT)PERF-FEATURES; cat $(OUTPUT)PERF-FEATURES)
763
764ifeq ($(dwarf-post-unwind),1)
765 PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text))
766endif
767
768# The $(display_lib) controls the default detection message
769# output. It's set if:
770# - detected features differes from stored features from
771# last build (in PERF-FEATURES file)
772# - one of the $(LIB_FEATURE_TESTS) is not detected
773# - VF is enabled
774
775ifneq ("$(PERF_FEATURES)","$(PERF_FEATURES_FILE)")
776 $(shell echo "$(PERF_FEATURES)" > $(OUTPUT)PERF-FEATURES)
777 display_lib := 1
778endif
779
780feature_check = $(eval $(feature_check_code))
781define feature_check_code
782 ifneq ($(feature-$(1)), 1)
783 display_lib := 1
784 endif
785endef
786
787$(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat)))
788
789ifeq ($(VF),1) 686ifeq ($(VF),1)
790 display_lib := 1 687 $(call print_var,prefix)
791 display_vf := 1 688 $(call print_var,bindir)
792endif 689 $(call print_var,libdir)
793 690 $(call print_var,sysconfdir)
794ifeq ($(display_lib),1) 691 $(call print_var,LIBUNWIND_DIR)
692 $(call print_var,LIBDW_DIR)
795 $(info ) 693 $(info )
796 $(info Auto-detecting system features:)
797 $(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_print_status,$(feat),))
798
799 ifeq ($(dwarf-post-unwind),1)
800 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
801 endif
802endif
803
804ifeq ($(display_vf),1)
805 $(foreach feat,$(VF_FEATURE_TESTS),$(call feature_print_status,$(feat),))
806 $(info )
807 $(call feature_print_var,prefix)
808 $(call feature_print_var,bindir)
809 $(call feature_print_var,libdir)
810 $(call feature_print_var,sysconfdir)
811 $(call feature_print_var,LIBUNWIND_DIR)
812 $(call feature_print_var,LIBDW_DIR)
813endif 694endif
814 695
815ifeq ($(display_lib),1) 696$(call detected_var,bindir_SQ)
816 $(info ) 697$(call detected_var,PYTHON_WORD)
817endif 698ifneq ($(OUTPUT),)
699$(call detected_var,OUTPUT)
700endif
701$(call detected_var,htmldir_SQ)
702$(call detected_var,infodir_SQ)
703$(call detected_var,mandir_SQ)
704$(call detected_var,ETC_PERFCONFIG_SQ)
705$(call detected_var,prefix_SQ)
706$(call detected_var,perfexecdir_SQ)
707$(call detected_var,LIBDIR)
708$(call detected_var,GTK_CFLAGS)
709$(call detected_var,PERL_EMBED_CCOPTS)
710$(call detected_var,PYTHON_EMBED_CCOPTS)
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
index ff95a68741d1..e11fbd6fae78 100644
--- a/tools/perf/config/Makefile.arch
+++ b/tools/perf/config/Makefile.arch
@@ -1,28 +1,15 @@
1ifndef ARCH
2ARCH := $(shell uname -m 2>/dev/null || echo not)
3endif
1 4
2uname_M := $(shell uname -m 2>/dev/null || echo not) 5ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
3 6 -e s/sun4u/sparc/ -e s/sparc64/sparc/ \
4RAW_ARCH := $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ 7 -e /arm64/!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/ \ 8 -e s/s390x/s390/ -e s/parisc64/parisc/ \
7 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ 9 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
8 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \ 10 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
9 -e s/tile.*/tile/ ) 11 -e s/tile.*/tile/ )
10 12
11# Additional ARCH settings for x86
12ifeq ($(RAW_ARCH),i386)
13 ARCH ?= x86
14endif
15
16ifeq ($(RAW_ARCH),x86_64)
17 ARCH ?= x86
18
19 ifneq (, $(findstring m32,$(CFLAGS)))
20 RAW_ARCH := x86_32
21 endif
22endif
23
24ARCH ?= $(RAW_ARCH)
25
26LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) 13LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
27ifeq ($(LP64), 1) 14ifeq ($(LP64), 1)
28 IS_64_BIT := 1 15 IS_64_BIT := 1
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 7076a62d0ff7..c16ce833079c 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -175,6 +175,5 @@ _ge-abspath = $(if $(is-executable),$(1))
175define get-executable-or-default 175define get-executable-or-default
176$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) 176$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
177endef 177endef
178_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) 178_ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2)))
179_gea_warn = $(warning The path '$(1)' is not executable.)
180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 179_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
diff --git a/tools/perf/perf-completion.sh b/tools/perf/perf-completion.sh
index 33569847fdcc..3ba80b2359cc 100644
--- a/tools/perf/perf-completion.sh
+++ b/tools/perf/perf-completion.sh
@@ -47,8 +47,16 @@ __my_reassemble_comp_words_by_ref()
47 done 47 done
48} 48}
49 49
50type _get_comp_words_by_ref &>/dev/null || 50# Define preload_get_comp_words_by_ref="false", if the function
51_get_comp_words_by_ref() 51# __perf_get_comp_words_by_ref() is required instead.
52preload_get_comp_words_by_ref="true"
53
54if [ $preload_get_comp_words_by_ref = "true" ]; then
55 type _get_comp_words_by_ref &>/dev/null ||
56 preload_get_comp_words_by_ref="false"
57fi
58[ $preload_get_comp_words_by_ref = "true" ] ||
59__perf_get_comp_words_by_ref()
52{ 60{
53 local exclude cur_ words_ cword_ 61 local exclude cur_ words_ cword_
54 if [ "$1" = "-n" ]; then 62 if [ "$1" = "-n" ]; then
@@ -76,8 +84,16 @@ _get_comp_words_by_ref()
76 done 84 done
77} 85}
78 86
79type __ltrim_colon_completions &>/dev/null || 87# Define preload__ltrim_colon_completions="false", if the function
80__ltrim_colon_completions() 88# __perf__ltrim_colon_completions() is required instead.
89preload__ltrim_colon_completions="true"
90
91if [ $preload__ltrim_colon_completions = "true" ]; then
92 type __ltrim_colon_completions &>/dev/null ||
93 preload__ltrim_colon_completions="false"
94fi
95[ $preload__ltrim_colon_completions = "true" ] ||
96__perf__ltrim_colon_completions()
81{ 97{
82 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then 98 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
83 # Remove colon-word prefix from COMPREPLY items 99 # Remove colon-word prefix from COMPREPLY items
@@ -97,7 +113,32 @@ __perfcomp ()
97__perfcomp_colon () 113__perfcomp_colon ()
98{ 114{
99 __perfcomp "$1" "$2" 115 __perfcomp "$1" "$2"
100 __ltrim_colon_completions $cur 116 if [ $preload__ltrim_colon_completions = "true" ]; then
117 __ltrim_colon_completions $cur
118 else
119 __perf__ltrim_colon_completions $cur
120 fi
121}
122
123__perf_prev_skip_opts ()
124{
125 local i cmd_ cmds_
126
127 let i=cword-1
128 cmds_=$($cmd $1 --list-cmds)
129 prev_skip_opts=()
130 while [ $i -ge 0 ]; do
131 if [[ ${words[i]} == $1 ]]; then
132 return
133 fi
134 for cmd_ in $cmds_; do
135 if [[ ${words[i]} == $cmd_ ]]; then
136 prev_skip_opts=${words[i]}
137 return
138 fi
139 done
140 ((i--))
141 done
101} 142}
102 143
103__perf_main () 144__perf_main ()
@@ -107,29 +148,36 @@ __perf_main ()
107 cmd=${words[0]} 148 cmd=${words[0]}
108 COMPREPLY=() 149 COMPREPLY=()
109 150
151 # Skip options backward and find the last perf command
152 __perf_prev_skip_opts
110 # List perf subcommands or long options 153 # List perf subcommands or long options
111 if [ $cword -eq 1 ]; then 154 if [ -z $prev_skip_opts ]; then
112 if [[ $cur == --* ]]; then 155 if [[ $cur == --* ]]; then
113 __perfcomp '--help --version \ 156 cmds=$($cmd --list-opts)
114 --exec-path --html-path --paginate --no-pager \
115 --perf-dir --work-tree --debugfs-dir' -- "$cur"
116 else 157 else
117 cmds=$($cmd --list-cmds) 158 cmds=$($cmd --list-cmds)
118 __perfcomp "$cmds" "$cur"
119 fi 159 fi
160 __perfcomp "$cmds" "$cur"
120 # List possible events for -e option 161 # List possible events for -e option
121 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then 162 elif [[ $prev == @("-e"|"--event") &&
163 $prev_skip_opts == @(record|stat|top) ]]; then
122 evts=$($cmd list --raw-dump) 164 evts=$($cmd list --raw-dump)
123 __perfcomp_colon "$evts" "$cur" 165 __perfcomp_colon "$evts" "$cur"
124 # List subcommands for perf commands 166 else
125 elif [[ $prev == @(kvm|kmem|mem|lock|sched) ]]; then 167 # List subcommands for perf commands
126 subcmds=$($cmd $prev --list-cmds) 168 if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched|
127 __perfcomp_colon "$subcmds" "$cur" 169 |data|help|script|test|timechart|trace) ]]; then
128 # List long option names 170 subcmds=$($cmd $prev_skip_opts --list-cmds)
129 elif [[ $cur == --* ]]; then 171 __perfcomp_colon "$subcmds" "$cur"
130 subcmd=${words[1]} 172 fi
131 opts=$($cmd $subcmd --list-opts) 173 # List long option names
132 __perfcomp "$opts" "$cur" 174 if [[ $cur == --* ]]; then
175 subcmd=$prev_skip_opts
176 __perf_prev_skip_opts $subcmd
177 subcmd=$subcmd" "$prev_skip_opts
178 opts=$($cmd $subcmd --list-opts)
179 __perfcomp "$opts" "$cur"
180 fi
133 fi 181 fi
134} 182}
135 183
@@ -198,7 +246,11 @@ type perf &>/dev/null &&
198_perf() 246_perf()
199{ 247{
200 local cur words cword prev 248 local cur words cword prev
201 _get_comp_words_by_ref -n =: cur words cword prev 249 if [ $preload_get_comp_words_by_ref = "true" ]; then
250 _get_comp_words_by_ref -n =: cur words cword prev
251 else
252 __perf_get_comp_words_by_ref -n =: cur words cword prev
253 fi
202 __perf_main 254 __perf_main
203} && 255} &&
204 256
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 3700a7faca6c..b857fcbd00cf 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -13,6 +13,7 @@
13#include "util/quote.h" 13#include "util/quote.h"
14#include "util/run-command.h" 14#include "util/run-command.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16#include "util/parse-options.h"
16#include "util/debug.h" 17#include "util/debug.h"
17#include <api/fs/debugfs.h> 18#include <api/fs/debugfs.h>
18#include <pthread.h> 19#include <pthread.h>
@@ -62,6 +63,7 @@ static struct cmd_struct commands[] = {
62#endif 63#endif
63 { "inject", cmd_inject, 0 }, 64 { "inject", cmd_inject, 0 },
64 { "mem", cmd_mem, 0 }, 65 { "mem", cmd_mem, 0 },
66 { "data", cmd_data, 0 },
65}; 67};
66 68
67struct pager_config { 69struct pager_config {
@@ -124,6 +126,23 @@ static void commit_pager_choice(void)
124 } 126 }
125} 127}
126 128
129struct option options[] = {
130 OPT_ARGUMENT("help", "help"),
131 OPT_ARGUMENT("version", "version"),
132 OPT_ARGUMENT("exec-path", "exec-path"),
133 OPT_ARGUMENT("html-path", "html-path"),
134 OPT_ARGUMENT("paginate", "paginate"),
135 OPT_ARGUMENT("no-pager", "no-pager"),
136 OPT_ARGUMENT("perf-dir", "perf-dir"),
137 OPT_ARGUMENT("work-tree", "work-tree"),
138 OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
139 OPT_ARGUMENT("buildid-dir", "buildid-dir"),
140 OPT_ARGUMENT("list-cmds", "list-cmds"),
141 OPT_ARGUMENT("list-opts", "list-opts"),
142 OPT_ARGUMENT("debug", "debug"),
143 OPT_END()
144};
145
127static int handle_options(const char ***argv, int *argc, int *envchanged) 146static int handle_options(const char ***argv, int *argc, int *envchanged)
128{ 147{
129 int handled = 0; 148 int handled = 0;
@@ -222,6 +241,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
222 struct cmd_struct *p = commands+i; 241 struct cmd_struct *p = commands+i;
223 printf("%s ", p->cmd); 242 printf("%s ", p->cmd);
224 } 243 }
244 putchar('\n');
245 exit(0);
246 } else if (!strcmp(cmd, "--list-opts")) {
247 unsigned int i;
248
249 for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
250 struct option *p = options+i;
251 printf("--%s ", p->long_name);
252 }
253 putchar('\n');
225 exit(0); 254 exit(0);
226 } else if (!strcmp(cmd, "--debug")) { 255 } else if (!strcmp(cmd, "--debug")) {
227 if (*argc < 2) { 256 if (*argc < 2) {
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 1dabb8553499..e14bb637255c 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -29,7 +29,7 @@ static inline unsigned long long rdclock(void)
29 return ts.tv_sec * 1000000000ULL + ts.tv_nsec; 29 return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
30} 30}
31 31
32#define MAX_NR_CPUS 256 32#define MAX_NR_CPUS 1024
33 33
34extern const char *input_name; 34extern const char *input_name;
35extern bool perf_host, perf_guest; 35extern bool perf_host, perf_guest;
@@ -53,6 +53,7 @@ struct record_opts {
53 bool sample_time; 53 bool sample_time;
54 bool period; 54 bool period;
55 bool sample_intr_regs; 55 bool sample_intr_regs;
56 bool running_time;
56 unsigned int freq; 57 unsigned int freq;
57 unsigned int mmap_pages; 58 unsigned int mmap_pages;
58 unsigned int user_freq; 59 unsigned int user_freq;
@@ -61,6 +62,8 @@ struct record_opts {
61 u64 user_interval; 62 u64 user_interval;
62 bool sample_transaction; 63 bool sample_transaction;
63 unsigned initial_delay; 64 unsigned initial_delay;
65 bool use_clockid;
66 clockid_t clockid;
64}; 67};
65 68
66struct option; 69struct option;
diff --git a/tools/perf/scripts/Build b/tools/perf/scripts/Build
new file mode 100644
index 000000000000..41efd7e368b3
--- /dev/null
+++ b/tools/perf/scripts/Build
@@ -0,0 +1,2 @@
1libperf-$(CONFIG_LIBPERL) += perl/Perf-Trace-Util/
2libperf-$(CONFIG_LIBPYTHON) += python/Perf-Trace-Util/
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build
new file mode 100644
index 000000000000..928e110179cb
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Build
@@ -0,0 +1,3 @@
1libperf-y += Context.o
2
3CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Build b/tools/perf/scripts/python/Perf-Trace-Util/Build
new file mode 100644
index 000000000000..aefc15c9444a
--- /dev/null
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Build
@@ -0,0 +1,3 @@
1libperf-y += Context.o
2
3CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
new file mode 100644
index 000000000000..6a8801b32017
--- /dev/null
+++ b/tools/perf/tests/Build
@@ -0,0 +1,43 @@
1perf-y += builtin-test.o
2perf-y += parse-events.o
3perf-y += dso-data.o
4perf-y += attr.o
5perf-y += vmlinux-kallsyms.o
6perf-y += open-syscall.o
7perf-y += open-syscall-all-cpus.o
8perf-y += open-syscall-tp-fields.o
9perf-y += mmap-basic.o
10perf-y += perf-record.o
11perf-y += rdpmc.o
12perf-y += evsel-roundtrip-name.o
13perf-y += evsel-tp-sched.o
14perf-y += fdarray.o
15perf-y += pmu.o
16perf-y += hists_common.o
17perf-y += hists_link.o
18perf-y += hists_filter.o
19perf-y += hists_output.o
20perf-y += hists_cumulate.o
21perf-y += python-use.o
22perf-y += bp_signal.o
23perf-y += bp_signal_overflow.o
24perf-y += task-exit.o
25perf-y += sw-clock.o
26perf-y += mmap-thread-lookup.o
27perf-y += thread-mg-share.o
28perf-y += switch-tracking.o
29perf-y += keep-tracking.o
30perf-y += code-reading.o
31perf-y += sample-parsing.o
32perf-y += parse-no-sample-id-all.o
33perf-y += kmod-path.o
34
35perf-$(CONFIG_X86) += perf-time-to-tsc.o
36
37ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
38perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
39endif
40
41CFLAGS_attr.o += -DBINDIR="BUILD_STR($(bindir_SQ))" -DPYTHON="BUILD_STR($(PYTHON_WORD))"
42CFLAGS_python-use.o += -DPYTHONPATH="BUILD_STR($(OUTPUT)python)" -DPYTHON="BUILD_STR($(PYTHON_WORD))"
43CFLAGS_dwarf-unwind.o += -fno-optimize-sibling-calls
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index d3095dafed36..7e6d74946e04 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -5,7 +5,7 @@ group_fd=-1
5flags=0|8 5flags=0|8
6cpu=* 6cpu=*
7type=0|1 7type=0|1
8size=104 8size=112
9config=0 9config=0
10sample_period=4000 10sample_period=4000
11sample_type=263 11sample_type=263
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat
index 872ed7e24c7c..f4cf148f14cb 100644
--- a/tools/perf/tests/attr/base-stat
+++ b/tools/perf/tests/attr/base-stat
@@ -5,7 +5,7 @@ group_fd=-1
5flags=0|8 5flags=0|8
6cpu=* 6cpu=*
7type=0 7type=0
8size=104 8size=112
9config=0 9config=0
10sample_period=0 10sample_period=0
11sample_type=0 11sample_type=0
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 4b7d9ab0f049..4f4098167112 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -167,6 +167,10 @@ static struct test {
167 .func = test__fdarray__add, 167 .func = test__fdarray__add,
168 }, 168 },
169 { 169 {
170 .desc = "Test kmod_path__parse function",
171 .func = test__kmod_path__parse,
172 },
173 {
170 .func = NULL, 174 .func = NULL,
171 }, 175 },
172}; 176};
@@ -291,7 +295,7 @@ static int perf_test__list(int argc, const char **argv)
291 295
292int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) 296int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
293{ 297{
294 const char * const test_usage[] = { 298 const char *test_usage[] = {
295 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", 299 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
296 NULL, 300 NULL,
297 }; 301 };
@@ -302,13 +306,14 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
302 "be more verbose (show symbol address, etc)"), 306 "be more verbose (show symbol address, etc)"),
303 OPT_END() 307 OPT_END()
304 }; 308 };
309 const char * const test_subcommands[] = { "list", NULL };
305 struct intlist *skiplist = NULL; 310 struct intlist *skiplist = NULL;
306 int ret = hists__init(); 311 int ret = hists__init();
307 312
308 if (ret < 0) 313 if (ret < 0)
309 return ret; 314 return ret;
310 315
311 argc = parse_options(argc, argv, test_options, test_usage, 0); 316 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
312 if (argc >= 1 && !strcmp(argv[0], "list")) 317 if (argc >= 1 && !strcmp(argv[0], "list"))
313 return perf_test__list(argc, argv); 318 return perf_test__list(argc, argv);
314 319
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index caaf37f079b1..513e5febbe5a 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -112,6 +112,9 @@ int test__dso_data(void)
112 112
113 dso = dso__new((const char *)file); 113 dso = dso__new((const char *)file);
114 114
115 TEST_ASSERT_VAL("Failed to access to dso",
116 dso__data_fd(dso, &machine) >= 0);
117
115 /* Basic 10 bytes tests. */ 118 /* Basic 10 bytes tests. */
116 for (i = 0; i < ARRAY_SIZE(offsets); i++) { 119 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
117 struct test_data_offset *data = &offsets[i]; 120 struct test_data_offset *data = &offsets[i];
@@ -243,8 +246,8 @@ int test__dso_data_cache(void)
243 limit = nr * 4; 246 limit = nr * 4;
244 TEST_ASSERT_VAL("failed to set file limit", !set_fd_limit(limit)); 247 TEST_ASSERT_VAL("failed to set file limit", !set_fd_limit(limit));
245 248
246 /* and this is now our dso open FDs limit + 1 extra */ 249 /* and this is now our dso open FDs limit */
247 dso_cnt = limit / 2 + 1; 250 dso_cnt = limit / 2;
248 TEST_ASSERT_VAL("failed to create dsos\n", 251 TEST_ASSERT_VAL("failed to create dsos\n",
249 !dsos__create(dso_cnt, TEST_FILE_SIZE)); 252 !dsos__create(dso_cnt, TEST_FILE_SIZE));
250 253
@@ -252,13 +255,13 @@ int test__dso_data_cache(void)
252 struct dso *dso = dsos[i]; 255 struct dso *dso = dsos[i];
253 256
254 /* 257 /*
255 * Open dsos via dso__data_fd or dso__data_read_offset. 258 * Open dsos via dso__data_fd(), it opens the data
256 * Both opens the data file and keep it open. 259 * file and keep it open (unless open file limit).
257 */ 260 */
261 fd = dso__data_fd(dso, &machine);
262 TEST_ASSERT_VAL("failed to get fd", fd > 0);
263
258 if (i % 2) { 264 if (i % 2) {
259 fd = dso__data_fd(dso, &machine);
260 TEST_ASSERT_VAL("failed to get fd", fd > 0);
261 } else {
262 #define BUFSIZE 10 265 #define BUFSIZE 10
263 u8 buf[BUFSIZE]; 266 u8 buf[BUFSIZE];
264 ssize_t n; 267 ssize_t n;
@@ -268,7 +271,10 @@ int test__dso_data_cache(void)
268 } 271 }
269 } 272 }
270 273
271 /* open +1 dso over the allowed limit */ 274 /* verify the first one is already open */
275 TEST_ASSERT_VAL("dsos[0] is not open", dsos[0]->data.fd != -1);
276
277 /* open +1 dso to reach the allowed limit */
272 fd = dso__data_fd(dsos[i], &machine); 278 fd = dso__data_fd(dsos[i], &machine);
273 TEST_ASSERT_VAL("failed to get fd", fd > 0); 279 TEST_ASSERT_VAL("failed to get fd", fd > 0);
274 280
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
new file mode 100644
index 000000000000..e8d7cbb9320c
--- /dev/null
+++ b/tools/perf/tests/kmod-path.c
@@ -0,0 +1,73 @@
1#include <stdbool.h>
2#include "tests.h"
3#include "dso.h"
4#include "debug.h"
5
6static int test(const char *path, bool alloc_name, bool alloc_ext,
7 bool kmod, bool comp, const char *name, const char *ext)
8{
9 struct kmod_path m;
10
11 memset(&m, 0x0, sizeof(m));
12
13 TEST_ASSERT_VAL("kmod_path__parse",
14 !__kmod_path__parse(&m, path, alloc_name, alloc_ext));
15
16 pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n",
17 path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext);
18
19 TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
20 TEST_ASSERT_VAL("wrong comp", m.comp == comp);
21
22 if (ext)
23 TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext));
24 else
25 TEST_ASSERT_VAL("wrong ext", !m.ext);
26
27 if (name)
28 TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
29 else
30 TEST_ASSERT_VAL("wrong name", !m.name);
31
32 free(m.name);
33 free(m.ext);
34 return 0;
35}
36
37#define T(path, an, ae, k, c, n, e) \
38 TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e))
39
40int test__kmod_path__parse(void)
41{
42 /* path alloc_name alloc_ext kmod comp name ext */
43 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL);
44 T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL);
45 T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL);
46 T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL);
47
48 /* path alloc_name alloc_ext kmod comp name ext */
49 T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz");
50 T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz");
51 T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL);
52 T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL);
53
54 /* path alloc_name alloc_ext kmod comp name ext */
55 T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz");
56 T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz");
57 T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL);
58 T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL);
59
60 /* path alloc_name alloc_ext kmod comp name ext */
61 T("x.gz", true , true , false, true, "x.gz", "gz");
62 T("x.gz", false , true , false, true, NULL , "gz");
63 T("x.gz", true , false , false, true, "x.gz", NULL);
64 T("x.gz", false , false , false, true, NULL , NULL);
65
66 /* path alloc_name alloc_ext kmod comp name ext */
67 T("x.ko.gz", true , true , true, true, "[x]", "gz");
68 T("x.ko.gz", false , true , true, true, NULL , "gz");
69 T("x.ko.gz", true , false , true, true, "[x]", NULL);
70 T("x.ko.gz", false , false , true, true, NULL , NULL);
71
72 return 0;
73}
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 75709d2b17b4..bff85324f799 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -5,7 +5,7 @@ include config/Makefile.arch
5 5
6# FIXME looks like x86 is the only arch running tests ;-) 6# FIXME looks like x86 is the only arch running tests ;-)
7# we need some IS_(32/64) flag to make this generic 7# we need some IS_(32/64) flag to make this generic
8ifeq ($(IS_X86_64),1) 8ifeq ($(ARCH)$(IS_64_BIT), x861)
9lib = lib64 9lib = lib64
10else 10else
11lib = lib 11lib = lib
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
index 8fa82d1700c7..3ec885c48f8f 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -29,7 +29,12 @@ int test__open_syscall_event_on_all_cpus(void)
29 29
30 evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); 30 evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
31 if (evsel == NULL) { 31 if (evsel == NULL) {
32 pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); 32 if (tracefs_configured())
33 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
34 else if (debugfs_configured())
35 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
36 else
37 pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
33 goto out_thread_map_delete; 38 goto out_thread_map_delete;
34 } 39 }
35 40
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
index a33b2daae40f..07aa319bf334 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/open-syscall.c
@@ -18,7 +18,12 @@ int test__open_syscall_event(void)
18 18
19 evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); 19 evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
20 if (evsel == NULL) { 20 if (evsel == NULL) {
21 pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); 21 if (tracefs_configured())
22 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
23 else if (debugfs_configured())
24 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
25 else
26 pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
22 goto out_thread_map_delete; 27 goto out_thread_map_delete;
23 } 28 }
24 29
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 1cdab0ce00e2..3de744961739 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -3,6 +3,7 @@
3#include "evsel.h" 3#include "evsel.h"
4#include "evlist.h" 4#include "evlist.h"
5#include <api/fs/fs.h> 5#include <api/fs/fs.h>
6#include <api/fs/tracefs.h>
6#include <api/fs/debugfs.h> 7#include <api/fs/debugfs.h>
7#include "tests.h" 8#include "tests.h"
8#include "debug.h" 9#include "debug.h"
@@ -294,6 +295,36 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
294 return test__checkevent_genhw(evlist); 295 return test__checkevent_genhw(evlist);
295} 296}
296 297
298static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist)
299{
300 struct perf_evsel *evsel = perf_evlist__first(evlist);
301
302 TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle);
303 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
304 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
305 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
306 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
307 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
308 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
309
310 return test__checkevent_symbolic_name(evlist);
311}
312
313static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist)
314{
315 struct perf_evsel *evsel = perf_evlist__first(evlist);
316
317 TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle);
318 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
319 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
320 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
321 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
322 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
323 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
324
325 return test__checkevent_symbolic_name(evlist);
326}
327
297static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) 328static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
298{ 329{
299 struct perf_evsel *evsel = perf_evlist__first(evlist); 330 struct perf_evsel *evsel = perf_evlist__first(evlist);
@@ -1192,11 +1223,19 @@ static int count_tracepoints(void)
1192{ 1223{
1193 char events_path[PATH_MAX]; 1224 char events_path[PATH_MAX];
1194 struct dirent *events_ent; 1225 struct dirent *events_ent;
1226 const char *mountpoint;
1195 DIR *events_dir; 1227 DIR *events_dir;
1196 int cnt = 0; 1228 int cnt = 0;
1197 1229
1198 scnprintf(events_path, PATH_MAX, "%s/tracing/events", 1230 mountpoint = tracefs_find_mountpoint();
1199 debugfs_find_mountpoint()); 1231 if (mountpoint) {
1232 scnprintf(events_path, PATH_MAX, "%s/events",
1233 mountpoint);
1234 } else {
1235 mountpoint = debugfs_find_mountpoint();
1236 scnprintf(events_path, PATH_MAX, "%s/tracing/events",
1237 mountpoint);
1238 }
1200 1239
1201 events_dir = opendir(events_path); 1240 events_dir = opendir(events_path);
1202 1241
@@ -1485,6 +1524,16 @@ static struct evlist_test test__events[] = {
1485 .id = 100, 1524 .id = 100,
1486 }, 1525 },
1487#endif 1526#endif
1527 {
1528 .name = "instructions:I",
1529 .check = test__checkevent_exclude_idle_modifier,
1530 .id = 45,
1531 },
1532 {
1533 .name = "instructions:kIG",
1534 .check = test__checkevent_exclude_idle_modifier_1,
1535 .id = 46,
1536 },
1488}; 1537};
1489 1538
1490static struct evlist_test test__events_pmu[] = { 1539static struct evlist_test test__events_pmu[] = {
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 00e776a87a9c..52758a33f64c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -51,6 +51,7 @@ int test__hists_cumulate(void);
51int test__switch_tracking(void); 51int test__switch_tracking(void);
52int test__fdarray__filter(void); 52int test__fdarray__filter(void);
53int test__fdarray__add(void); 53int test__fdarray__add(void);
54int test__kmod_path__parse(void);
54 55
55#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 56#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
56#ifdef HAVE_DWARF_UNWIND_SUPPORT 57#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/Build b/tools/perf/ui/Build
new file mode 100644
index 000000000000..0a73538c0441
--- /dev/null
+++ b/tools/perf/ui/Build
@@ -0,0 +1,14 @@
1libperf-y += setup.o
2libperf-y += helpline.o
3libperf-y += progress.o
4libperf-y += util.o
5libperf-y += hist.o
6libperf-y += stdio/hist.o
7
8CFLAGS_setup.o += -DLIBDIR="BUILD_STR($(LIBDIR))"
9
10libperf-$(CONFIG_SLANG) += browser.o
11libperf-$(CONFIG_SLANG) += browsers/
12libperf-$(CONFIG_SLANG) += tui/
13
14CFLAGS_browser.o += -DENABLE_SLFUTURE_CONST
diff --git a/tools/perf/ui/browsers/Build b/tools/perf/ui/browsers/Build
new file mode 100644
index 000000000000..de223f5bed58
--- /dev/null
+++ b/tools/perf/ui/browsers/Build
@@ -0,0 +1,10 @@
1libperf-y += annotate.o
2libperf-y += hists.o
3libperf-y += map.o
4libperf-y += scripts.o
5libperf-y += header.o
6
7CFLAGS_annotate.o += -DENABLE_SLFUTURE_CONST
8CFLAGS_hists.o += -DENABLE_SLFUTURE_CONST
9CFLAGS_map.o += -DENABLE_SLFUTURE_CONST
10CFLAGS_scripts.o += -DENABLE_SLFUTURE_CONST
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 9d32e3c0cfee..e5250eb2dd57 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -829,10 +829,16 @@ out:
829 return key; 829 return key;
830} 830}
831 831
832int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
833 struct hist_browser_timer *hbt)
834{
835 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
836}
837
832int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 838int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
833 struct hist_browser_timer *hbt) 839 struct hist_browser_timer *hbt)
834{ 840{
835 return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt); 841 return map_symbol__tui_annotate(&he->ms, evsel, hbt);
836} 842}
837 843
838static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 844static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 788506eef567..995b7a8596b1 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -48,6 +48,24 @@ static bool hist_browser__has_filter(struct hist_browser *hb)
48 return hists__has_filter(hb->hists) || hb->min_pcnt; 48 return hists__has_filter(hb->hists) || hb->min_pcnt;
49} 49}
50 50
51static int hist_browser__get_folding(struct hist_browser *browser)
52{
53 struct rb_node *nd;
54 struct hists *hists = browser->hists;
55 int unfolded_rows = 0;
56
57 for (nd = rb_first(&hists->entries);
58 (nd = hists__filter_entries(nd, browser->min_pcnt)) != NULL;
59 nd = rb_next(nd)) {
60 struct hist_entry *he =
61 rb_entry(nd, struct hist_entry, rb_node);
62
63 if (he->ms.unfolded)
64 unfolded_rows += he->nr_rows;
65 }
66 return unfolded_rows;
67}
68
51static u32 hist_browser__nr_entries(struct hist_browser *hb) 69static u32 hist_browser__nr_entries(struct hist_browser *hb)
52{ 70{
53 u32 nr_entries; 71 u32 nr_entries;
@@ -57,6 +75,7 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb)
57 else 75 else
58 nr_entries = hb->hists->nr_entries; 76 nr_entries = hb->hists->nr_entries;
59 77
78 hb->nr_callchain_rows = hist_browser__get_folding(hb);
60 return nr_entries + hb->nr_callchain_rows; 79 return nr_entries + hb->nr_callchain_rows;
61} 80}
62 81
@@ -492,6 +511,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
492{ 511{
493 int color, width; 512 int color, width;
494 char folded_sign = callchain_list__folded(chain); 513 char folded_sign = callchain_list__folded(chain);
514 bool show_annotated = browser->show_dso && chain->ms.sym && symbol__annotation(chain->ms.sym)->src;
495 515
496 color = HE_COLORSET_NORMAL; 516 color = HE_COLORSET_NORMAL;
497 width = browser->b.width - (offset + 2); 517 width = browser->b.width - (offset + 2);
@@ -504,7 +524,8 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
504 ui_browser__set_color(&browser->b, color); 524 ui_browser__set_color(&browser->b, color);
505 hist_browser__gotorc(browser, row, 0); 525 hist_browser__gotorc(browser, row, 0);
506 slsmg_write_nstring(" ", offset); 526 slsmg_write_nstring(" ", offset);
507 slsmg_printf("%c ", folded_sign); 527 slsmg_printf("%c", folded_sign);
528 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' ');
508 slsmg_write_nstring(str, width); 529 slsmg_write_nstring(str, width);
509} 530}
510 531
@@ -1467,7 +1488,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1467 perf_hpp__set_user_width(symbol_conf.col_width_list_str); 1488 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
1468 1489
1469 while (1) { 1490 while (1) {
1470 const struct thread *thread = NULL; 1491 struct thread *thread = NULL;
1471 const struct dso *dso = NULL; 1492 const struct dso *dso = NULL;
1472 int choice = 0, 1493 int choice = 0,
1473 annotate = -2, zoom_dso = -2, zoom_thread = -2, 1494 annotate = -2, zoom_dso = -2, zoom_thread = -2,
@@ -1593,28 +1614,30 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1593 if (!sort__has_sym) 1614 if (!sort__has_sym)
1594 goto add_exit_option; 1615 goto add_exit_option;
1595 1616
1617 if (browser->selection == NULL)
1618 goto skip_annotation;
1619
1596 if (sort__mode == SORT_MODE__BRANCH) { 1620 if (sort__mode == SORT_MODE__BRANCH) {
1597 bi = browser->he_selection->branch_info; 1621 bi = browser->he_selection->branch_info;
1598 if (browser->selection != NULL && 1622
1599 bi && 1623 if (bi == NULL)
1600 bi->from.sym != NULL && 1624 goto skip_annotation;
1625
1626 if (bi->from.sym != NULL &&
1601 !bi->from.map->dso->annotate_warned && 1627 !bi->from.map->dso->annotate_warned &&
1602 asprintf(&options[nr_options], "Annotate %s", 1628 asprintf(&options[nr_options], "Annotate %s", bi->from.sym->name) > 0) {
1603 bi->from.sym->name) > 0)
1604 annotate_f = nr_options++; 1629 annotate_f = nr_options++;
1630 }
1605 1631
1606 if (browser->selection != NULL && 1632 if (bi->to.sym != NULL &&
1607 bi &&
1608 bi->to.sym != NULL &&
1609 !bi->to.map->dso->annotate_warned && 1633 !bi->to.map->dso->annotate_warned &&
1610 (bi->to.sym != bi->from.sym || 1634 (bi->to.sym != bi->from.sym ||
1611 bi->to.map->dso != bi->from.map->dso) && 1635 bi->to.map->dso != bi->from.map->dso) &&
1612 asprintf(&options[nr_options], "Annotate %s", 1636 asprintf(&options[nr_options], "Annotate %s", bi->to.sym->name) > 0) {
1613 bi->to.sym->name) > 0)
1614 annotate_t = nr_options++; 1637 annotate_t = nr_options++;
1638 }
1615 } else { 1639 } else {
1616 if (browser->selection != NULL && 1640 if (browser->selection->sym != NULL &&
1617 browser->selection->sym != NULL &&
1618 !browser->selection->map->dso->annotate_warned) { 1641 !browser->selection->map->dso->annotate_warned) {
1619 struct annotation *notes; 1642 struct annotation *notes;
1620 1643
@@ -1622,11 +1645,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1622 1645
1623 if (notes->src && 1646 if (notes->src &&
1624 asprintf(&options[nr_options], "Annotate %s", 1647 asprintf(&options[nr_options], "Annotate %s",
1625 browser->selection->sym->name) > 0) 1648 browser->selection->sym->name) > 0) {
1626 annotate = nr_options++; 1649 annotate = nr_options++;
1650 }
1627 } 1651 }
1628 } 1652 }
1629 1653skip_annotation:
1630 if (thread != NULL && 1654 if (thread != NULL &&
1631 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 1655 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
1632 (browser->hists->thread_filter ? "out of" : "into"), 1656 (browser->hists->thread_filter ? "out of" : "into"),
@@ -1682,6 +1706,7 @@ retry_popup_menu:
1682 if (choice == annotate || choice == annotate_t || choice == annotate_f) { 1706 if (choice == annotate || choice == annotate_t || choice == annotate_f) {
1683 struct hist_entry *he; 1707 struct hist_entry *he;
1684 struct annotation *notes; 1708 struct annotation *notes;
1709 struct map_symbol ms;
1685 int err; 1710 int err;
1686do_annotate: 1711do_annotate:
1687 if (!objdump_path && perf_session_env__lookup_objdump(env)) 1712 if (!objdump_path && perf_session_env__lookup_objdump(env))
@@ -1691,30 +1716,21 @@ do_annotate:
1691 if (he == NULL) 1716 if (he == NULL)
1692 continue; 1717 continue;
1693 1718
1694 /*
1695 * we stash the branch_info symbol + map into the
1696 * the ms so we don't have to rewrite all the annotation
1697 * code to use branch_info.
1698 * in branch mode, the ms struct is not used
1699 */
1700 if (choice == annotate_f) { 1719 if (choice == annotate_f) {
1701 he->ms.sym = he->branch_info->from.sym; 1720 ms.map = he->branch_info->from.map;
1702 he->ms.map = he->branch_info->from.map; 1721 ms.sym = he->branch_info->from.sym;
1703 } else if (choice == annotate_t) { 1722 } else if (choice == annotate_t) {
1704 he->ms.sym = he->branch_info->to.sym; 1723 ms.map = he->branch_info->to.map;
1705 he->ms.map = he->branch_info->to.map; 1724 ms.sym = he->branch_info->to.sym;
1725 } else {
1726 ms = *browser->selection;
1706 } 1727 }
1707 1728
1708 notes = symbol__annotation(he->ms.sym); 1729 notes = symbol__annotation(ms.sym);
1709 if (!notes->src) 1730 if (!notes->src)
1710 continue; 1731 continue;
1711 1732
1712 /* 1733 err = map_symbol__tui_annotate(&ms, evsel, hbt);
1713 * Don't let this be freed, say, by hists__decay_entry.
1714 */
1715 he->used = true;
1716 err = hist_entry__tui_annotate(he, evsel, hbt);
1717 he->used = false;
1718 /* 1734 /*
1719 * offer option to annotate the other branch source or target 1735 * offer option to annotate the other branch source or target
1720 * (if they exists) when returning from annotate 1736 * (if they exists) when returning from annotate
@@ -1754,13 +1770,13 @@ zoom_thread:
1754 pstack__remove(fstack, &browser->hists->thread_filter); 1770 pstack__remove(fstack, &browser->hists->thread_filter);
1755zoom_out_thread: 1771zoom_out_thread:
1756 ui_helpline__pop(); 1772 ui_helpline__pop();
1757 browser->hists->thread_filter = NULL; 1773 thread__zput(browser->hists->thread_filter);
1758 perf_hpp__set_elide(HISTC_THREAD, false); 1774 perf_hpp__set_elide(HISTC_THREAD, false);
1759 } else { 1775 } else {
1760 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", 1776 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1761 thread->comm_set ? thread__comm_str(thread) : "", 1777 thread->comm_set ? thread__comm_str(thread) : "",
1762 thread->tid); 1778 thread->tid);
1763 browser->hists->thread_filter = thread; 1779 browser->hists->thread_filter = thread__get(thread);
1764 perf_hpp__set_elide(HISTC_THREAD, false); 1780 perf_hpp__set_elide(HISTC_THREAD, false);
1765 pstack__push(fstack, &browser->hists->thread_filter); 1781 pstack__push(fstack, &browser->hists->thread_filter);
1766 } 1782 }
diff --git a/tools/perf/ui/gtk/Build b/tools/perf/ui/gtk/Build
new file mode 100644
index 000000000000..ec22e899a224
--- /dev/null
+++ b/tools/perf/ui/gtk/Build
@@ -0,0 +1,9 @@
1CFLAGS_gtk += -fPIC $(GTK_CFLAGS)
2
3gtk-y += browser.o
4gtk-y += hists.o
5gtk-y += setup.o
6gtk-y += util.o
7gtk-y += helpline.o
8gtk-y += progress.o
9gtk-y += annotate.o
diff --git a/tools/perf/ui/tui/Build b/tools/perf/ui/tui/Build
new file mode 100644
index 000000000000..9e4c6ca41a9f
--- /dev/null
+++ b/tools/perf/ui/tui/Build
@@ -0,0 +1,4 @@
1libperf-y += setup.o
2libperf-y += util.o
3libperf-y += helpline.o
4libperf-y += progress.o
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
new file mode 100644
index 000000000000..797490a40075
--- /dev/null
+++ b/tools/perf/util/Build
@@ -0,0 +1,145 @@
1libperf-y += abspath.o
2libperf-y += alias.o
3libperf-y += annotate.o
4libperf-y += build-id.o
5libperf-y += config.o
6libperf-y += ctype.o
7libperf-y += db-export.o
8libperf-y += environment.o
9libperf-y += event.o
10libperf-y += evlist.o
11libperf-y += evsel.o
12libperf-y += exec_cmd.o
13libperf-y += find_next_bit.o
14libperf-y += help.o
15libperf-y += kallsyms.o
16libperf-y += levenshtein.o
17libperf-y += parse-options.o
18libperf-y += parse-events.o
19libperf-y += path.o
20libperf-y += rbtree.o
21libperf-y += bitmap.o
22libperf-y += hweight.o
23libperf-y += run-command.o
24libperf-y += quote.o
25libperf-y += strbuf.o
26libperf-y += string.o
27libperf-y += strlist.o
28libperf-y += strfilter.o
29libperf-y += top.o
30libperf-y += usage.o
31libperf-y += wrapper.o
32libperf-y += sigchain.o
33libperf-y += dso.o
34libperf-y += symbol.o
35libperf-y += color.o
36libperf-y += pager.o
37libperf-y += header.o
38libperf-y += callchain.o
39libperf-y += values.o
40libperf-y += debug.o
41libperf-y += machine.o
42libperf-y += map.o
43libperf-y += pstack.o
44libperf-y += session.o
45libperf-y += ordered-events.o
46libperf-y += comm.o
47libperf-y += thread.o
48libperf-y += thread_map.o
49libperf-y += trace-event-parse.o
50libperf-y += parse-events-flex.o
51libperf-y += parse-events-bison.o
52libperf-y += pmu.o
53libperf-y += pmu-flex.o
54libperf-y += pmu-bison.o
55libperf-y += trace-event-read.o
56libperf-y += trace-event-info.o
57libperf-y += trace-event-scripting.o
58libperf-y += trace-event.o
59libperf-y += svghelper.o
60libperf-y += sort.o
61libperf-y += hist.o
62libperf-y += util.o
63libperf-y += xyarray.o
64libperf-y += cpumap.o
65libperf-y += cgroup.o
66libperf-y += target.o
67libperf-y += rblist.o
68libperf-y += intlist.o
69libperf-y += vdso.o
70libperf-y += stat.o
71libperf-y += record.o
72libperf-y += srcline.o
73libperf-y += data.o
74libperf-$(CONFIG_X86) += tsc.o
75libperf-y += cloexec.o
76libperf-y += thread-stack.o
77
78libperf-$(CONFIG_LIBELF) += symbol-elf.o
79libperf-$(CONFIG_LIBELF) += probe-event.o
80
81ifndef CONFIG_LIBELF
82libperf-y += symbol-minimal.o
83endif
84
85libperf-$(CONFIG_DWARF) += probe-finder.o
86libperf-$(CONFIG_DWARF) += dwarf-aux.o
87
88libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
89libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
90
91libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
92
93libperf-y += scripting-engines/
94
95libperf-$(CONFIG_PERF_REGS) += perf_regs.o
96libperf-$(CONFIG_ZLIB) += zlib.o
97libperf-$(CONFIG_LZMA) += lzma.o
98
99CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
100CFLAGS_exec_cmd.o += -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" -DPREFIX="BUILD_STR($(prefix_SQ))"
101
102$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
103 $(call rule_mkdir)
104 @$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
105
106$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
107 $(call rule_mkdir)
108 @$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_
109
110$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
111 $(call rule_mkdir)
112 @$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
113
114$(OUTPUT)util/pmu-bison.c: util/pmu.y
115 $(call rule_mkdir)
116 @$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_
117
118CFLAGS_parse-events-flex.o += -w
119CFLAGS_pmu-flex.o += -w
120CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
121CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
122
123$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
124$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
125
126CFLAGS_find_next_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
127CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
128CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
129CFLAGS_parse-events.o += -Wno-redundant-decls
130
131$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
132 $(call rule_mkdir)
133 $(call if_changed_dep,cc_o_c)
134
135$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c FORCE
136 $(call rule_mkdir)
137 $(call if_changed_dep,cc_o_c)
138
139$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c FORCE
140 $(call rule_mkdir)
141 $(call if_changed_dep,cc_o_c)
142
143$(OUTPUT)util/hweight.o: ../../lib/hweight.c FORCE
144 $(call rule_mkdir)
145 $(call if_changed_dep,cc_o_c)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 61bf9128e1f2..7f5bdfc9bc87 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -30,6 +30,8 @@ static int disasm_line__parse(char *line, char **namep, char **rawp);
30 30
31static void ins__delete(struct ins_operands *ops) 31static void ins__delete(struct ins_operands *ops)
32{ 32{
33 if (ops == NULL)
34 return;
33 zfree(&ops->source.raw); 35 zfree(&ops->source.raw);
34 zfree(&ops->source.name); 36 zfree(&ops->source.name);
35 zfree(&ops->target.raw); 37 zfree(&ops->target.raw);
@@ -1008,6 +1010,32 @@ fallback:
1008 } 1010 }
1009 filename = symfs_filename; 1011 filename = symfs_filename;
1010 } 1012 }
1013 } else if (dso__needs_decompress(dso)) {
1014 char tmp[PATH_MAX];
1015 struct kmod_path m;
1016 int fd;
1017 bool ret;
1018
1019 if (kmod_path__parse_ext(&m, symfs_filename))
1020 goto out_free_filename;
1021
1022 snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
1023
1024 fd = mkstemp(tmp);
1025 if (fd < 0) {
1026 free(m.ext);
1027 goto out_free_filename;
1028 }
1029
1030 ret = decompress_to_file(m.ext, symfs_filename, fd);
1031
1032 free(m.ext);
1033 close(fd);
1034
1035 if (!ret)
1036 goto out_free_filename;
1037
1038 strcpy(symfs_filename, tmp);
1011 } 1039 }
1012 1040
1013 snprintf(command, sizeof(command), 1041 snprintf(command, sizeof(command),
@@ -1027,7 +1055,7 @@ fallback:
1027 1055
1028 file = popen(command, "r"); 1056 file = popen(command, "r");
1029 if (!file) 1057 if (!file)
1030 goto out_free_filename; 1058 goto out_remove_tmp;
1031 1059
1032 while (!feof(file)) 1060 while (!feof(file))
1033 if (symbol__parse_objdump_line(sym, map, file, privsize, 1061 if (symbol__parse_objdump_line(sym, map, file, privsize,
@@ -1042,6 +1070,10 @@ fallback:
1042 delete_last_nop(sym); 1070 delete_last_nop(sym);
1043 1071
1044 pclose(file); 1072 pclose(file);
1073
1074out_remove_tmp:
1075 if (dso__needs_decompress(dso))
1076 unlink(symfs_filename);
1045out_free_filename: 1077out_free_filename:
1046 if (delete_extract) 1078 if (delete_extract)
1047 kcore_extract__delete(&kce); 1079 kcore_extract__delete(&kce);
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0c72680a977f..61867dff5d5a 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -59,11 +59,8 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
59 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 59 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
60 event->fork.ppid, event->fork.ptid); 60 event->fork.ppid, event->fork.ptid);
61 61
62 if (thread) { 62 if (thread)
63 rb_erase(&thread->rb_node, &machine->threads); 63 machine__remove_thread(machine, thread);
64 machine->last_match = NULL;
65 thread__delete(thread);
66 }
67 64
68 return 0; 65 return 0;
69} 66}
@@ -93,6 +90,35 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
93 return raw - build_id; 90 return raw - build_id;
94} 91}
95 92
93/* asnprintf consolidates asprintf and snprintf */
94static int asnprintf(char **strp, size_t size, const char *fmt, ...)
95{
96 va_list ap;
97 int ret;
98
99 if (!strp)
100 return -EINVAL;
101
102 va_start(ap, fmt);
103 if (*strp)
104 ret = vsnprintf(*strp, size, fmt, ap);
105 else
106 ret = vasprintf(strp, fmt, ap);
107 va_end(ap);
108
109 return ret;
110}
111
112static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
113{
114 char *tmp = bf;
115 int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
116 sbuild_id, sbuild_id + 2);
117 if (ret < 0 || (tmp && size < (unsigned int)ret))
118 return NULL;
119 return bf;
120}
121
96char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) 122char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
97{ 123{
98 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 124 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -101,14 +127,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
101 return NULL; 127 return NULL;
102 128
103 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex); 129 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
104 if (bf == NULL) { 130 return build_id__filename(build_id_hex, bf, size);
105 if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir,
106 build_id_hex, build_id_hex + 2) < 0)
107 return NULL;
108 } else
109 snprintf(bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
110 build_id_hex, build_id_hex + 2);
111 return bf;
112} 131}
113 132
114#define dsos__for_each_with_build_id(pos, head) \ 133#define dsos__for_each_with_build_id(pos, head) \
@@ -259,52 +278,113 @@ void disable_buildid_cache(void)
259 no_buildid_cache = true; 278 no_buildid_cache = true;
260} 279}
261 280
262int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 281static char *build_id_cache__dirname_from_path(const char *name,
263 const char *name, bool is_kallsyms, bool is_vdso) 282 bool is_kallsyms, bool is_vdso)
264{ 283{
265 const size_t size = PATH_MAX; 284 char *realname = (char *)name, *filename;
266 char *realname, *filename = zalloc(size),
267 *linkname = zalloc(size), *targetname;
268 int len, err = -1;
269 bool slash = is_kallsyms || is_vdso; 285 bool slash = is_kallsyms || is_vdso;
270 286
271 if (is_kallsyms) { 287 if (!slash) {
272 if (symbol_conf.kptr_restrict) {
273 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
274 err = 0;
275 goto out_free;
276 }
277 realname = (char *) name;
278 } else
279 realname = realpath(name, NULL); 288 realname = realpath(name, NULL);
289 if (!realname)
290 return NULL;
291 }
280 292
281 if (realname == NULL || filename == NULL || linkname == NULL) 293 if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
294 is_vdso ? DSO__NAME_VDSO : realname) < 0)
295 filename = NULL;
296
297 if (!slash)
298 free(realname);
299
300 return filename;
301}
302
303int build_id_cache__list_build_ids(const char *pathname,
304 struct strlist **result)
305{
306 struct strlist *list;
307 char *dir_name;
308 DIR *dir;
309 struct dirent *d;
310 int ret = 0;
311
312 list = strlist__new(true, NULL);
313 dir_name = build_id_cache__dirname_from_path(pathname, false, false);
314 if (!list || !dir_name) {
315 ret = -ENOMEM;
316 goto out;
317 }
318
319 /* List up all dirents */
320 dir = opendir(dir_name);
321 if (!dir) {
322 ret = -errno;
323 goto out;
324 }
325
326 while ((d = readdir(dir)) != NULL) {
327 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
328 continue;
329 strlist__add(list, d->d_name);
330 }
331 closedir(dir);
332
333out:
334 free(dir_name);
335 if (ret)
336 strlist__delete(list);
337 else
338 *result = list;
339
340 return ret;
341}
342
343int build_id_cache__add_s(const char *sbuild_id, const char *name,
344 bool is_kallsyms, bool is_vdso)
345{
346 const size_t size = PATH_MAX;
347 char *realname = NULL, *filename = NULL, *dir_name = NULL,
348 *linkname = zalloc(size), *targetname, *tmp;
349 int err = -1;
350
351 if (!is_kallsyms) {
352 realname = realpath(name, NULL);
353 if (!realname)
354 goto out_free;
355 }
356
357 dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
358 if (!dir_name)
282 goto out_free; 359 goto out_free;
283 360
284 len = scnprintf(filename, size, "%s%s%s", 361 if (mkdir_p(dir_name, 0755))
285 debugdir, slash ? "/" : "",
286 is_vdso ? DSO__NAME_VDSO : realname);
287 if (mkdir_p(filename, 0755))
288 goto out_free; 362 goto out_free;
289 363
290 snprintf(filename + len, size - len, "/%s", sbuild_id); 364 if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
365 filename = NULL;
366 goto out_free;
367 }
291 368
292 if (access(filename, F_OK)) { 369 if (access(filename, F_OK)) {
293 if (is_kallsyms) { 370 if (is_kallsyms) {
294 if (copyfile("/proc/kallsyms", filename)) 371 if (copyfile("/proc/kallsyms", filename))
295 goto out_free; 372 goto out_free;
296 } else if (link(realname, filename) && copyfile(name, filename)) 373 } else if (link(realname, filename) && errno != EEXIST &&
374 copyfile(name, filename))
297 goto out_free; 375 goto out_free;
298 } 376 }
299 377
300 len = scnprintf(linkname, size, "%s/.build-id/%.2s", 378 if (!build_id__filename(sbuild_id, linkname, size))
301 debugdir, sbuild_id); 379 goto out_free;
380 tmp = strrchr(linkname, '/');
381 *tmp = '\0';
302 382
303 if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) 383 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
304 goto out_free; 384 goto out_free;
305 385
306 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2); 386 *tmp = '/';
307 targetname = filename + strlen(debugdir) - 5; 387 targetname = filename + strlen(buildid_dir) - 5;
308 memcpy(targetname, "../..", 5); 388 memcpy(targetname, "../..", 5);
309 389
310 if (symlink(targetname, linkname) == 0) 390 if (symlink(targetname, linkname) == 0)
@@ -313,34 +393,46 @@ out_free:
313 if (!is_kallsyms) 393 if (!is_kallsyms)
314 free(realname); 394 free(realname);
315 free(filename); 395 free(filename);
396 free(dir_name);
316 free(linkname); 397 free(linkname);
317 return err; 398 return err;
318} 399}
319 400
320static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 401static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
321 const char *name, const char *debugdir, 402 const char *name, bool is_kallsyms,
322 bool is_kallsyms, bool is_vdso) 403 bool is_vdso)
323{ 404{
324 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 405 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
325 406
326 build_id__sprintf(build_id, build_id_size, sbuild_id); 407 build_id__sprintf(build_id, build_id_size, sbuild_id);
327 408
328 return build_id_cache__add_s(sbuild_id, debugdir, name, 409 return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso);
329 is_kallsyms, is_vdso); 410}
411
412bool build_id_cache__cached(const char *sbuild_id)
413{
414 bool ret = false;
415 char *filename = build_id__filename(sbuild_id, NULL, 0);
416
417 if (filename && !access(filename, F_OK))
418 ret = true;
419 free(filename);
420
421 return ret;
330} 422}
331 423
332int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) 424int build_id_cache__remove_s(const char *sbuild_id)
333{ 425{
334 const size_t size = PATH_MAX; 426 const size_t size = PATH_MAX;
335 char *filename = zalloc(size), 427 char *filename = zalloc(size),
336 *linkname = zalloc(size); 428 *linkname = zalloc(size), *tmp;
337 int err = -1; 429 int err = -1;
338 430
339 if (filename == NULL || linkname == NULL) 431 if (filename == NULL || linkname == NULL)
340 goto out_free; 432 goto out_free;
341 433
342 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 434 if (!build_id__filename(sbuild_id, linkname, size))
343 debugdir, sbuild_id, sbuild_id + 2); 435 goto out_free;
344 436
345 if (access(linkname, F_OK)) 437 if (access(linkname, F_OK))
346 goto out_free; 438 goto out_free;
@@ -354,8 +446,8 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
354 /* 446 /*
355 * Since the link is relative, we must make it absolute: 447 * Since the link is relative, we must make it absolute:
356 */ 448 */
357 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 449 tmp = strrchr(linkname, '/') + 1;
358 debugdir, sbuild_id, filename); 450 snprintf(tmp, size - (tmp - linkname), "%s", filename);
359 451
360 if (unlink(linkname)) 452 if (unlink(linkname))
361 goto out_free; 453 goto out_free;
@@ -367,8 +459,7 @@ out_free:
367 return err; 459 return err;
368} 460}
369 461
370static int dso__cache_build_id(struct dso *dso, struct machine *machine, 462static int dso__cache_build_id(struct dso *dso, struct machine *machine)
371 const char *debugdir)
372{ 463{
373 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 464 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
374 bool is_vdso = dso__is_vdso(dso); 465 bool is_vdso = dso__is_vdso(dso);
@@ -381,28 +472,26 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
381 name = nm; 472 name = nm;
382 } 473 }
383 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 474 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
384 debugdir, is_kallsyms, is_vdso); 475 is_kallsyms, is_vdso);
385} 476}
386 477
387static int __dsos__cache_build_ids(struct list_head *head, 478static int __dsos__cache_build_ids(struct list_head *head,
388 struct machine *machine, const char *debugdir) 479 struct machine *machine)
389{ 480{
390 struct dso *pos; 481 struct dso *pos;
391 int err = 0; 482 int err = 0;
392 483
393 dsos__for_each_with_build_id(pos, head) 484 dsos__for_each_with_build_id(pos, head)
394 if (dso__cache_build_id(pos, machine, debugdir)) 485 if (dso__cache_build_id(pos, machine))
395 err = -1; 486 err = -1;
396 487
397 return err; 488 return err;
398} 489}
399 490
400static int machine__cache_build_ids(struct machine *machine, const char *debugdir) 491static int machine__cache_build_ids(struct machine *machine)
401{ 492{
402 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine, 493 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine);
403 debugdir); 494 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine);
404 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
405 debugdir);
406 return ret; 495 return ret;
407} 496}
408 497
@@ -417,11 +506,11 @@ int perf_session__cache_build_ids(struct perf_session *session)
417 if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST) 506 if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST)
418 return -1; 507 return -1;
419 508
420 ret = machine__cache_build_ids(&session->machines.host, buildid_dir); 509 ret = machine__cache_build_ids(&session->machines.host);
421 510
422 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { 511 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
423 struct machine *pos = rb_entry(nd, struct machine, rb_node); 512 struct machine *pos = rb_entry(nd, struct machine, rb_node);
424 ret |= machine__cache_build_ids(pos, buildid_dir); 513 ret |= machine__cache_build_ids(pos);
425 } 514 }
426 return ret ? -1 : 0; 515 return ret ? -1 : 0;
427} 516}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 8236319514d5..85011222cc14 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -4,6 +4,7 @@
4#define BUILD_ID_SIZE 20 4#define BUILD_ID_SIZE 20
5 5
6#include "tool.h" 6#include "tool.h"
7#include "strlist.h"
7#include <linux/types.h> 8#include <linux/types.h>
8 9
9extern struct perf_tool build_id__mark_dso_hit_ops; 10extern struct perf_tool build_id__mark_dso_hit_ops;
@@ -22,9 +23,12 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
22int perf_session__write_buildid_table(struct perf_session *session, int fd); 23int perf_session__write_buildid_table(struct perf_session *session, int fd);
23int perf_session__cache_build_ids(struct perf_session *session); 24int perf_session__cache_build_ids(struct perf_session *session);
24 25
25int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 26int build_id_cache__list_build_ids(const char *pathname,
27 struct strlist **result);
28bool build_id_cache__cached(const char *sbuild_id);
29int build_id_cache__add_s(const char *sbuild_id,
26 const char *name, bool is_kallsyms, bool is_vdso); 30 const char *name, bool is_kallsyms, bool is_vdso);
27int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 31int build_id_cache__remove_s(const char *sbuild_id);
28void disable_buildid_cache(void); 32void disable_buildid_cache(void);
29 33
30#endif 34#endif
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index d04d770d90f6..fbcca21d66ab 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -17,6 +17,7 @@
17#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH" 17#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
18#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" 18#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
19#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" 19#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
20#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
20 21
21typedef int (*config_fn_t)(const char *, const char *, void *); 22typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 23extern int perf_default_config(const char *, const char *, void *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 14e7a123d43b..9f643ee77001 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -97,6 +97,14 @@ int parse_callchain_record_opt(const char *arg)
97 callchain_param.dump_size = size; 97 callchain_param.dump_size = size;
98 } 98 }
99#endif /* HAVE_DWARF_UNWIND_SUPPORT */ 99#endif /* HAVE_DWARF_UNWIND_SUPPORT */
100 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
101 if (!strtok_r(NULL, ",", &saveptr)) {
102 callchain_param.record_mode = CALLCHAIN_LBR;
103 ret = 0;
104 } else
105 pr_err("callchain: No more arguments "
106 "needed for --call-graph lbr\n");
107 break;
100 } else { 108 } else {
101 pr_err("callchain: Unknown --call-graph option " 109 pr_err("callchain: Unknown --call-graph option "
102 "value: %s\n", arg); 110 "value: %s\n", arg);
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index c0ec1acc38e4..6033a0a212ca 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -11,6 +11,7 @@ enum perf_call_graph_mode {
11 CALLCHAIN_NONE, 11 CALLCHAIN_NONE,
12 CALLCHAIN_FP, 12 CALLCHAIN_FP,
13 CALLCHAIN_DWARF, 13 CALLCHAIN_DWARF,
14 CALLCHAIN_LBR,
14 CALLCHAIN_MAX 15 CALLCHAIN_MAX
15}; 16};
16 17
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index 47b78b3f0325..85b523885f9d 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -7,6 +7,12 @@
7 7
8static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 8static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
9 9
10int __weak sched_getcpu(void)
11{
12 errno = ENOSYS;
13 return -1;
14}
15
10static int perf_flag_probe(void) 16static int perf_flag_probe(void)
11{ 17{
12 /* use 'safest' configuration as used in perf_evsel__fallback() */ 18 /* use 'safest' configuration as used in perf_evsel__fallback() */
@@ -25,6 +31,10 @@ static int perf_flag_probe(void)
25 if (cpu < 0) 31 if (cpu < 0)
26 cpu = 0; 32 cpu = 0;
27 33
34 /*
35 * Using -1 for the pid is a workaround to avoid gratuitous jump label
36 * changes.
37 */
28 while (1) { 38 while (1) {
29 /* check cloexec flag */ 39 /* check cloexec flag */
30 fd = sys_perf_event_open(&attr, pid, cpu, -1, 40 fd = sys_perf_event_open(&attr, pid, cpu, -1,
@@ -47,16 +57,24 @@ static int perf_flag_probe(void)
47 err, strerror_r(err, sbuf, sizeof(sbuf))); 57 err, strerror_r(err, sbuf, sizeof(sbuf)));
48 58
49 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 59 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
50 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0); 60 while (1) {
61 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
62 if (fd < 0 && pid == -1 && errno == EACCES) {
63 pid = 0;
64 continue;
65 }
66 break;
67 }
51 err = errno; 68 err = errno;
52 69
70 if (fd >= 0)
71 close(fd);
72
53 if (WARN_ONCE(fd < 0 && err != EBUSY, 73 if (WARN_ONCE(fd < 0 && err != EBUSY,
54 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 74 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
55 err, strerror_r(err, sbuf, sizeof(sbuf)))) 75 err, strerror_r(err, sbuf, sizeof(sbuf))))
56 return -1; 76 return -1;
57 77
58 close(fd);
59
60 return 0; 78 return 0;
61} 79}
62 80
diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h
index 94a5a7d829d5..68888c29b04a 100644
--- a/tools/perf/util/cloexec.h
+++ b/tools/perf/util/cloexec.h
@@ -3,4 +3,10 @@
3 3
4unsigned long perf_event_open_cloexec_flag(void); 4unsigned long perf_event_open_cloexec_flag(void);
5 5
6#ifdef __GLIBC_PREREQ
7#if !__GLIBC_PREREQ(2, 6)
8extern int sched_getcpu(void) __THROW;
9#endif
10#endif
11
6#endif /* __PERF_CLOEXEC_H */ 12#endif /* __PERF_CLOEXEC_H */
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
new file mode 100644
index 000000000000..dd17c9a32fbc
--- /dev/null
+++ b/tools/perf/util/data-convert-bt.c
@@ -0,0 +1,857 @@
1/*
2 * CTF writing support via babeltrace.
3 *
4 * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
5 * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9
10#include <linux/compiler.h>
11#include <babeltrace/ctf-writer/writer.h>
12#include <babeltrace/ctf-writer/clock.h>
13#include <babeltrace/ctf-writer/stream.h>
14#include <babeltrace/ctf-writer/event.h>
15#include <babeltrace/ctf-writer/event-types.h>
16#include <babeltrace/ctf-writer/event-fields.h>
17#include <babeltrace/ctf/events.h>
18#include <traceevent/event-parse.h>
19#include "asm/bug.h"
20#include "data-convert-bt.h"
21#include "session.h"
22#include "util.h"
23#include "debug.h"
24#include "tool.h"
25#include "evlist.h"
26#include "evsel.h"
27#include "machine.h"
28
29#define pr_N(n, fmt, ...) \
30 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
31
32#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
33#define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
34
35#define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
36
37struct evsel_priv {
38 struct bt_ctf_event_class *event_class;
39};
40
41struct ctf_writer {
42 /* writer primitives */
43 struct bt_ctf_writer *writer;
44 struct bt_ctf_stream *stream;
45 struct bt_ctf_stream_class *stream_class;
46 struct bt_ctf_clock *clock;
47
48 /* data types */
49 union {
50 struct {
51 struct bt_ctf_field_type *s64;
52 struct bt_ctf_field_type *u64;
53 struct bt_ctf_field_type *s32;
54 struct bt_ctf_field_type *u32;
55 struct bt_ctf_field_type *string;
56 struct bt_ctf_field_type *u64_hex;
57 };
58 struct bt_ctf_field_type *array[6];
59 } data;
60};
61
62struct convert {
63 struct perf_tool tool;
64 struct ctf_writer writer;
65
66 u64 events_size;
67 u64 events_count;
68};
69
70static int value_set(struct bt_ctf_field_type *type,
71 struct bt_ctf_event *event,
72 const char *name, u64 val)
73{
74 struct bt_ctf_field *field;
75 bool sign = bt_ctf_field_type_integer_get_signed(type);
76 int ret;
77
78 field = bt_ctf_field_create(type);
79 if (!field) {
80 pr_err("failed to create a field %s\n", name);
81 return -1;
82 }
83
84 if (sign) {
85 ret = bt_ctf_field_signed_integer_set_value(field, val);
86 if (ret) {
87 pr_err("failed to set field value %s\n", name);
88 goto err;
89 }
90 } else {
91 ret = bt_ctf_field_unsigned_integer_set_value(field, val);
92 if (ret) {
93 pr_err("failed to set field value %s\n", name);
94 goto err;
95 }
96 }
97
98 ret = bt_ctf_event_set_payload(event, name, field);
99 if (ret) {
100 pr_err("failed to set payload %s\n", name);
101 goto err;
102 }
103
104 pr2(" SET [%s = %" PRIu64 "]\n", name, val);
105
106err:
107 bt_ctf_field_put(field);
108 return ret;
109}
110
111#define __FUNC_VALUE_SET(_name, _val_type) \
112static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \
113 struct bt_ctf_event *event, \
114 const char *name, \
115 _val_type val) \
116{ \
117 struct bt_ctf_field_type *type = cw->data._name; \
118 return value_set(type, event, name, (u64) val); \
119}
120
121#define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
122
123FUNC_VALUE_SET(s32)
124FUNC_VALUE_SET(u32)
125FUNC_VALUE_SET(s64)
126FUNC_VALUE_SET(u64)
127__FUNC_VALUE_SET(u64_hex, u64)
128
129static struct bt_ctf_field_type*
130get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
131{
132 unsigned long flags = field->flags;
133
134 if (flags & FIELD_IS_STRING)
135 return cw->data.string;
136
137 if (!(flags & FIELD_IS_SIGNED)) {
138 /* unsigned long are mostly pointers */
139 if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
140 return cw->data.u64_hex;
141 }
142
143 if (flags & FIELD_IS_SIGNED) {
144 if (field->size == 8)
145 return cw->data.s64;
146 else
147 return cw->data.s32;
148 }
149
150 if (field->size == 8)
151 return cw->data.u64;
152 else
153 return cw->data.u32;
154}
155
156static int add_tracepoint_field_value(struct ctf_writer *cw,
157 struct bt_ctf_event_class *event_class,
158 struct bt_ctf_event *event,
159 struct perf_sample *sample,
160 struct format_field *fmtf)
161{
162 struct bt_ctf_field_type *type;
163 struct bt_ctf_field *array_field;
164 struct bt_ctf_field *field;
165 const char *name = fmtf->name;
166 void *data = sample->raw_data;
167 unsigned long long value_int;
168 unsigned long flags = fmtf->flags;
169 unsigned int n_items;
170 unsigned int i;
171 unsigned int offset;
172 unsigned int len;
173 int ret;
174
175 offset = fmtf->offset;
176 len = fmtf->size;
177 if (flags & FIELD_IS_STRING)
178 flags &= ~FIELD_IS_ARRAY;
179
180 if (flags & FIELD_IS_DYNAMIC) {
181 unsigned long long tmp_val;
182
183 tmp_val = pevent_read_number(fmtf->event->pevent,
184 data + offset, len);
185 offset = tmp_val;
186 len = offset >> 16;
187 offset &= 0xffff;
188 }
189
190 if (flags & FIELD_IS_ARRAY) {
191
192 type = bt_ctf_event_class_get_field_by_name(
193 event_class, name);
194 array_field = bt_ctf_field_create(type);
195 bt_ctf_field_type_put(type);
196 if (!array_field) {
197 pr_err("Failed to create array type %s\n", name);
198 return -1;
199 }
200
201 len = fmtf->size / fmtf->arraylen;
202 n_items = fmtf->arraylen;
203 } else {
204 n_items = 1;
205 array_field = NULL;
206 }
207
208 type = get_tracepoint_field_type(cw, fmtf);
209
210 for (i = 0; i < n_items; i++) {
211 if (!(flags & FIELD_IS_STRING))
212 value_int = pevent_read_number(
213 fmtf->event->pevent,
214 data + offset + i * len, len);
215
216 if (flags & FIELD_IS_ARRAY)
217 field = bt_ctf_field_array_get_field(array_field, i);
218 else
219 field = bt_ctf_field_create(type);
220
221 if (!field) {
222 pr_err("failed to create a field %s\n", name);
223 return -1;
224 }
225
226 if (flags & FIELD_IS_STRING)
227 ret = bt_ctf_field_string_set_value(field,
228 data + offset + i * len);
229 else if (!(flags & FIELD_IS_SIGNED))
230 ret = bt_ctf_field_unsigned_integer_set_value(
231 field, value_int);
232 else
233 ret = bt_ctf_field_signed_integer_set_value(
234 field, value_int);
235 if (ret) {
236 pr_err("failed to set file value %s\n", name);
237 goto err_put_field;
238 }
239 if (!(flags & FIELD_IS_ARRAY)) {
240 ret = bt_ctf_event_set_payload(event, name, field);
241 if (ret) {
242 pr_err("failed to set payload %s\n", name);
243 goto err_put_field;
244 }
245 }
246 bt_ctf_field_put(field);
247 }
248 if (flags & FIELD_IS_ARRAY) {
249 ret = bt_ctf_event_set_payload(event, name, array_field);
250 if (ret) {
251 pr_err("Failed add payload array %s\n", name);
252 return -1;
253 }
254 bt_ctf_field_put(array_field);
255 }
256 return 0;
257
258err_put_field:
259 bt_ctf_field_put(field);
260 return -1;
261}
262
263static int add_tracepoint_fields_values(struct ctf_writer *cw,
264 struct bt_ctf_event_class *event_class,
265 struct bt_ctf_event *event,
266 struct format_field *fields,
267 struct perf_sample *sample)
268{
269 struct format_field *field;
270 int ret;
271
272 for (field = fields; field; field = field->next) {
273 ret = add_tracepoint_field_value(cw, event_class, event, sample,
274 field);
275 if (ret)
276 return -1;
277 }
278 return 0;
279}
280
281static int add_tracepoint_values(struct ctf_writer *cw,
282 struct bt_ctf_event_class *event_class,
283 struct bt_ctf_event *event,
284 struct perf_evsel *evsel,
285 struct perf_sample *sample)
286{
287 struct format_field *common_fields = evsel->tp_format->format.common_fields;
288 struct format_field *fields = evsel->tp_format->format.fields;
289 int ret;
290
291 ret = add_tracepoint_fields_values(cw, event_class, event,
292 common_fields, sample);
293 if (!ret)
294 ret = add_tracepoint_fields_values(cw, event_class, event,
295 fields, sample);
296
297 return ret;
298}
299
300static int add_generic_values(struct ctf_writer *cw,
301 struct bt_ctf_event *event,
302 struct perf_evsel *evsel,
303 struct perf_sample *sample)
304{
305 u64 type = evsel->attr.sample_type;
306 int ret;
307
308 /*
309 * missing:
310 * PERF_SAMPLE_TIME - not needed as we have it in
311 * ctf event header
312 * PERF_SAMPLE_READ - TODO
313 * PERF_SAMPLE_CALLCHAIN - TODO
314 * PERF_SAMPLE_RAW - tracepoint fields are handled separately
315 * PERF_SAMPLE_BRANCH_STACK - TODO
316 * PERF_SAMPLE_REGS_USER - TODO
317 * PERF_SAMPLE_STACK_USER - TODO
318 */
319
320 if (type & PERF_SAMPLE_IP) {
321 ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
322 if (ret)
323 return -1;
324 }
325
326 if (type & PERF_SAMPLE_TID) {
327 ret = value_set_s32(cw, event, "perf_tid", sample->tid);
328 if (ret)
329 return -1;
330
331 ret = value_set_s32(cw, event, "perf_pid", sample->pid);
332 if (ret)
333 return -1;
334 }
335
336 if ((type & PERF_SAMPLE_ID) ||
337 (type & PERF_SAMPLE_IDENTIFIER)) {
338 ret = value_set_u64(cw, event, "perf_id", sample->id);
339 if (ret)
340 return -1;
341 }
342
343 if (type & PERF_SAMPLE_STREAM_ID) {
344 ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
345 if (ret)
346 return -1;
347 }
348
349 if (type & PERF_SAMPLE_CPU) {
350 ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
351 if (ret)
352 return -1;
353 }
354
355 if (type & PERF_SAMPLE_PERIOD) {
356 ret = value_set_u64(cw, event, "perf_period", sample->period);
357 if (ret)
358 return -1;
359 }
360
361 if (type & PERF_SAMPLE_WEIGHT) {
362 ret = value_set_u64(cw, event, "perf_weight", sample->weight);
363 if (ret)
364 return -1;
365 }
366
367 if (type & PERF_SAMPLE_DATA_SRC) {
368 ret = value_set_u64(cw, event, "perf_data_src",
369 sample->data_src);
370 if (ret)
371 return -1;
372 }
373
374 if (type & PERF_SAMPLE_TRANSACTION) {
375 ret = value_set_u64(cw, event, "perf_transaction",
376 sample->transaction);
377 if (ret)
378 return -1;
379 }
380
381 return 0;
382}
383
384static int process_sample_event(struct perf_tool *tool,
385 union perf_event *_event __maybe_unused,
386 struct perf_sample *sample,
387 struct perf_evsel *evsel,
388 struct machine *machine __maybe_unused)
389{
390 struct convert *c = container_of(tool, struct convert, tool);
391 struct evsel_priv *priv = evsel->priv;
392 struct ctf_writer *cw = &c->writer;
393 struct bt_ctf_event_class *event_class;
394 struct bt_ctf_event *event;
395 int ret;
396
397 if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
398 return 0;
399
400 event_class = priv->event_class;
401
402 /* update stats */
403 c->events_count++;
404 c->events_size += _event->header.size;
405
406 pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
407
408 event = bt_ctf_event_create(event_class);
409 if (!event) {
410 pr_err("Failed to create an CTF event\n");
411 return -1;
412 }
413
414 bt_ctf_clock_set_time(cw->clock, sample->time);
415
416 ret = add_generic_values(cw, event, evsel, sample);
417 if (ret)
418 return -1;
419
420 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
421 ret = add_tracepoint_values(cw, event_class, event,
422 evsel, sample);
423 if (ret)
424 return -1;
425 }
426
427 bt_ctf_stream_append_event(cw->stream, event);
428 bt_ctf_event_put(event);
429 return 0;
430}
431
432static int add_tracepoint_fields_types(struct ctf_writer *cw,
433 struct format_field *fields,
434 struct bt_ctf_event_class *event_class)
435{
436 struct format_field *field;
437 int ret;
438
439 for (field = fields; field; field = field->next) {
440 struct bt_ctf_field_type *type;
441 unsigned long flags = field->flags;
442
443 pr2(" field '%s'\n", field->name);
444
445 type = get_tracepoint_field_type(cw, field);
446 if (!type)
447 return -1;
448
449 /*
450 * A string is an array of chars. For this we use the string
451 * type and don't care that it is an array. What we don't
452 * support is an array of strings.
453 */
454 if (flags & FIELD_IS_STRING)
455 flags &= ~FIELD_IS_ARRAY;
456
457 if (flags & FIELD_IS_ARRAY)
458 type = bt_ctf_field_type_array_create(type, field->arraylen);
459
460 ret = bt_ctf_event_class_add_field(event_class, type,
461 field->name);
462
463 if (flags & FIELD_IS_ARRAY)
464 bt_ctf_field_type_put(type);
465
466 if (ret) {
467 pr_err("Failed to add field '%s\n", field->name);
468 return -1;
469 }
470 }
471
472 return 0;
473}
474
475static int add_tracepoint_types(struct ctf_writer *cw,
476 struct perf_evsel *evsel,
477 struct bt_ctf_event_class *class)
478{
479 struct format_field *common_fields = evsel->tp_format->format.common_fields;
480 struct format_field *fields = evsel->tp_format->format.fields;
481 int ret;
482
483 ret = add_tracepoint_fields_types(cw, common_fields, class);
484 if (!ret)
485 ret = add_tracepoint_fields_types(cw, fields, class);
486
487 return ret;
488}
489
490static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
491 struct bt_ctf_event_class *event_class)
492{
493 u64 type = evsel->attr.sample_type;
494
495 /*
496 * missing:
497 * PERF_SAMPLE_TIME - not needed as we have it in
498 * ctf event header
499 * PERF_SAMPLE_READ - TODO
500 * PERF_SAMPLE_CALLCHAIN - TODO
501 * PERF_SAMPLE_RAW - tracepoint fields are handled separately
502 * PERF_SAMPLE_BRANCH_STACK - TODO
503 * PERF_SAMPLE_REGS_USER - TODO
504 * PERF_SAMPLE_STACK_USER - TODO
505 */
506
507#define ADD_FIELD(cl, t, n) \
508 do { \
509 pr2(" field '%s'\n", n); \
510 if (bt_ctf_event_class_add_field(cl, t, n)) { \
511 pr_err("Failed to add field '%s;\n", n); \
512 return -1; \
513 } \
514 } while (0)
515
516 if (type & PERF_SAMPLE_IP)
517 ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
518
519 if (type & PERF_SAMPLE_TID) {
520 ADD_FIELD(event_class, cw->data.s32, "perf_tid");
521 ADD_FIELD(event_class, cw->data.s32, "perf_pid");
522 }
523
524 if ((type & PERF_SAMPLE_ID) ||
525 (type & PERF_SAMPLE_IDENTIFIER))
526 ADD_FIELD(event_class, cw->data.u64, "perf_id");
527
528 if (type & PERF_SAMPLE_STREAM_ID)
529 ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
530
531 if (type & PERF_SAMPLE_CPU)
532 ADD_FIELD(event_class, cw->data.u32, "perf_cpu");
533
534 if (type & PERF_SAMPLE_PERIOD)
535 ADD_FIELD(event_class, cw->data.u64, "perf_period");
536
537 if (type & PERF_SAMPLE_WEIGHT)
538 ADD_FIELD(event_class, cw->data.u64, "perf_weight");
539
540 if (type & PERF_SAMPLE_DATA_SRC)
541 ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
542
543 if (type & PERF_SAMPLE_TRANSACTION)
544 ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
545
546#undef ADD_FIELD
547 return 0;
548}
549
550static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
551{
552 struct bt_ctf_event_class *event_class;
553 struct evsel_priv *priv;
554 const char *name = perf_evsel__name(evsel);
555 int ret;
556
557 pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
558
559 event_class = bt_ctf_event_class_create(name);
560 if (!event_class)
561 return -1;
562
563 ret = add_generic_types(cw, evsel, event_class);
564 if (ret)
565 goto err;
566
567 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
568 ret = add_tracepoint_types(cw, evsel, event_class);
569 if (ret)
570 goto err;
571 }
572
573 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
574 if (ret) {
575 pr("Failed to add event class into stream.\n");
576 goto err;
577 }
578
579 priv = malloc(sizeof(*priv));
580 if (!priv)
581 goto err;
582
583 priv->event_class = event_class;
584 evsel->priv = priv;
585 return 0;
586
587err:
588 bt_ctf_event_class_put(event_class);
589 pr_err("Failed to add event '%s'.\n", name);
590 return -1;
591}
592
593static int setup_events(struct ctf_writer *cw, struct perf_session *session)
594{
595 struct perf_evlist *evlist = session->evlist;
596 struct perf_evsel *evsel;
597 int ret;
598
599 evlist__for_each(evlist, evsel) {
600 ret = add_event(cw, evsel);
601 if (ret)
602 return ret;
603 }
604 return 0;
605}
606
607static int ctf_writer__setup_env(struct ctf_writer *cw,
608 struct perf_session *session)
609{
610 struct perf_header *header = &session->header;
611 struct bt_ctf_writer *writer = cw->writer;
612
613#define ADD(__n, __v) \
614do { \
615 if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \
616 return -1; \
617} while (0)
618
619 ADD("host", header->env.hostname);
620 ADD("sysname", "Linux");
621 ADD("release", header->env.os_release);
622 ADD("version", header->env.version);
623 ADD("machine", header->env.arch);
624 ADD("domain", "kernel");
625 ADD("tracer_name", "perf");
626
627#undef ADD
628 return 0;
629}
630
631static int ctf_writer__setup_clock(struct ctf_writer *cw)
632{
633 struct bt_ctf_clock *clock = cw->clock;
634
635 bt_ctf_clock_set_description(clock, "perf clock");
636
637#define SET(__n, __v) \
638do { \
639 if (bt_ctf_clock_set_##__n(clock, __v)) \
640 return -1; \
641} while (0)
642
643 SET(frequency, 1000000000);
644 SET(offset_s, 0);
645 SET(offset, 0);
646 SET(precision, 10);
647 SET(is_absolute, 0);
648
649#undef SET
650 return 0;
651}
652
653static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
654{
655 struct bt_ctf_field_type *type;
656
657 type = bt_ctf_field_type_integer_create(size);
658 if (!type)
659 return NULL;
660
661 if (sign &&
662 bt_ctf_field_type_integer_set_signed(type, 1))
663 goto err;
664
665 if (hex &&
666 bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
667 goto err;
668
669 pr2("Created type: INTEGER %d-bit %ssigned %s\n",
670 size, sign ? "un" : "", hex ? "hex" : "");
671 return type;
672
673err:
674 bt_ctf_field_type_put(type);
675 return NULL;
676}
677
678static void ctf_writer__cleanup_data(struct ctf_writer *cw)
679{
680 unsigned int i;
681
682 for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
683 bt_ctf_field_type_put(cw->data.array[i]);
684}
685
686static int ctf_writer__init_data(struct ctf_writer *cw)
687{
688#define CREATE_INT_TYPE(type, size, sign, hex) \
689do { \
690 (type) = create_int_type(size, sign, hex); \
691 if (!(type)) \
692 goto err; \
693} while (0)
694
695 CREATE_INT_TYPE(cw->data.s64, 64, true, false);
696 CREATE_INT_TYPE(cw->data.u64, 64, false, false);
697 CREATE_INT_TYPE(cw->data.s32, 32, true, false);
698 CREATE_INT_TYPE(cw->data.u32, 32, false, false);
699 CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
700
701 cw->data.string = bt_ctf_field_type_string_create();
702 if (cw->data.string)
703 return 0;
704
705err:
706 ctf_writer__cleanup_data(cw);
707 pr_err("Failed to create data types.\n");
708 return -1;
709}
710
711static void ctf_writer__cleanup(struct ctf_writer *cw)
712{
713 ctf_writer__cleanup_data(cw);
714
715 bt_ctf_clock_put(cw->clock);
716 bt_ctf_stream_put(cw->stream);
717 bt_ctf_stream_class_put(cw->stream_class);
718 bt_ctf_writer_put(cw->writer);
719
720 /* and NULL all the pointers */
721 memset(cw, 0, sizeof(*cw));
722}
723
724static int ctf_writer__init(struct ctf_writer *cw, const char *path)
725{
726 struct bt_ctf_writer *writer;
727 struct bt_ctf_stream_class *stream_class;
728 struct bt_ctf_stream *stream;
729 struct bt_ctf_clock *clock;
730
731 /* CTF writer */
732 writer = bt_ctf_writer_create(path);
733 if (!writer)
734 goto err;
735
736 cw->writer = writer;
737
738 /* CTF clock */
739 clock = bt_ctf_clock_create("perf_clock");
740 if (!clock) {
741 pr("Failed to create CTF clock.\n");
742 goto err_cleanup;
743 }
744
745 cw->clock = clock;
746
747 if (ctf_writer__setup_clock(cw)) {
748 pr("Failed to setup CTF clock.\n");
749 goto err_cleanup;
750 }
751
752 /* CTF stream class */
753 stream_class = bt_ctf_stream_class_create("perf_stream");
754 if (!stream_class) {
755 pr("Failed to create CTF stream class.\n");
756 goto err_cleanup;
757 }
758
759 cw->stream_class = stream_class;
760
761 /* CTF clock stream setup */
762 if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
763 pr("Failed to assign CTF clock to stream class.\n");
764 goto err_cleanup;
765 }
766
767 if (ctf_writer__init_data(cw))
768 goto err_cleanup;
769
770 /* CTF stream instance */
771 stream = bt_ctf_writer_create_stream(writer, stream_class);
772 if (!stream) {
773 pr("Failed to create CTF stream.\n");
774 goto err_cleanup;
775 }
776
777 cw->stream = stream;
778
779 /* CTF clock writer setup */
780 if (bt_ctf_writer_add_clock(writer, clock)) {
781 pr("Failed to assign CTF clock to writer.\n");
782 goto err_cleanup;
783 }
784
785 return 0;
786
787err_cleanup:
788 ctf_writer__cleanup(cw);
789err:
790 pr_err("Failed to setup CTF writer.\n");
791 return -1;
792}
793
794int bt_convert__perf2ctf(const char *input, const char *path, bool force)
795{
796 struct perf_session *session;
797 struct perf_data_file file = {
798 .path = input,
799 .mode = PERF_DATA_MODE_READ,
800 .force = force,
801 };
802 struct convert c = {
803 .tool = {
804 .sample = process_sample_event,
805 .mmap = perf_event__process_mmap,
806 .mmap2 = perf_event__process_mmap2,
807 .comm = perf_event__process_comm,
808 .exit = perf_event__process_exit,
809 .fork = perf_event__process_fork,
810 .lost = perf_event__process_lost,
811 .tracing_data = perf_event__process_tracing_data,
812 .build_id = perf_event__process_build_id,
813 .ordered_events = true,
814 .ordering_requires_timestamps = true,
815 },
816 };
817 struct ctf_writer *cw = &c.writer;
818 int err = -1;
819
820 /* CTF writer */
821 if (ctf_writer__init(cw, path))
822 return -1;
823
824 /* perf.data session */
825 session = perf_session__new(&file, 0, &c.tool);
826 if (!session)
827 goto free_writer;
828
829 /* CTF writer env/clock setup */
830 if (ctf_writer__setup_env(cw, session))
831 goto free_session;
832
833 /* CTF events setup */
834 if (setup_events(cw, session))
835 goto free_session;
836
837 err = perf_session__process_events(session);
838 if (!err)
839 err = bt_ctf_stream_flush(cw->stream);
840
841 fprintf(stderr,
842 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
843 file.path, path);
844
845 fprintf(stderr,
846 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
847 (double) c.events_size / 1024.0 / 1024.0,
848 c.events_count);
849
850 /* its all good */
851free_session:
852 perf_session__delete(session);
853
854free_writer:
855 ctf_writer__cleanup(cw);
856 return err;
857}
diff --git a/tools/perf/util/data-convert-bt.h b/tools/perf/util/data-convert-bt.h
new file mode 100644
index 000000000000..4c204342a9d8
--- /dev/null
+++ b/tools/perf/util/data-convert-bt.h
@@ -0,0 +1,8 @@
1#ifndef __DATA_CONVERT_BT_H
2#define __DATA_CONVERT_BT_H
3#ifdef HAVE_LIBBABELTRACE_SUPPORT
4
5int bt_convert__perf2ctf(const char *input_name, const char *to_ctf, bool force);
6
7#endif /* HAVE_LIBBABELTRACE_SUPPORT */
8#endif /* __DATA_CONVERT_BT_H */
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index c81dae399763..bb39a3ffc70b 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -282,13 +282,13 @@ int db_export__branch_type(struct db_export *dbe, u32 branch_type,
282 282
283int db_export__sample(struct db_export *dbe, union perf_event *event, 283int db_export__sample(struct db_export *dbe, union perf_event *event,
284 struct perf_sample *sample, struct perf_evsel *evsel, 284 struct perf_sample *sample, struct perf_evsel *evsel,
285 struct thread *thread, struct addr_location *al) 285 struct addr_location *al)
286{ 286{
287 struct thread* thread = al->thread;
287 struct export_sample es = { 288 struct export_sample es = {
288 .event = event, 289 .event = event,
289 .sample = sample, 290 .sample = sample,
290 .evsel = evsel, 291 .evsel = evsel,
291 .thread = thread,
292 .al = al, 292 .al = al,
293 }; 293 };
294 struct thread *main_thread; 294 struct thread *main_thread;
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
index adbd22d66798..25e22fd76aca 100644
--- a/tools/perf/util/db-export.h
+++ b/tools/perf/util/db-export.h
@@ -34,7 +34,6 @@ struct export_sample {
34 union perf_event *event; 34 union perf_event *event;
35 struct perf_sample *sample; 35 struct perf_sample *sample;
36 struct perf_evsel *evsel; 36 struct perf_evsel *evsel;
37 struct thread *thread;
38 struct addr_location *al; 37 struct addr_location *al;
39 u64 db_id; 38 u64 db_id;
40 u64 comm_db_id; 39 u64 comm_db_id;
@@ -97,7 +96,7 @@ int db_export__branch_type(struct db_export *dbe, u32 branch_type,
97 const char *name); 96 const char *name);
98int db_export__sample(struct db_export *dbe, union perf_event *event, 97int db_export__sample(struct db_export *dbe, union perf_event *event,
99 struct perf_sample *sample, struct perf_evsel *evsel, 98 struct perf_sample *sample, struct perf_evsel *evsel,
100 struct thread *thread, struct addr_location *al); 99 struct addr_location *al);
101 100
102int db_export__branch_types(struct db_export *dbe); 101int db_export__branch_types(struct db_export *dbe);
103 102
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index ad60b2f20258..2da5581ec74d 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -20,6 +20,7 @@ int verbose;
20bool dump_trace = false, quiet = false; 20bool dump_trace = false, quiet = false;
21int debug_ordered_events; 21int debug_ordered_events;
22static int redirect_to_stderr; 22static int redirect_to_stderr;
23int debug_data_convert;
23 24
24static int _eprintf(int level, int var, const char *fmt, va_list args) 25static int _eprintf(int level, int var, const char *fmt, va_list args)
25{ 26{
@@ -147,6 +148,7 @@ static struct debug_variable {
147 { .name = "verbose", .ptr = &verbose }, 148 { .name = "verbose", .ptr = &verbose },
148 { .name = "ordered-events", .ptr = &debug_ordered_events}, 149 { .name = "ordered-events", .ptr = &debug_ordered_events},
149 { .name = "stderr", .ptr = &redirect_to_stderr}, 150 { .name = "stderr", .ptr = &redirect_to_stderr},
151 { .name = "data-convert", .ptr = &debug_data_convert },
150 { .name = NULL, } 152 { .name = NULL, }
151}; 153};
152 154
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index be264d6f3b30..caac2fdc6105 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -12,6 +12,7 @@
12extern int verbose; 12extern int verbose;
13extern bool quiet, dump_trace; 13extern bool quiet, dump_trace;
14extern int debug_ordered_events; 14extern int debug_ordered_events;
15extern int debug_data_convert;
15 16
16#ifndef pr_fmt 17#ifndef pr_fmt
17#define pr_fmt(fmt) fmt 18#define pr_fmt(fmt) fmt
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index c2f7d3b90966..fc0ddd5792a9 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -45,13 +45,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
45 case DSO_BINARY_TYPE__DEBUGLINK: { 45 case DSO_BINARY_TYPE__DEBUGLINK: {
46 char *debuglink; 46 char *debuglink;
47 47
48 strncpy(filename, dso->long_name, size); 48 len = __symbol__join_symfs(filename, size, dso->long_name);
49 debuglink = filename + dso->long_name_len; 49 debuglink = filename + len;
50 while (debuglink != filename && *debuglink != '/') 50 while (debuglink != filename && *debuglink != '/')
51 debuglink--; 51 debuglink--;
52 if (*debuglink == '/') 52 if (*debuglink == '/')
53 debuglink++; 53 debuglink++;
54 ret = filename__read_debuglink(dso->long_name, debuglink, 54 ret = filename__read_debuglink(filename, debuglink,
55 size - (debuglink - filename)); 55 size - (debuglink - filename));
56 } 56 }
57 break; 57 break;
@@ -148,6 +148,9 @@ static const struct {
148#ifdef HAVE_ZLIB_SUPPORT 148#ifdef HAVE_ZLIB_SUPPORT
149 { "gz", gzip_decompress_to_file }, 149 { "gz", gzip_decompress_to_file },
150#endif 150#endif
151#ifdef HAVE_LZMA_SUPPORT
152 { "xz", lzma_decompress_to_file },
153#endif
151 { NULL, NULL }, 154 { NULL, NULL },
152}; 155};
153 156
@@ -162,32 +165,14 @@ bool is_supported_compression(const char *ext)
162 return false; 165 return false;
163} 166}
164 167
165bool is_kmodule_extension(const char *ext) 168bool is_kernel_module(const char *pathname)
166{
167 if (strncmp(ext, "ko", 2))
168 return false;
169
170 if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3)))
171 return true;
172
173 return false;
174}
175
176bool is_kernel_module(const char *pathname, bool *compressed)
177{ 169{
178 const char *ext = strrchr(pathname, '.'); 170 struct kmod_path m;
179 171
180 if (ext == NULL) 172 if (kmod_path__parse(&m, pathname))
181 return false; 173 return NULL;
182
183 if (is_supported_compression(ext + 1)) {
184 if (compressed)
185 *compressed = true;
186 ext -= 3;
187 } else if (compressed)
188 *compressed = false;
189 174
190 return is_kmodule_extension(ext + 1); 175 return m.kmod;
191} 176}
192 177
193bool decompress_to_file(const char *ext, const char *filename, int output_fd) 178bool decompress_to_file(const char *ext, const char *filename, int output_fd)
@@ -209,6 +194,72 @@ bool dso__needs_decompress(struct dso *dso)
209} 194}
210 195
211/* 196/*
197 * Parses kernel module specified in @path and updates
198 * @m argument like:
199 *
200 * @comp - true if @path contains supported compression suffix,
201 * false otherwise
202 * @kmod - true if @path contains '.ko' suffix in right position,
203 * false otherwise
204 * @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name
205 * of the kernel module without suffixes, otherwise strudup-ed
206 * base name of @path
207 * @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string
208 * the compression suffix
209 *
210 * Returns 0 if there's no strdup error, -ENOMEM otherwise.
211 */
212int __kmod_path__parse(struct kmod_path *m, const char *path,
213 bool alloc_name, bool alloc_ext)
214{
215 const char *name = strrchr(path, '/');
216 const char *ext = strrchr(path, '.');
217
218 memset(m, 0x0, sizeof(*m));
219 name = name ? name + 1 : path;
220
221 /* No extension, just return name. */
222 if (ext == NULL) {
223 if (alloc_name) {
224 m->name = strdup(name);
225 return m->name ? 0 : -ENOMEM;
226 }
227 return 0;
228 }
229
230 if (is_supported_compression(ext + 1)) {
231 m->comp = true;
232 ext -= 3;
233 }
234
235 /* Check .ko extension only if there's enough name left. */
236 if (ext > name)
237 m->kmod = !strncmp(ext, ".ko", 3);
238
239 if (alloc_name) {
240 if (m->kmod) {
241 if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1)
242 return -ENOMEM;
243 } else {
244 if (asprintf(&m->name, "%s", name) == -1)
245 return -ENOMEM;
246 }
247
248 strxfrchar(m->name, '-', '_');
249 }
250
251 if (alloc_ext && m->comp) {
252 m->ext = strdup(ext + 4);
253 if (!m->ext) {
254 free((void *) m->name);
255 return -ENOMEM;
256 }
257 }
258
259 return 0;
260}
261
262/*
212 * Global list of open DSOs and the counter. 263 * Global list of open DSOs and the counter.
213 */ 264 */
214static LIST_HEAD(dso__data_open); 265static LIST_HEAD(dso__data_open);
@@ -240,7 +291,7 @@ static int do_open(char *name)
240 if (fd >= 0) 291 if (fd >= 0)
241 return fd; 292 return fd;
242 293
243 pr_debug("dso open failed, mmap: %s\n", 294 pr_debug("dso open failed: %s\n",
244 strerror_r(errno, sbuf, sizeof(sbuf))); 295 strerror_r(errno, sbuf, sizeof(sbuf)));
245 if (!dso__data_open_cnt || errno != EMFILE) 296 if (!dso__data_open_cnt || errno != EMFILE)
246 break; 297 break;
@@ -1002,21 +1053,24 @@ struct dso *dsos__find(const struct dsos *dsos, const char *name,
1002 return dso__find_by_longname(&dsos->root, name); 1053 return dso__find_by_longname(&dsos->root, name);
1003} 1054}
1004 1055
1005struct dso *__dsos__findnew(struct dsos *dsos, const char *name) 1056struct dso *dsos__addnew(struct dsos *dsos, const char *name)
1006{ 1057{
1007 struct dso *dso = dsos__find(dsos, name, false); 1058 struct dso *dso = dso__new(name);
1008 1059
1009 if (!dso) { 1060 if (dso != NULL) {
1010 dso = dso__new(name); 1061 dsos__add(dsos, dso);
1011 if (dso != NULL) { 1062 dso__set_basename(dso);
1012 dsos__add(dsos, dso);
1013 dso__set_basename(dso);
1014 }
1015 } 1063 }
1016
1017 return dso; 1064 return dso;
1018} 1065}
1019 1066
1067struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
1068{
1069 struct dso *dso = dsos__find(dsos, name, false);
1070
1071 return dso ? dso : dsos__addnew(dsos, name);
1072}
1073
1020size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 1074size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
1021 bool (skip)(struct dso *dso, int parm), int parm) 1075 bool (skip)(struct dso *dso, int parm), int parm)
1022{ 1076{
@@ -1083,3 +1137,36 @@ enum dso_type dso__type(struct dso *dso, struct machine *machine)
1083 1137
1084 return dso__type_fd(fd); 1138 return dso__type_fd(fd);
1085} 1139}
1140
1141int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
1142{
1143 int idx, errnum = dso->load_errno;
1144 /*
1145 * This must have a same ordering as the enum dso_load_errno.
1146 */
1147 static const char *dso_load__error_str[] = {
1148 "Internal tools/perf/ library error",
1149 "Invalid ELF file",
1150 "Can not read build id",
1151 "Mismatching build id",
1152 "Decompression failure",
1153 };
1154
1155 BUG_ON(buflen == 0);
1156
1157 if (errnum >= 0) {
1158 const char *err = strerror_r(errnum, buf, buflen);
1159
1160 if (err != buf)
1161 scnprintf(buf, buflen, "%s", err);
1162
1163 return 0;
1164 }
1165
1166 if (errnum < __DSO_LOAD_ERRNO__START || errnum >= __DSO_LOAD_ERRNO__END)
1167 return -1;
1168
1169 idx = errnum - __DSO_LOAD_ERRNO__START;
1170 scnprintf(buf, buflen, "%s", dso_load__error_str[idx]);
1171 return 0;
1172}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ced92841ff97..e0901b4ed8de 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -60,6 +60,31 @@ enum dso_type {
60 DSO__TYPE_X32BIT, 60 DSO__TYPE_X32BIT,
61}; 61};
62 62
63enum dso_load_errno {
64 DSO_LOAD_ERRNO__SUCCESS = 0,
65
66 /*
67 * Choose an arbitrary negative big number not to clash with standard
68 * errno since SUS requires the errno has distinct positive values.
69 * See 'Issue 6' in the link below.
70 *
71 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
72 */
73 __DSO_LOAD_ERRNO__START = -10000,
74
75 DSO_LOAD_ERRNO__INTERNAL_ERROR = __DSO_LOAD_ERRNO__START,
76
77 /* for symsrc__init() */
78 DSO_LOAD_ERRNO__INVALID_ELF,
79 DSO_LOAD_ERRNO__CANNOT_READ_BUILDID,
80 DSO_LOAD_ERRNO__MISMATCHING_BUILDID,
81
82 /* for decompress_kmodule */
83 DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE,
84
85 __DSO_LOAD_ERRNO__END,
86};
87
63#define DSO__SWAP(dso, type, val) \ 88#define DSO__SWAP(dso, type, val) \
64({ \ 89({ \
65 type ____r = val; \ 90 type ____r = val; \
@@ -113,6 +138,7 @@ struct dso {
113 enum dso_swap_type needs_swap; 138 enum dso_swap_type needs_swap;
114 enum dso_binary_type symtab_type; 139 enum dso_binary_type symtab_type;
115 enum dso_binary_type binary_type; 140 enum dso_binary_type binary_type;
141 enum dso_load_errno load_errno;
116 u8 adjust_symbols:1; 142 u8 adjust_symbols:1;
117 u8 has_build_id:1; 143 u8 has_build_id:1;
118 u8 has_srcline:1; 144 u8 has_srcline:1;
@@ -139,7 +165,8 @@ struct dso {
139 u32 status_seen; 165 u32 status_seen;
140 size_t file_size; 166 size_t file_size;
141 struct list_head open_entry; 167 struct list_head open_entry;
142 u64 frame_offset; 168 u64 debug_frame_offset;
169 u64 eh_frame_hdr_offset;
143 } data; 170 } data;
144 171
145 union { /* Tool specific area */ 172 union { /* Tool specific area */
@@ -189,11 +216,24 @@ char dso__symtab_origin(const struct dso *dso);
189int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 216int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
190 char *root_dir, char *filename, size_t size); 217 char *root_dir, char *filename, size_t size);
191bool is_supported_compression(const char *ext); 218bool is_supported_compression(const char *ext);
192bool is_kmodule_extension(const char *ext); 219bool is_kernel_module(const char *pathname);
193bool is_kernel_module(const char *pathname, bool *compressed);
194bool decompress_to_file(const char *ext, const char *filename, int output_fd); 220bool decompress_to_file(const char *ext, const char *filename, int output_fd);
195bool dso__needs_decompress(struct dso *dso); 221bool dso__needs_decompress(struct dso *dso);
196 222
223struct kmod_path {
224 char *name;
225 char *ext;
226 bool comp;
227 bool kmod;
228};
229
230int __kmod_path__parse(struct kmod_path *m, const char *path,
231 bool alloc_name, bool alloc_ext);
232
233#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false)
234#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
235#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
236
197/* 237/*
198 * The dso__data_* external interface provides following functions: 238 * The dso__data_* external interface provides following functions:
199 * dso__data_fd 239 * dso__data_fd
@@ -249,6 +289,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
249 const char *short_name, int dso_type); 289 const char *short_name, int dso_type);
250 290
251void dsos__add(struct dsos *dsos, struct dso *dso); 291void dsos__add(struct dsos *dsos, struct dso *dso);
292struct dso *dsos__addnew(struct dsos *dsos, const char *name);
252struct dso *dsos__find(const struct dsos *dsos, const char *name, 293struct dso *dsos__find(const struct dsos *dsos, const char *name,
253 bool cmp_short); 294 bool cmp_short);
254struct dso *__dsos__findnew(struct dsos *dsos, const char *name); 295struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
@@ -279,4 +320,6 @@ void dso__free_a2l(struct dso *dso);
279 320
280enum dso_type dso__type(struct dso *dso, struct machine *machine); 321enum dso_type dso__type(struct dso *dso, struct machine *machine);
281 322
323int dso__strerror_load(struct dso *dso, char *buf, size_t buflen);
324
282#endif /* __PERF_DSO */ 325#endif /* __PERF_DSO */
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index cc66c4049e09..c34e024020c7 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -278,6 +278,21 @@ bool die_is_func_def(Dwarf_Die *dw_die)
278} 278}
279 279
280/** 280/**
281 * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
282 * @dw_die: a DIE
283 *
284 * Ensure that this DIE is an instance (which has an entry address).
285 * This returns true if @dw_die is a function instance. If not, you need to
286 * call die_walk_instances() to find actual instances.
287 **/
288bool die_is_func_instance(Dwarf_Die *dw_die)
289{
290 Dwarf_Addr tmp;
291
292 /* Actually gcc optimizes non-inline as like as inlined */
293 return !dwarf_func_inline(dw_die) && dwarf_entrypc(dw_die, &tmp) == 0;
294}
295/**
281 * die_get_data_member_location - Get the data-member offset 296 * die_get_data_member_location - Get the data-member offset
282 * @mb_die: a DIE of a member of a data structure 297 * @mb_die: a DIE of a member of a data structure
283 * @offs: The offset of the member in the data structure 298 * @offs: The offset of the member in the data structure
@@ -786,10 +801,16 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
786{ 801{
787 const char *name = data; 802 const char *name = data;
788 803
789 if ((dwarf_tag(die_mem) == DW_TAG_member) && 804 if (dwarf_tag(die_mem) == DW_TAG_member) {
790 die_compare_name(die_mem, name)) 805 if (die_compare_name(die_mem, name))
791 return DIE_FIND_CB_END; 806 return DIE_FIND_CB_END;
792 807 else if (!dwarf_diename(die_mem)) { /* Unnamed structure */
808 Dwarf_Die type_die, tmp_die;
809 if (die_get_type(die_mem, &type_die) &&
810 die_find_member(&type_die, name, &tmp_die))
811 return DIE_FIND_CB_END;
812 }
813 }
793 return DIE_FIND_CB_SIBLING; 814 return DIE_FIND_CB_SIBLING;
794} 815}
795 816
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index b4fe90c6cb2d..af7dbcd5f929 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -41,6 +41,9 @@ extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
41/* Ensure that this DIE is a subprogram and definition (not declaration) */ 41/* Ensure that this DIE is a subprogram and definition (not declaration) */
42extern bool die_is_func_def(Dwarf_Die *dw_die); 42extern bool die_is_func_def(Dwarf_Die *dw_die);
43 43
44/* Ensure that this DIE is an instance of a subprogram */
45extern bool die_is_func_instance(Dwarf_Die *dw_die);
46
44/* Compare diename and tname */ 47/* Compare diename and tname */
45extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); 48extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
46 49
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6c6d044e959a..ff866c4d2e2f 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -49,72 +49,103 @@ static struct perf_sample synth_sample = {
49 .period = 1, 49 .period = 1,
50}; 50};
51 51
52static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) 52/*
53 * Assumes that the first 4095 bytes of /proc/pid/stat contains
54 * the comm, tgid and ppid.
55 */
56static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
57 pid_t *tgid, pid_t *ppid)
53{ 58{
54 char filename[PATH_MAX]; 59 char filename[PATH_MAX];
55 char bf[BUFSIZ]; 60 char bf[4096];
56 FILE *fp; 61 int fd;
57 size_t size = 0; 62 size_t size = 0, n;
58 pid_t tgid = -1; 63 char *nl, *name, *tgids, *ppids;
64
65 *tgid = -1;
66 *ppid = -1;
59 67
60 snprintf(filename, sizeof(filename), "/proc/%d/status", pid); 68 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
61 69
62 fp = fopen(filename, "r"); 70 fd = open(filename, O_RDONLY);
63 if (fp == NULL) { 71 if (fd < 0) {
64 pr_debug("couldn't open %s\n", filename); 72 pr_debug("couldn't open %s\n", filename);
65 return 0; 73 return -1;
66 } 74 }
67 75
68 while (!comm[0] || (tgid < 0)) { 76 n = read(fd, bf, sizeof(bf) - 1);
69 if (fgets(bf, sizeof(bf), fp) == NULL) { 77 close(fd);
70 pr_warning("couldn't get COMM and pgid, malformed %s\n", 78 if (n <= 0) {
71 filename); 79 pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
72 break; 80 pid);
73 } 81 return -1;
82 }
83 bf[n] = '\0';
74 84
75 if (memcmp(bf, "Name:", 5) == 0) { 85 name = strstr(bf, "Name:");
76 char *name = bf + 5; 86 tgids = strstr(bf, "Tgid:");
77 while (*name && isspace(*name)) 87 ppids = strstr(bf, "PPid:");
78 ++name; 88
79 size = strlen(name) - 1; 89 if (name) {
80 if (size >= len) 90 name += 5; /* strlen("Name:") */
81 size = len - 1; 91
82 memcpy(comm, name, size); 92 while (*name && isspace(*name))
83 comm[size] = '\0'; 93 ++name;
84 94
85 } else if (memcmp(bf, "Tgid:", 5) == 0) { 95 nl = strchr(name, '\n');
86 char *tgids = bf + 5; 96 if (nl)
87 while (*tgids && isspace(*tgids)) 97 *nl = '\0';
88 ++tgids; 98
89 tgid = atoi(tgids); 99 size = strlen(name);
90 } 100 if (size >= len)
101 size = len - 1;
102 memcpy(comm, name, size);
103 comm[size] = '\0';
104 } else {
105 pr_debug("Name: string not found for pid %d\n", pid);
91 } 106 }
92 107
93 fclose(fp); 108 if (tgids) {
109 tgids += 5; /* strlen("Tgid:") */
110 *tgid = atoi(tgids);
111 } else {
112 pr_debug("Tgid: string not found for pid %d\n", pid);
113 }
94 114
95 return tgid; 115 if (ppids) {
116 ppids += 5; /* strlen("PPid:") */
117 *ppid = atoi(ppids);
118 } else {
119 pr_debug("PPid: string not found for pid %d\n", pid);
120 }
121
122 return 0;
96} 123}
97 124
98static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 125static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
99 union perf_event *event, pid_t pid, 126 struct machine *machine,
100 perf_event__handler_t process, 127 pid_t *tgid, pid_t *ppid)
101 struct machine *machine)
102{ 128{
103 size_t size; 129 size_t size;
104 pid_t tgid; 130
131 *ppid = -1;
105 132
106 memset(&event->comm, 0, sizeof(event->comm)); 133 memset(&event->comm, 0, sizeof(event->comm));
107 134
108 if (machine__is_host(machine)) 135 if (machine__is_host(machine)) {
109 tgid = perf_event__get_comm_tgid(pid, event->comm.comm, 136 if (perf_event__get_comm_ids(pid, event->comm.comm,
110 sizeof(event->comm.comm)); 137 sizeof(event->comm.comm),
111 else 138 tgid, ppid) != 0) {
112 tgid = machine->pid; 139 return -1;
140 }
141 } else {
142 *tgid = machine->pid;
143 }
113 144
114 if (tgid < 0) 145 if (*tgid < 0)
115 goto out; 146 return -1;
116 147
117 event->comm.pid = tgid; 148 event->comm.pid = *tgid;
118 event->comm.header.type = PERF_RECORD_COMM; 149 event->comm.header.type = PERF_RECORD_COMM;
119 150
120 size = strlen(event->comm.comm) + 1; 151 size = strlen(event->comm.comm) + 1;
@@ -125,23 +156,45 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
125 machine->id_hdr_size); 156 machine->id_hdr_size);
126 event->comm.tid = pid; 157 event->comm.tid = pid;
127 158
159 return 0;
160}
161
162static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
163 union perf_event *event, pid_t pid,
164 perf_event__handler_t process,
165 struct machine *machine)
166{
167 pid_t tgid, ppid;
168
169 if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
170 return -1;
171
128 if (process(tool, event, &synth_sample, machine) != 0) 172 if (process(tool, event, &synth_sample, machine) != 0)
129 return -1; 173 return -1;
130 174
131out:
132 return tgid; 175 return tgid;
133} 176}
134 177
135static int perf_event__synthesize_fork(struct perf_tool *tool, 178static int perf_event__synthesize_fork(struct perf_tool *tool,
136 union perf_event *event, pid_t pid, 179 union perf_event *event,
137 pid_t tgid, perf_event__handler_t process, 180 pid_t pid, pid_t tgid, pid_t ppid,
181 perf_event__handler_t process,
138 struct machine *machine) 182 struct machine *machine)
139{ 183{
140 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); 184 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
141 185
142 /* this is really a clone event but we use fork to synthesize it */ 186 /*
143 event->fork.ppid = tgid; 187 * for main thread set parent to ppid from status file. For other
144 event->fork.ptid = tgid; 188 * threads set parent pid to main thread. ie., assume main thread
189 * spawns all threads in a process
190 */
191 if (tgid == pid) {
192 event->fork.ppid = ppid;
193 event->fork.ptid = ppid;
194 } else {
195 event->fork.ppid = tgid;
196 event->fork.ptid = tgid;
197 }
145 event->fork.pid = tgid; 198 event->fork.pid = tgid;
146 event->fork.tid = pid; 199 event->fork.tid = pid;
147 event->fork.header.type = PERF_RECORD_FORK; 200 event->fork.header.type = PERF_RECORD_FORK;
@@ -333,7 +386,8 @@ static int __event__synthesize_thread(union perf_event *comm_event,
333 char filename[PATH_MAX]; 386 char filename[PATH_MAX];
334 DIR *tasks; 387 DIR *tasks;
335 struct dirent dirent, *next; 388 struct dirent dirent, *next;
336 pid_t tgid; 389 pid_t tgid, ppid;
390 int rc = 0;
337 391
338 /* special case: only send one comm event using passed in pid */ 392 /* special case: only send one comm event using passed in pid */
339 if (!full) { 393 if (!full) {
@@ -361,34 +415,38 @@ static int __event__synthesize_thread(union perf_event *comm_event,
361 415
362 while (!readdir_r(tasks, &dirent, &next) && next) { 416 while (!readdir_r(tasks, &dirent, &next) && next) {
363 char *end; 417 char *end;
364 int rc = 0;
365 pid_t _pid; 418 pid_t _pid;
366 419
367 _pid = strtol(dirent.d_name, &end, 10); 420 _pid = strtol(dirent.d_name, &end, 10);
368 if (*end) 421 if (*end)
369 continue; 422 continue;
370 423
371 tgid = perf_event__synthesize_comm(tool, comm_event, _pid, 424 rc = -1;
372 process, machine); 425 if (perf_event__prepare_comm(comm_event, _pid, machine,
373 if (tgid == -1) 426 &tgid, &ppid) != 0)
374 return -1; 427 break;
375 428
429 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
430 ppid, process, machine) < 0)
431 break;
432 /*
433 * Send the prepared comm event
434 */
435 if (process(tool, comm_event, &synth_sample, machine) != 0)
436 break;
437
438 rc = 0;
376 if (_pid == pid) { 439 if (_pid == pid) {
377 /* process the parent's maps too */ 440 /* process the parent's maps too */
378 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 441 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
379 process, machine, mmap_data); 442 process, machine, mmap_data);
380 } else { 443 if (rc)
381 /* only fork the tid's map, to save time */ 444 break;
382 rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
383 process, machine);
384 } 445 }
385
386 if (rc)
387 return rc;
388 } 446 }
389 447
390 closedir(tasks); 448 closedir(tasks);
391 return 0; 449 return rc;
392} 450}
393 451
394int perf_event__synthesize_thread_map(struct perf_tool *tool, 452int perf_event__synthesize_thread_map(struct perf_tool *tool,
@@ -615,7 +673,7 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
615 else 673 else
616 s = ""; 674 s = "";
617 675
618 return fprintf(fp, "%s: %s:%d\n", s, event->comm.comm, event->comm.tid); 676 return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
619} 677}
620 678
621int perf_event__process_comm(struct perf_tool *tool __maybe_unused, 679int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c4ffe2bd0738..09b9e8d3fcf7 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -242,7 +242,6 @@ struct events_stats {
242 u32 nr_invalid_chains; 242 u32 nr_invalid_chains;
243 u32 nr_unknown_id; 243 u32 nr_unknown_id;
244 u32 nr_unprocessable_samples; 244 u32 nr_unprocessable_samples;
245 u32 nr_unordered_events;
246}; 245};
247 246
248struct attr_event { 247struct attr_event {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 28b8ce86bf12..080be93eea96 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -7,7 +7,6 @@
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include <api/fs/debugfs.h>
11#include <api/fs/fs.h> 10#include <api/fs/fs.h>
12#include <poll.h> 11#include <poll.h>
13#include "cpumap.h" 12#include "cpumap.h"
@@ -635,8 +634,8 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
635union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 634union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
636{ 635{
637 struct perf_mmap *md = &evlist->mmap[idx]; 636 struct perf_mmap *md = &evlist->mmap[idx];
638 unsigned int head = perf_mmap__read_head(md); 637 u64 head = perf_mmap__read_head(md);
639 unsigned int old = md->prev; 638 u64 old = md->prev;
640 unsigned char *data = md->base + page_size; 639 unsigned char *data = md->base + page_size;
641 union perf_event *event = NULL; 640 union perf_event *event = NULL;
642 641
@@ -696,7 +695,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
696 695
697static bool perf_mmap__empty(struct perf_mmap *md) 696static bool perf_mmap__empty(struct perf_mmap *md)
698{ 697{
699 return perf_mmap__read_head(md) != md->prev; 698 return perf_mmap__read_head(md) == md->prev;
700} 699}
701 700
702static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) 701static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
@@ -717,7 +716,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
717 struct perf_mmap *md = &evlist->mmap[idx]; 716 struct perf_mmap *md = &evlist->mmap[idx];
718 717
719 if (!evlist->overwrite) { 718 if (!evlist->overwrite) {
720 unsigned int old = md->prev; 719 u64 old = md->prev;
721 720
722 perf_mmap__write_tail(md, old); 721 perf_mmap__write_tail(md, old);
723 } 722 }
@@ -1051,7 +1050,7 @@ out_delete_threads:
1051 return -1; 1050 return -1;
1052} 1051}
1053 1052
1054int perf_evlist__apply_filters(struct perf_evlist *evlist) 1053int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
1055{ 1054{
1056 struct perf_evsel *evsel; 1055 struct perf_evsel *evsel;
1057 int err = 0; 1056 int err = 0;
@@ -1063,8 +1062,10 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist)
1063 continue; 1062 continue;
1064 1063
1065 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter); 1064 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter);
1066 if (err) 1065 if (err) {
1066 *err_evsel = evsel;
1067 break; 1067 break;
1068 }
1068 } 1069 }
1069 1070
1070 return err; 1071 return err;
@@ -1086,6 +1087,38 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
1086 return err; 1087 return err;
1087} 1088}
1088 1089
1090int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids)
1091{
1092 char *filter;
1093 int ret = -1;
1094 size_t i;
1095
1096 for (i = 0; i < npids; ++i) {
1097 if (i == 0) {
1098 if (asprintf(&filter, "common_pid != %d", pids[i]) < 0)
1099 return -1;
1100 } else {
1101 char *tmp;
1102
1103 if (asprintf(&tmp, "%s && common_pid != %d", filter, pids[i]) < 0)
1104 goto out_free;
1105
1106 free(filter);
1107 filter = tmp;
1108 }
1109 }
1110
1111 ret = perf_evlist__set_filter(evlist, filter);
1112out_free:
1113 free(filter);
1114 return ret;
1115}
1116
1117int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid)
1118{
1119 return perf_evlist__set_filter_pids(evlist, 1, &pid);
1120}
1121
1089bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) 1122bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
1090{ 1123{
1091 struct perf_evsel *pos; 1124 struct perf_evsel *pos;
@@ -1329,7 +1362,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1329 * writing exactly one byte, in workload.cork_fd, usually via 1362 * writing exactly one byte, in workload.cork_fd, usually via
1330 * perf_evlist__start_workload(). 1363 * perf_evlist__start_workload().
1331 * 1364 *
1332 * For cancelling the workload without actuallin running it, 1365 * For cancelling the workload without actually running it,
1333 * the parent will just close workload.cork_fd, without writing 1366 * the parent will just close workload.cork_fd, without writing
1334 * anything, i.e. read will return zero and we just exit() 1367 * anything, i.e. read will return zero and we just exit()
1335 * here. 1368 * here.
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index c94a9e03ecf1..b5cce95d644e 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -27,8 +27,8 @@ struct perf_mmap {
27 void *base; 27 void *base;
28 int mask; 28 int mask;
29 int refcnt; 29 int refcnt;
30 unsigned int prev; 30 u64 prev;
31 char event_copy[PERF_SAMPLE_MAX_SIZE]; 31 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
32}; 32};
33 33
34struct perf_evlist { 34struct perf_evlist {
@@ -51,6 +51,7 @@ struct perf_evlist {
51 struct thread_map *threads; 51 struct thread_map *threads;
52 struct cpu_map *cpus; 52 struct cpu_map *cpus;
53 struct perf_evsel *selected; 53 struct perf_evsel *selected;
54 struct events_stats stats;
54}; 55};
55 56
56struct perf_evsel_str_handler { 57struct perf_evsel_str_handler {
@@ -77,6 +78,8 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
77 const char *sys, const char *name, void *handler); 78 const char *sys, const char *name, void *handler);
78 79
79int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); 80int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
81int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid);
82int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
80 83
81struct perf_evsel * 84struct perf_evsel *
82perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); 85perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
@@ -149,7 +152,7 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
149} 152}
150 153
151int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); 154int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
152int perf_evlist__apply_filters(struct perf_evlist *evlist); 155int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
153 156
154void __perf_evlist__set_leader(struct list_head *list); 157void __perf_evlist__set_leader(struct list_head *list);
155void perf_evlist__set_leader(struct perf_evlist *evlist); 158void perf_evlist__set_leader(struct perf_evlist *evlist);
@@ -186,16 +189,15 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
186int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); 189int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
187int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); 190int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
188 191
189static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) 192static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
190{ 193{
191 struct perf_event_mmap_page *pc = mm->base; 194 struct perf_event_mmap_page *pc = mm->base;
192 int head = ACCESS_ONCE(pc->data_head); 195 u64 head = ACCESS_ONCE(pc->data_head);
193 rmb(); 196 rmb();
194 return head; 197 return head;
195} 198}
196 199
197static inline void perf_mmap__write_tail(struct perf_mmap *md, 200static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
198 unsigned long tail)
199{ 201{
200 struct perf_event_mmap_page *pc = md->base; 202 struct perf_event_mmap_page *pc = md->base;
201 203
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ea51a90e20a0..33e3fd8c2e68 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -32,8 +32,12 @@ static struct {
32 bool exclude_guest; 32 bool exclude_guest;
33 bool mmap2; 33 bool mmap2;
34 bool cloexec; 34 bool cloexec;
35 bool clockid;
36 bool clockid_wrong;
35} perf_missing_features; 37} perf_missing_features;
36 38
39static clockid_t clockid;
40
37static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) 41static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
38{ 42{
39 return 0; 43 return 0;
@@ -537,13 +541,30 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
537} 541}
538 542
539static void 543static void
540perf_evsel__config_callgraph(struct perf_evsel *evsel) 544perf_evsel__config_callgraph(struct perf_evsel *evsel,
545 struct record_opts *opts)
541{ 546{
542 bool function = perf_evsel__is_function_event(evsel); 547 bool function = perf_evsel__is_function_event(evsel);
543 struct perf_event_attr *attr = &evsel->attr; 548 struct perf_event_attr *attr = &evsel->attr;
544 549
545 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 550 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
546 551
552 if (callchain_param.record_mode == CALLCHAIN_LBR) {
553 if (!opts->branch_stack) {
554 if (attr->exclude_user) {
555 pr_warning("LBR callstack option is only available "
556 "to get user callchain information. "
557 "Falling back to framepointers.\n");
558 } else {
559 perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
560 attr->branch_sample_type = PERF_SAMPLE_BRANCH_USER |
561 PERF_SAMPLE_BRANCH_CALL_STACK;
562 }
563 } else
564 pr_warning("Cannot use LBR callstack with branch stack. "
565 "Falling back to framepointers.\n");
566 }
567
547 if (callchain_param.record_mode == CALLCHAIN_DWARF) { 568 if (callchain_param.record_mode == CALLCHAIN_DWARF) {
548 if (!function) { 569 if (!function) {
549 perf_evsel__set_sample_bit(evsel, REGS_USER); 570 perf_evsel__set_sample_bit(evsel, REGS_USER);
@@ -667,7 +688,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
667 evsel->attr.exclude_callchain_user = 1; 688 evsel->attr.exclude_callchain_user = 1;
668 689
669 if (callchain_param.enabled && !evsel->no_aux_samples) 690 if (callchain_param.enabled && !evsel->no_aux_samples)
670 perf_evsel__config_callgraph(evsel); 691 perf_evsel__config_callgraph(evsel, opts);
671 692
672 if (opts->sample_intr_regs) { 693 if (opts->sample_intr_regs) {
673 attr->sample_regs_intr = PERF_REGS_MASK; 694 attr->sample_regs_intr = PERF_REGS_MASK;
@@ -717,6 +738,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
717 if (opts->sample_transaction) 738 if (opts->sample_transaction)
718 perf_evsel__set_sample_bit(evsel, TRANSACTION); 739 perf_evsel__set_sample_bit(evsel, TRANSACTION);
719 740
741 if (opts->running_time) {
742 evsel->attr.read_format |=
743 PERF_FORMAT_TOTAL_TIME_ENABLED |
744 PERF_FORMAT_TOTAL_TIME_RUNNING;
745 }
746
720 /* 747 /*
721 * XXX see the function comment above 748 * XXX see the function comment above
722 * 749 *
@@ -738,6 +765,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
738 attr->disabled = 0; 765 attr->disabled = 0;
739 attr->enable_on_exec = 0; 766 attr->enable_on_exec = 0;
740 } 767 }
768
769 clockid = opts->clockid;
770 if (opts->use_clockid) {
771 attr->use_clockid = 1;
772 attr->clockid = opts->clockid;
773 }
741} 774}
742 775
743static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 776static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -978,67 +1011,126 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
978 return fd; 1011 return fd;
979} 1012}
980 1013
981#define __PRINT_ATTR(fmt, cast, field) \ 1014struct bit_names {
982 fprintf(fp, " %-19s "fmt"\n", #field, cast attr->field) 1015 int bit;
983 1016 const char *name;
984#define PRINT_ATTR_U32(field) __PRINT_ATTR("%u" , , field) 1017};
985#define PRINT_ATTR_X32(field) __PRINT_ATTR("%#x", , field) 1018
986#define PRINT_ATTR_U64(field) __PRINT_ATTR("%" PRIu64, (uint64_t), field) 1019static void __p_bits(char *buf, size_t size, u64 value, struct bit_names *bits)
987#define PRINT_ATTR_X64(field) __PRINT_ATTR("%#"PRIx64, (uint64_t), field) 1020{
988 1021 bool first_bit = true;
989#define PRINT_ATTR2N(name1, field1, name2, field2) \ 1022 int i = 0;
990 fprintf(fp, " %-19s %u %-19s %u\n", \ 1023
991 name1, attr->field1, name2, attr->field2) 1024 do {
992 1025 if (value & bits[i].bit) {
993#define PRINT_ATTR2(field1, field2) \ 1026 buf += scnprintf(buf, size, "%s%s", first_bit ? "" : "|", bits[i].name);
994 PRINT_ATTR2N(#field1, field1, #field2, field2) 1027 first_bit = false;
995 1028 }
996static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) 1029 } while (bits[++i].name != NULL);
997{ 1030}
998 size_t ret = 0; 1031
999 1032static void __p_sample_type(char *buf, size_t size, u64 value)
1000 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1033{
1001 ret += fprintf(fp, "perf_event_attr:\n"); 1034#define bit_name(n) { PERF_SAMPLE_##n, #n }
1002 1035 struct bit_names bits[] = {
1003 ret += PRINT_ATTR_U32(type); 1036 bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
1004 ret += PRINT_ATTR_U32(size); 1037 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1005 ret += PRINT_ATTR_X64(config); 1038 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1006 ret += PRINT_ATTR_U64(sample_period); 1039 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1007 ret += PRINT_ATTR_U64(sample_freq); 1040 bit_name(IDENTIFIER), bit_name(REGS_INTR),
1008 ret += PRINT_ATTR_X64(sample_type); 1041 { .name = NULL, }
1009 ret += PRINT_ATTR_X64(read_format); 1042 };
1010 1043#undef bit_name
1011 ret += PRINT_ATTR2(disabled, inherit); 1044 __p_bits(buf, size, value, bits);
1012 ret += PRINT_ATTR2(pinned, exclusive); 1045}
1013 ret += PRINT_ATTR2(exclude_user, exclude_kernel); 1046
1014 ret += PRINT_ATTR2(exclude_hv, exclude_idle); 1047static void __p_read_format(char *buf, size_t size, u64 value)
1015 ret += PRINT_ATTR2(mmap, comm); 1048{
1016 ret += PRINT_ATTR2(mmap2, comm_exec); 1049#define bit_name(n) { PERF_FORMAT_##n, #n }
1017 ret += PRINT_ATTR2(freq, inherit_stat); 1050 struct bit_names bits[] = {
1018 ret += PRINT_ATTR2(enable_on_exec, task); 1051 bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
1019 ret += PRINT_ATTR2(watermark, precise_ip); 1052 bit_name(ID), bit_name(GROUP),
1020 ret += PRINT_ATTR2(mmap_data, sample_id_all); 1053 { .name = NULL, }
1021 ret += PRINT_ATTR2(exclude_host, exclude_guest); 1054 };
1022 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, 1055#undef bit_name
1023 "excl.callchain_user", exclude_callchain_user); 1056 __p_bits(buf, size, value, bits);
1024 1057}
1025 ret += PRINT_ATTR_U32(wakeup_events); 1058
1026 ret += PRINT_ATTR_U32(wakeup_watermark); 1059#define BUF_SIZE 1024
1027 ret += PRINT_ATTR_X32(bp_type); 1060
1028 ret += PRINT_ATTR_X64(bp_addr); 1061#define p_hex(val) snprintf(buf, BUF_SIZE, "%"PRIx64, (uint64_t)(val))
1029 ret += PRINT_ATTR_X64(config1); 1062#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
1030 ret += PRINT_ATTR_U64(bp_len); 1063#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
1031 ret += PRINT_ATTR_X64(config2); 1064#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
1032 ret += PRINT_ATTR_X64(branch_sample_type); 1065#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val)
1033 ret += PRINT_ATTR_X64(sample_regs_user); 1066
1034 ret += PRINT_ATTR_U32(sample_stack_user); 1067#define PRINT_ATTRn(_n, _f, _p) \
1035 ret += PRINT_ATTR_X64(sample_regs_intr); 1068do { \
1036 1069 if (attr->_f) { \
1037 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1070 _p(attr->_f); \
1071 ret += attr__fprintf(fp, _n, buf, priv);\
1072 } \
1073} while (0)
1074
1075#define PRINT_ATTRf(_f, _p) PRINT_ATTRn(#_f, _f, _p)
1076
1077int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1078 attr__fprintf_f attr__fprintf, void *priv)
1079{
1080 char buf[BUF_SIZE];
1081 int ret = 0;
1082
1083 PRINT_ATTRf(type, p_unsigned);
1084 PRINT_ATTRf(size, p_unsigned);
1085 PRINT_ATTRf(config, p_hex);
1086 PRINT_ATTRn("{ sample_period, sample_freq }", sample_period, p_unsigned);
1087 PRINT_ATTRf(sample_type, p_sample_type);
1088 PRINT_ATTRf(read_format, p_read_format);
1089
1090 PRINT_ATTRf(disabled, p_unsigned);
1091 PRINT_ATTRf(inherit, p_unsigned);
1092 PRINT_ATTRf(pinned, p_unsigned);
1093 PRINT_ATTRf(exclusive, p_unsigned);
1094 PRINT_ATTRf(exclude_user, p_unsigned);
1095 PRINT_ATTRf(exclude_kernel, p_unsigned);
1096 PRINT_ATTRf(exclude_hv, p_unsigned);
1097 PRINT_ATTRf(exclude_idle, p_unsigned);
1098 PRINT_ATTRf(mmap, p_unsigned);
1099 PRINT_ATTRf(comm, p_unsigned);
1100 PRINT_ATTRf(freq, p_unsigned);
1101 PRINT_ATTRf(inherit_stat, p_unsigned);
1102 PRINT_ATTRf(enable_on_exec, p_unsigned);
1103 PRINT_ATTRf(task, p_unsigned);
1104 PRINT_ATTRf(watermark, p_unsigned);
1105 PRINT_ATTRf(precise_ip, p_unsigned);
1106 PRINT_ATTRf(mmap_data, p_unsigned);
1107 PRINT_ATTRf(sample_id_all, p_unsigned);
1108 PRINT_ATTRf(exclude_host, p_unsigned);
1109 PRINT_ATTRf(exclude_guest, p_unsigned);
1110 PRINT_ATTRf(exclude_callchain_kernel, p_unsigned);
1111 PRINT_ATTRf(exclude_callchain_user, p_unsigned);
1112 PRINT_ATTRf(mmap2, p_unsigned);
1113 PRINT_ATTRf(comm_exec, p_unsigned);
1114 PRINT_ATTRf(use_clockid, p_unsigned);
1115
1116 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
1117 PRINT_ATTRf(bp_type, p_unsigned);
1118 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
1119 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
1120 PRINT_ATTRf(sample_regs_user, p_hex);
1121 PRINT_ATTRf(sample_stack_user, p_unsigned);
1122 PRINT_ATTRf(clockid, p_signed);
1123 PRINT_ATTRf(sample_regs_intr, p_hex);
1038 1124
1039 return ret; 1125 return ret;
1040} 1126}
1041 1127
1128static int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
1129 void *priv __attribute__((unused)))
1130{
1131 return fprintf(fp, " %-32s %s\n", name, val);
1132}
1133
1042static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1134static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1043 struct thread_map *threads) 1135 struct thread_map *threads)
1044{ 1136{
@@ -1062,6 +1154,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1062 } 1154 }
1063 1155
1064fallback_missing_features: 1156fallback_missing_features:
1157 if (perf_missing_features.clockid_wrong)
1158 evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */
1159 if (perf_missing_features.clockid) {
1160 evsel->attr.use_clockid = 0;
1161 evsel->attr.clockid = 0;
1162 }
1065 if (perf_missing_features.cloexec) 1163 if (perf_missing_features.cloexec)
1066 flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; 1164 flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
1067 if (perf_missing_features.mmap2) 1165 if (perf_missing_features.mmap2)
@@ -1072,8 +1170,12 @@ retry_sample_id:
1072 if (perf_missing_features.sample_id_all) 1170 if (perf_missing_features.sample_id_all)
1073 evsel->attr.sample_id_all = 0; 1171 evsel->attr.sample_id_all = 0;
1074 1172
1075 if (verbose >= 2) 1173 if (verbose >= 2) {
1076 perf_event_attr__fprintf(&evsel->attr, stderr); 1174 fprintf(stderr, "%.60s\n", graph_dotted_line);
1175 fprintf(stderr, "perf_event_attr:\n");
1176 perf_event_attr__fprintf(stderr, &evsel->attr, __open_attr__fprintf, NULL);
1177 fprintf(stderr, "%.60s\n", graph_dotted_line);
1178 }
1077 1179
1078 for (cpu = 0; cpu < cpus->nr; cpu++) { 1180 for (cpu = 0; cpu < cpus->nr; cpu++) {
1079 1181
@@ -1099,6 +1201,17 @@ retry_open:
1099 goto try_fallback; 1201 goto try_fallback;
1100 } 1202 }
1101 set_rlimit = NO_CHANGE; 1203 set_rlimit = NO_CHANGE;
1204
1205 /*
1206 * If we succeeded but had to kill clockid, fail and
1207 * have perf_evsel__open_strerror() print us a nice
1208 * error.
1209 */
1210 if (perf_missing_features.clockid ||
1211 perf_missing_features.clockid_wrong) {
1212 err = -EINVAL;
1213 goto out_close;
1214 }
1102 } 1215 }
1103 } 1216 }
1104 1217
@@ -1132,7 +1245,17 @@ try_fallback:
1132 if (err != -EINVAL || cpu > 0 || thread > 0) 1245 if (err != -EINVAL || cpu > 0 || thread > 0)
1133 goto out_close; 1246 goto out_close;
1134 1247
1135 if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { 1248 /*
1249 * Must probe features in the order they were added to the
1250 * perf_event_attr interface.
1251 */
1252 if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1253 perf_missing_features.clockid_wrong = true;
1254 goto fallback_missing_features;
1255 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
1256 perf_missing_features.clockid = true;
1257 goto fallback_missing_features;
1258 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
1136 perf_missing_features.cloexec = true; 1259 perf_missing_features.cloexec = true;
1137 goto fallback_missing_features; 1260 goto fallback_missing_features;
1138 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { 1261 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
@@ -1892,7 +2015,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
1892 value = *(u32 *)ptr; 2015 value = *(u32 *)ptr;
1893 break; 2016 break;
1894 case 8: 2017 case 8:
1895 value = *(u64 *)ptr; 2018 memcpy(&value, ptr, sizeof(u64));
1896 break; 2019 break;
1897 default: 2020 default:
1898 return 0; 2021 return 0;
@@ -1933,62 +2056,9 @@ static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
1933 return ret; 2056 return ret;
1934} 2057}
1935 2058
1936static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value) 2059static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
1937{
1938 if (value == 0)
1939 return 0;
1940
1941 return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
1942}
1943
1944#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
1945
1946struct bit_names {
1947 int bit;
1948 const char *name;
1949};
1950
1951static int bits__fprintf(FILE *fp, const char *field, u64 value,
1952 struct bit_names *bits, bool *first)
1953{
1954 int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
1955 bool first_bit = true;
1956
1957 do {
1958 if (value & bits[i].bit) {
1959 printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
1960 first_bit = false;
1961 }
1962 } while (bits[++i].name != NULL);
1963
1964 return printed;
1965}
1966
1967static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
1968{
1969#define bit_name(n) { PERF_SAMPLE_##n, #n }
1970 struct bit_names bits[] = {
1971 bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
1972 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1973 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1974 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1975 bit_name(IDENTIFIER), bit_name(REGS_INTR),
1976 { .name = NULL, }
1977 };
1978#undef bit_name
1979 return bits__fprintf(fp, "sample_type", value, bits, first);
1980}
1981
1982static int read_format__fprintf(FILE *fp, bool *first, u64 value)
1983{ 2060{
1984#define bit_name(n) { PERF_FORMAT_##n, #n } 2061 return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
1985 struct bit_names bits[] = {
1986 bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
1987 bit_name(ID), bit_name(GROUP),
1988 { .name = NULL, }
1989 };
1990#undef bit_name
1991 return bits__fprintf(fp, "read_format", value, bits, first);
1992} 2062}
1993 2063
1994int perf_evsel__fprintf(struct perf_evsel *evsel, 2064int perf_evsel__fprintf(struct perf_evsel *evsel,
@@ -2017,47 +2087,13 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
2017 2087
2018 printed += fprintf(fp, "%s", perf_evsel__name(evsel)); 2088 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
2019 2089
2020 if (details->verbose || details->freq) { 2090 if (details->verbose) {
2091 printed += perf_event_attr__fprintf(fp, &evsel->attr,
2092 __print_attr__fprintf, &first);
2093 } else if (details->freq) {
2021 printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64, 2094 printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
2022 (u64)evsel->attr.sample_freq); 2095 (u64)evsel->attr.sample_freq);
2023 } 2096 }
2024
2025 if (details->verbose) {
2026 if_print(type);
2027 if_print(config);
2028 if_print(config1);
2029 if_print(config2);
2030 if_print(size);
2031 printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
2032 if (evsel->attr.read_format)
2033 printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
2034 if_print(disabled);
2035 if_print(inherit);
2036 if_print(pinned);
2037 if_print(exclusive);
2038 if_print(exclude_user);
2039 if_print(exclude_kernel);
2040 if_print(exclude_hv);
2041 if_print(exclude_idle);
2042 if_print(mmap);
2043 if_print(mmap2);
2044 if_print(comm);
2045 if_print(comm_exec);
2046 if_print(freq);
2047 if_print(inherit_stat);
2048 if_print(enable_on_exec);
2049 if_print(task);
2050 if_print(watermark);
2051 if_print(precise_ip);
2052 if_print(mmap_data);
2053 if_print(sample_id_all);
2054 if_print(exclude_host);
2055 if_print(exclude_guest);
2056 if_print(__reserved_1);
2057 if_print(wakeup_events);
2058 if_print(bp_type);
2059 if_print(branch_sample_type);
2060 }
2061out: 2097out:
2062 fputc('\n', fp); 2098 fputc('\n', fp);
2063 return ++printed; 2099 return ++printed;
@@ -2135,6 +2171,12 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2135 "The PMU counters are busy/taken by another profiler.\n" 2171 "The PMU counters are busy/taken by another profiler.\n"
2136 "We found oprofile daemon running, please stop it and try again."); 2172 "We found oprofile daemon running, please stop it and try again.");
2137 break; 2173 break;
2174 case EINVAL:
2175 if (perf_missing_features.clockid)
2176 return scnprintf(msg, size, "clockid feature not supported.");
2177 if (perf_missing_features.clockid_wrong)
2178 return scnprintf(msg, size, "wrong clockid (%d).", clockid);
2179 break;
2138 default: 2180 default:
2139 break; 2181 break;
2140 } 2182 }
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 38622747d130..e486151b0308 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -335,6 +335,7 @@ struct perf_attr_details {
335 bool freq; 335 bool freq;
336 bool verbose; 336 bool verbose;
337 bool event_group; 337 bool event_group;
338 bool force;
338}; 339};
339 340
340int perf_evsel__fprintf(struct perf_evsel *evsel, 341int perf_evsel__fprintf(struct perf_evsel *evsel,
@@ -355,4 +356,14 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
355 (_evsel) && (_evsel)->leader == (_leader); \ 356 (_evsel) && (_evsel)->leader == (_leader); \
356 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) 357 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
357 358
359static inline bool has_branch_callstack(struct perf_evsel *evsel)
360{
361 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
362}
363
364typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
365
366int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
367 attr__fprintf_f attr__fprintf, void *priv);
368
358#endif /* __PERF_EVSEL_H */ 369#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1f407f7352a7..918fd8ae2d80 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1055,6 +1055,12 @@ error:
1055 goto out; 1055 goto out;
1056} 1056}
1057 1057
1058static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
1059 void *priv __attribute__((unused)))
1060{
1061 return fprintf(fp, ", %s = %s", name, val);
1062}
1063
1058static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) 1064static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1059{ 1065{
1060 struct perf_evsel *evsel, *events = read_event_desc(ph, fd); 1066 struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
@@ -1069,26 +1075,6 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1069 for (evsel = events; evsel->attr.size; evsel++) { 1075 for (evsel = events; evsel->attr.size; evsel++) {
1070 fprintf(fp, "# event : name = %s, ", evsel->name); 1076 fprintf(fp, "# event : name = %s, ", evsel->name);
1071 1077
1072 fprintf(fp, "type = %d, config = 0x%"PRIx64
1073 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
1074 evsel->attr.type,
1075 (u64)evsel->attr.config,
1076 (u64)evsel->attr.config1,
1077 (u64)evsel->attr.config2);
1078
1079 fprintf(fp, ", excl_usr = %d, excl_kern = %d",
1080 evsel->attr.exclude_user,
1081 evsel->attr.exclude_kernel);
1082
1083 fprintf(fp, ", excl_host = %d, excl_guest = %d",
1084 evsel->attr.exclude_host,
1085 evsel->attr.exclude_guest);
1086
1087 fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
1088
1089 fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
1090 fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap);
1091 fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
1092 if (evsel->ids) { 1078 if (evsel->ids) {
1093 fprintf(fp, ", id = {"); 1079 fprintf(fp, ", id = {");
1094 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { 1080 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
@@ -1099,6 +1085,8 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1099 fprintf(fp, " }"); 1085 fprintf(fp, " }");
1100 } 1086 }
1101 1087
1088 perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL);
1089
1102 fputc('\n', fp); 1090 fputc('\n', fp);
1103 } 1091 }
1104 1092
@@ -1266,7 +1254,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1266 1254
1267 dso__set_build_id(dso, &bev->build_id); 1255 dso__set_build_id(dso, &bev->build_id);
1268 1256
1269 if (!is_kernel_module(filename, NULL)) 1257 if (!is_kernel_module(filename))
1270 dso->kernel = dso_type; 1258 dso->kernel = dso_type;
1271 1259
1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1260 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
@@ -2516,8 +2504,11 @@ int perf_session__read_header(struct perf_session *session)
2516 if (read_attr(fd, header, &f_attr) < 0) 2504 if (read_attr(fd, header, &f_attr) < 0)
2517 goto out_errno; 2505 goto out_errno;
2518 2506
2519 if (header->needs_swap) 2507 if (header->needs_swap) {
2508 f_attr.ids.size = bswap_64(f_attr.ids.size);
2509 f_attr.ids.offset = bswap_64(f_attr.ids.offset);
2520 perf_event__attr_swap(&f_attr.attr); 2510 perf_event__attr_swap(&f_attr.attr);
2511 }
2521 2512
2522 tmp = lseek(fd, 0, SEEK_CUR); 2513 tmp = lseek(fd, 0, SEEK_CUR);
2523 evsel = perf_evsel__new(&f_attr.attr); 2514 evsel = perf_evsel__new(&f_attr.attr);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 70b48a65064c..cc22b9158b93 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -263,15 +263,9 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
263 while (next) { 263 while (next) {
264 n = rb_entry(next, struct hist_entry, rb_node); 264 n = rb_entry(next, struct hist_entry, rb_node);
265 next = rb_next(&n->rb_node); 265 next = rb_next(&n->rb_node);
266 /*
267 * We may be annotating this, for instance, so keep it here in
268 * case some it gets new samples, we'll eventually free it when
269 * the user stops browsing and it agains gets fully decayed.
270 */
271 if (((zap_user && n->level == '.') || 266 if (((zap_user && n->level == '.') ||
272 (zap_kernel && n->level != '.') || 267 (zap_kernel && n->level != '.') ||
273 hists__decay_entry(hists, n)) && 268 hists__decay_entry(hists, n))) {
274 !n->used) {
275 hists__delete_entry(hists, n); 269 hists__delete_entry(hists, n);
276 } 270 }
277 } 271 }
@@ -355,6 +349,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
355 callchain_init(he->callchain); 349 callchain_init(he->callchain);
356 350
357 INIT_LIST_HEAD(&he->pairs.node); 351 INIT_LIST_HEAD(&he->pairs.node);
352 thread__get(he->thread);
358 } 353 }
359 354
360 return he; 355 return he;
@@ -941,6 +936,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
941 936
942void hist_entry__delete(struct hist_entry *he) 937void hist_entry__delete(struct hist_entry *he)
943{ 938{
939 thread__zput(he->thread);
944 zfree(&he->branch_info); 940 zfree(&he->branch_info);
945 zfree(&he->mem_info); 941 zfree(&he->mem_info);
946 zfree(&he->stat_acc); 942 zfree(&he->stat_acc);
@@ -1169,6 +1165,7 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
1169 /* force fold unfiltered entry for simplicity */ 1165 /* force fold unfiltered entry for simplicity */
1170 h->ms.unfolded = false; 1166 h->ms.unfolded = false;
1171 h->row_offset = 0; 1167 h->row_offset = 0;
1168 h->nr_rows = 0;
1172 1169
1173 hists->stats.nr_non_filtered_samples += h->stat.nr_events; 1170 hists->stats.nr_non_filtered_samples += h->stat.nr_events;
1174 1171
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2b690d028907..9f31b89a527a 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -60,7 +60,7 @@ struct hists {
60 struct rb_root entries_collapsed; 60 struct rb_root entries_collapsed;
61 u64 nr_entries; 61 u64 nr_entries;
62 u64 nr_non_filtered_entries; 62 u64 nr_non_filtered_entries;
63 const struct thread *thread_filter; 63 struct thread *thread_filter;
64 const struct dso *dso_filter; 64 const struct dso *dso_filter;
65 const char *uid_filter_str; 65 const char *uid_filter_str;
66 const char *symbol_filter_str; 66 const char *symbol_filter_str;
@@ -303,6 +303,9 @@ struct hist_browser_timer {
303 303
304#ifdef HAVE_SLANG_SUPPORT 304#ifdef HAVE_SLANG_SUPPORT
305#include "../ui/keysyms.h" 305#include "../ui/keysyms.h"
306int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
307 struct hist_browser_timer *hbt);
308
306int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 309int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
307 struct hist_browser_timer *hbt); 310 struct hist_browser_timer *hbt);
308 311
@@ -321,6 +324,12 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
321{ 324{
322 return 0; 325 return 0;
323} 326}
327static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
328 struct perf_evsel *evsel __maybe_unused,
329 struct hist_browser_timer *hbt __maybe_unused)
330{
331 return 0;
332}
324 333
325static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, 334static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
326 struct perf_evsel *evsel __maybe_unused, 335 struct perf_evsel *evsel __maybe_unused,
diff --git a/tools/perf/util/include/asm/alternative-asm.h b/tools/perf/util/include/asm/alternative-asm.h
index 6789d788d494..3a3a0f16456a 100644
--- a/tools/perf/util/include/asm/alternative-asm.h
+++ b/tools/perf/util/include/asm/alternative-asm.h
@@ -4,5 +4,6 @@
4/* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */ 4/* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */
5 5
6#define altinstruction_entry # 6#define altinstruction_entry #
7#define ALTERNATIVE_2 #
7 8
8#endif 9#endif
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index cf1d7913783b..ae825d4ec110 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -99,6 +99,7 @@ struct perf_kvm_stat {
99 int timerfd; 99 int timerfd;
100 unsigned int display_time; 100 unsigned int display_time;
101 bool live; 101 bool live;
102 bool force;
102}; 103};
103 104
104struct kvm_reg_events_ops { 105struct kvm_reg_events_ops {
diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c
new file mode 100644
index 000000000000..95a1acb61245
--- /dev/null
+++ b/tools/perf/util/lzma.c
@@ -0,0 +1,95 @@
1#include <lzma.h>
2#include <stdio.h>
3#include <linux/compiler.h>
4#include "util.h"
5#include "debug.h"
6
7#define BUFSIZE 8192
8
9static const char *lzma_strerror(lzma_ret ret)
10{
11 switch ((int) ret) {
12 case LZMA_MEM_ERROR:
13 return "Memory allocation failed";
14 case LZMA_OPTIONS_ERROR:
15 return "Unsupported decompressor flags";
16 case LZMA_FORMAT_ERROR:
17 return "The input is not in the .xz format";
18 case LZMA_DATA_ERROR:
19 return "Compressed file is corrupt";
20 case LZMA_BUF_ERROR:
21 return "Compressed file is truncated or otherwise corrupt";
22 default:
23 return "Unknown error, possibly a bug";
24 }
25}
26
27int lzma_decompress_to_file(const char *input, int output_fd)
28{
29 lzma_action action = LZMA_RUN;
30 lzma_stream strm = LZMA_STREAM_INIT;
31 lzma_ret ret;
32
33 u8 buf_in[BUFSIZE];
34 u8 buf_out[BUFSIZE];
35 FILE *infile;
36
37 infile = fopen(input, "rb");
38 if (!infile) {
39 pr_err("lzma: fopen failed on %s: '%s'\n",
40 input, strerror(errno));
41 return -1;
42 }
43
44 ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
45 if (ret != LZMA_OK) {
46 pr_err("lzma: lzma_stream_decoder failed %s (%d)\n",
47 lzma_strerror(ret), ret);
48 return -1;
49 }
50
51 strm.next_in = NULL;
52 strm.avail_in = 0;
53 strm.next_out = buf_out;
54 strm.avail_out = sizeof(buf_out);
55
56 while (1) {
57 if (strm.avail_in == 0 && !feof(infile)) {
58 strm.next_in = buf_in;
59 strm.avail_in = fread(buf_in, 1, sizeof(buf_in), infile);
60
61 if (ferror(infile)) {
62 pr_err("lzma: read error: %s\n", strerror(errno));
63 return -1;
64 }
65
66 if (feof(infile))
67 action = LZMA_FINISH;
68 }
69
70 ret = lzma_code(&strm, action);
71
72 if (strm.avail_out == 0 || ret == LZMA_STREAM_END) {
73 ssize_t write_size = sizeof(buf_out) - strm.avail_out;
74
75 if (writen(output_fd, buf_out, write_size) != write_size) {
76 pr_err("lzma: write error: %s\n", strerror(errno));
77 return -1;
78 }
79
80 strm.next_out = buf_out;
81 strm.avail_out = sizeof(buf_out);
82 }
83
84 if (ret != LZMA_OK) {
85 if (ret == LZMA_STREAM_END)
86 return 0;
87
88 pr_err("lzma: failed %s\n", lzma_strerror(ret));
89 return -1;
90 }
91 }
92
93 fclose(infile);
94 return 0;
95}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 1bca3a9f2b16..527e032e24f6 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -89,16 +89,6 @@ static void dsos__delete(struct dsos *dsos)
89 } 89 }
90} 90}
91 91
92void machine__delete_dead_threads(struct machine *machine)
93{
94 struct thread *n, *t;
95
96 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
97 list_del(&t->node);
98 thread__delete(t);
99 }
100}
101
102void machine__delete_threads(struct machine *machine) 92void machine__delete_threads(struct machine *machine)
103{ 93{
104 struct rb_node *nd = rb_first(&machine->threads); 94 struct rb_node *nd = rb_first(&machine->threads);
@@ -106,9 +96,8 @@ void machine__delete_threads(struct machine *machine)
106 while (nd) { 96 while (nd) {
107 struct thread *t = rb_entry(nd, struct thread, rb_node); 97 struct thread *t = rb_entry(nd, struct thread, rb_node);
108 98
109 rb_erase(&t->rb_node, &machine->threads);
110 nd = rb_next(nd); 99 nd = rb_next(nd);
111 thread__delete(t); 100 machine__remove_thread(machine, t);
112 } 101 }
113} 102}
114 103
@@ -361,9 +350,13 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
361 * the full rbtree: 350 * the full rbtree:
362 */ 351 */
363 th = machine->last_match; 352 th = machine->last_match;
364 if (th && th->tid == tid) { 353 if (th != NULL) {
365 machine__update_thread_pid(machine, th, pid); 354 if (th->tid == tid) {
366 return th; 355 machine__update_thread_pid(machine, th, pid);
356 return th;
357 }
358
359 thread__zput(machine->last_match);
367 } 360 }
368 361
369 while (*p != NULL) { 362 while (*p != NULL) {
@@ -371,7 +364,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
371 th = rb_entry(parent, struct thread, rb_node); 364 th = rb_entry(parent, struct thread, rb_node);
372 365
373 if (th->tid == tid) { 366 if (th->tid == tid) {
374 machine->last_match = th; 367 machine->last_match = thread__get(th);
375 machine__update_thread_pid(machine, th, pid); 368 machine__update_thread_pid(machine, th, pid);
376 return th; 369 return th;
377 } 370 }
@@ -403,8 +396,11 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
403 thread__delete(th); 396 thread__delete(th);
404 return NULL; 397 return NULL;
405 } 398 }
406 399 /*
407 machine->last_match = th; 400 * It is now in the rbtree, get a ref
401 */
402 thread__get(th);
403 machine->last_match = thread__get(th);
408 } 404 }
409 405
410 return th; 406 return th;
@@ -462,30 +458,61 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
462 return 0; 458 return 0;
463} 459}
464 460
461static struct dso*
462machine__module_dso(struct machine *machine, struct kmod_path *m,
463 const char *filename)
464{
465 struct dso *dso;
466
467 dso = dsos__find(&machine->kernel_dsos, m->name, true);
468 if (!dso) {
469 dso = dsos__addnew(&machine->kernel_dsos, m->name);
470 if (dso == NULL)
471 return NULL;
472
473 if (machine__is_host(machine))
474 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
475 else
476 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
477
478 /* _KMODULE_COMP should be next to _KMODULE */
479 if (m->kmod && m->comp)
480 dso->symtab_type++;
481
482 dso__set_short_name(dso, strdup(m->name), true);
483 dso__set_long_name(dso, strdup(filename), true);
484 }
485
486 return dso;
487}
488
465struct map *machine__new_module(struct machine *machine, u64 start, 489struct map *machine__new_module(struct machine *machine, u64 start,
466 const char *filename) 490 const char *filename)
467{ 491{
468 struct map *map; 492 struct map *map = NULL;
469 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 493 struct dso *dso;
470 bool compressed; 494 struct kmod_path m;
471 495
472 if (dso == NULL) 496 if (kmod_path__parse_name(&m, filename))
473 return NULL; 497 return NULL;
474 498
475 map = map__new2(start, dso, MAP__FUNCTION); 499 map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION,
476 if (map == NULL) 500 m.name);
477 return NULL; 501 if (map)
502 goto out;
478 503
479 if (machine__is_host(machine)) 504 dso = machine__module_dso(machine, &m, filename);
480 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 505 if (dso == NULL)
481 else 506 goto out;
482 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
483 507
484 /* _KMODULE_COMP should be next to _KMODULE */ 508 map = map__new2(start, dso, MAP__FUNCTION);
485 if (is_kernel_module(filename, &compressed) && compressed) 509 if (map == NULL)
486 dso->symtab_type++; 510 goto out;
487 511
488 map_groups__insert(&machine->kmaps, map); 512 map_groups__insert(&machine->kmaps, map);
513
514out:
515 free(m.name);
489 return map; 516 return map;
490} 517}
491 518
@@ -650,6 +677,9 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
650 machine->vmlinux_maps[type]->unmap_ip = 677 machine->vmlinux_maps[type]->unmap_ip =
651 identity__map_ip; 678 identity__map_ip;
652 kmap = map__kmap(machine->vmlinux_maps[type]); 679 kmap = map__kmap(machine->vmlinux_maps[type]);
680 if (!kmap)
681 return -1;
682
653 kmap->kmaps = &machine->kmaps; 683 kmap->kmaps = &machine->kmaps;
654 map_groups__insert(&machine->kmaps, 684 map_groups__insert(&machine->kmaps,
655 machine->vmlinux_maps[type]); 685 machine->vmlinux_maps[type]);
@@ -671,7 +701,7 @@ void machine__destroy_kernel_maps(struct machine *machine)
671 kmap = map__kmap(machine->vmlinux_maps[type]); 701 kmap = map__kmap(machine->vmlinux_maps[type]);
672 map_groups__remove(&machine->kmaps, 702 map_groups__remove(&machine->kmaps,
673 machine->vmlinux_maps[type]); 703 machine->vmlinux_maps[type]);
674 if (kmap->ref_reloc_sym) { 704 if (kmap && kmap->ref_reloc_sym) {
675 /* 705 /*
676 * ref_reloc_sym is shared among all maps, so free just 706 * ref_reloc_sym is shared among all maps, so free just
677 * on one of them. 707 * on one of them.
@@ -827,6 +857,39 @@ static char *get_kernel_version(const char *root_dir)
827 return strdup(name); 857 return strdup(name);
828} 858}
829 859
860static bool is_kmod_dso(struct dso *dso)
861{
862 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
863 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
864}
865
866static int map_groups__set_module_path(struct map_groups *mg, const char *path,
867 struct kmod_path *m)
868{
869 struct map *map;
870 char *long_name;
871
872 map = map_groups__find_by_name(mg, MAP__FUNCTION, m->name);
873 if (map == NULL)
874 return 0;
875
876 long_name = strdup(path);
877 if (long_name == NULL)
878 return -ENOMEM;
879
880 dso__set_long_name(map->dso, long_name, true);
881 dso__kernel_module_get_build_id(map->dso, "");
882
883 /*
884 * Full name could reveal us kmod compression, so
885 * we need to update the symtab_type if needed.
886 */
887 if (m->comp && is_kmod_dso(map->dso))
888 map->dso->symtab_type++;
889
890 return 0;
891}
892
830static int map_groups__set_modules_path_dir(struct map_groups *mg, 893static int map_groups__set_modules_path_dir(struct map_groups *mg,
831 const char *dir_name, int depth) 894 const char *dir_name, int depth)
832{ 895{
@@ -865,35 +928,19 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
865 if (ret < 0) 928 if (ret < 0)
866 goto out; 929 goto out;
867 } else { 930 } else {
868 char *dot = strrchr(dent->d_name, '.'), 931 struct kmod_path m;
869 dso_name[PATH_MAX];
870 struct map *map;
871 char *long_name;
872 932
873 if (dot == NULL) 933 ret = kmod_path__parse_name(&m, dent->d_name);
874 continue; 934 if (ret)
875 935 goto out;
876 /* On some system, modules are compressed like .ko.gz */
877 if (is_supported_compression(dot + 1) &&
878 is_kmodule_extension(dot - 2))
879 dot -= 3;
880 936
881 snprintf(dso_name, sizeof(dso_name), "[%.*s]", 937 if (m.kmod)
882 (int)(dot - dent->d_name), dent->d_name); 938 ret = map_groups__set_module_path(mg, path, &m);
883 939
884 strxfrchar(dso_name, '-', '_'); 940 free(m.name);
885 map = map_groups__find_by_name(mg, MAP__FUNCTION,
886 dso_name);
887 if (map == NULL)
888 continue;
889 941
890 long_name = strdup(path); 942 if (ret)
891 if (long_name == NULL) {
892 ret = -1;
893 goto out; 943 goto out;
894 }
895 dso__set_long_name(map->dso, long_name, true);
896 dso__kernel_module_get_build_id(map->dso, "");
897 } 944 }
898 } 945 }
899 946
@@ -1046,40 +1093,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1046 strlen(kmmap_prefix) - 1) == 0; 1093 strlen(kmmap_prefix) - 1) == 0;
1047 if (event->mmap.filename[0] == '/' || 1094 if (event->mmap.filename[0] == '/' ||
1048 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 1095 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
1049
1050 char short_module_name[1024];
1051 char *name, *dot;
1052
1053 if (event->mmap.filename[0] == '/') {
1054 name = strrchr(event->mmap.filename, '/');
1055 if (name == NULL)
1056 goto out_problem;
1057
1058 ++name; /* skip / */
1059 dot = strrchr(name, '.');
1060 if (dot == NULL)
1061 goto out_problem;
1062 /* On some system, modules are compressed like .ko.gz */
1063 if (is_supported_compression(dot + 1))
1064 dot -= 3;
1065 if (!is_kmodule_extension(dot + 1))
1066 goto out_problem;
1067 snprintf(short_module_name, sizeof(short_module_name),
1068 "[%.*s]", (int)(dot - name), name);
1069 strxfrchar(short_module_name, '-', '_');
1070 } else
1071 strcpy(short_module_name, event->mmap.filename);
1072
1073 map = machine__new_module(machine, event->mmap.start, 1096 map = machine__new_module(machine, event->mmap.start,
1074 event->mmap.filename); 1097 event->mmap.filename);
1075 if (map == NULL) 1098 if (map == NULL)
1076 goto out_problem; 1099 goto out_problem;
1077 1100
1078 name = strdup(short_module_name);
1079 if (name == NULL)
1080 goto out_problem;
1081
1082 dso__set_short_name(map->dso, name, true);
1083 map->end = map->start + event->mmap.len; 1101 map->end = map->start + event->mmap.len;
1084 } else if (is_kernel_mmap) { 1102 } else if (is_kernel_mmap) {
1085 const char *symbol_name = (event->mmap.filename + 1103 const char *symbol_name = (event->mmap.filename +
@@ -1092,7 +1110,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1092 struct dso *dso; 1110 struct dso *dso;
1093 1111
1094 list_for_each_entry(dso, &machine->kernel_dsos.head, node) { 1112 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
1095 if (is_kernel_module(dso->long_name, NULL)) 1113 if (is_kernel_module(dso->long_name))
1096 continue; 1114 continue;
1097 1115
1098 kernel = dso; 1116 kernel = dso;
@@ -1236,15 +1254,19 @@ out_problem:
1236 return 0; 1254 return 0;
1237} 1255}
1238 1256
1239static void machine__remove_thread(struct machine *machine, struct thread *th) 1257void machine__remove_thread(struct machine *machine, struct thread *th)
1240{ 1258{
1241 machine->last_match = NULL; 1259 if (machine->last_match == th)
1260 thread__zput(machine->last_match);
1261
1242 rb_erase(&th->rb_node, &machine->threads); 1262 rb_erase(&th->rb_node, &machine->threads);
1243 /* 1263 /*
1244 * We may have references to this thread, for instance in some hist_entry 1264 * Move it first to the dead_threads list, then drop the reference,
1245 * instances, so just move them to a separate list. 1265 * if this is the last reference, then the thread__delete destructor
1266 * will be called and we will remove it from the dead_threads list.
1246 */ 1267 */
1247 list_add_tail(&th->node, &machine->dead_threads); 1268 list_add_tail(&th->node, &machine->dead_threads);
1269 thread__put(th);
1248} 1270}
1249 1271
1250int machine__process_fork_event(struct machine *machine, union perf_event *event, 1272int machine__process_fork_event(struct machine *machine, union perf_event *event,
@@ -1387,29 +1409,27 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1387static int add_callchain_ip(struct thread *thread, 1409static int add_callchain_ip(struct thread *thread,
1388 struct symbol **parent, 1410 struct symbol **parent,
1389 struct addr_location *root_al, 1411 struct addr_location *root_al,
1390 bool branch_history, 1412 u8 *cpumode,
1391 u64 ip) 1413 u64 ip)
1392{ 1414{
1393 struct addr_location al; 1415 struct addr_location al;
1394 1416
1395 al.filtered = 0; 1417 al.filtered = 0;
1396 al.sym = NULL; 1418 al.sym = NULL;
1397 if (branch_history) 1419 if (!cpumode) {
1398 thread__find_cpumode_addr_location(thread, MAP__FUNCTION, 1420 thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
1399 ip, &al); 1421 ip, &al);
1400 else { 1422 } else {
1401 u8 cpumode = PERF_RECORD_MISC_USER;
1402
1403 if (ip >= PERF_CONTEXT_MAX) { 1423 if (ip >= PERF_CONTEXT_MAX) {
1404 switch (ip) { 1424 switch (ip) {
1405 case PERF_CONTEXT_HV: 1425 case PERF_CONTEXT_HV:
1406 cpumode = PERF_RECORD_MISC_HYPERVISOR; 1426 *cpumode = PERF_RECORD_MISC_HYPERVISOR;
1407 break; 1427 break;
1408 case PERF_CONTEXT_KERNEL: 1428 case PERF_CONTEXT_KERNEL:
1409 cpumode = PERF_RECORD_MISC_KERNEL; 1429 *cpumode = PERF_RECORD_MISC_KERNEL;
1410 break; 1430 break;
1411 case PERF_CONTEXT_USER: 1431 case PERF_CONTEXT_USER:
1412 cpumode = PERF_RECORD_MISC_USER; 1432 *cpumode = PERF_RECORD_MISC_USER;
1413 break; 1433 break;
1414 default: 1434 default:
1415 pr_debug("invalid callchain context: " 1435 pr_debug("invalid callchain context: "
@@ -1423,8 +1443,8 @@ static int add_callchain_ip(struct thread *thread,
1423 } 1443 }
1424 return 0; 1444 return 0;
1425 } 1445 }
1426 thread__find_addr_location(thread, cpumode, MAP__FUNCTION, 1446 thread__find_addr_location(thread, *cpumode, MAP__FUNCTION,
1427 ip, &al); 1447 ip, &al);
1428 } 1448 }
1429 1449
1430 if (al.sym != NULL) { 1450 if (al.sym != NULL) {
@@ -1502,18 +1522,102 @@ static int remove_loops(struct branch_entry *l, int nr)
1502 return nr; 1522 return nr;
1503} 1523}
1504 1524
1505static int thread__resolve_callchain_sample(struct thread *thread, 1525/*
1506 struct ip_callchain *chain, 1526 * Recolve LBR callstack chain sample
1507 struct branch_stack *branch, 1527 * Return:
1508 struct symbol **parent, 1528 * 1 on success get LBR callchain information
1509 struct addr_location *root_al, 1529 * 0 no available LBR callchain information, should try fp
1510 int max_stack) 1530 * negative error code on other errors.
1531 */
1532static int resolve_lbr_callchain_sample(struct thread *thread,
1533 struct perf_sample *sample,
1534 struct symbol **parent,
1535 struct addr_location *root_al,
1536 int max_stack)
1511{ 1537{
1538 struct ip_callchain *chain = sample->callchain;
1512 int chain_nr = min(max_stack, (int)chain->nr); 1539 int chain_nr = min(max_stack, (int)chain->nr);
1540 u8 cpumode = PERF_RECORD_MISC_USER;
1541 int i, j, err;
1542 u64 ip;
1543
1544 for (i = 0; i < chain_nr; i++) {
1545 if (chain->ips[i] == PERF_CONTEXT_USER)
1546 break;
1547 }
1548
1549 /* LBR only affects the user callchain */
1550 if (i != chain_nr) {
1551 struct branch_stack *lbr_stack = sample->branch_stack;
1552 int lbr_nr = lbr_stack->nr;
1553 /*
1554 * LBR callstack can only get user call chain.
1555 * The mix_chain_nr is kernel call chain
1556 * number plus LBR user call chain number.
1557 * i is kernel call chain number,
1558 * 1 is PERF_CONTEXT_USER,
1559 * lbr_nr + 1 is the user call chain number.
1560 * For details, please refer to the comments
1561 * in callchain__printf
1562 */
1563 int mix_chain_nr = i + 1 + lbr_nr + 1;
1564
1565 if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) {
1566 pr_warning("corrupted callchain. skipping...\n");
1567 return 0;
1568 }
1569
1570 for (j = 0; j < mix_chain_nr; j++) {
1571 if (callchain_param.order == ORDER_CALLEE) {
1572 if (j < i + 1)
1573 ip = chain->ips[j];
1574 else if (j > i + 1)
1575 ip = lbr_stack->entries[j - i - 2].from;
1576 else
1577 ip = lbr_stack->entries[0].to;
1578 } else {
1579 if (j < lbr_nr)
1580 ip = lbr_stack->entries[lbr_nr - j - 1].from;
1581 else if (j > lbr_nr)
1582 ip = chain->ips[i + 1 - (j - lbr_nr)];
1583 else
1584 ip = lbr_stack->entries[0].to;
1585 }
1586
1587 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
1588 if (err)
1589 return (err < 0) ? err : 0;
1590 }
1591 return 1;
1592 }
1593
1594 return 0;
1595}
1596
1597static int thread__resolve_callchain_sample(struct thread *thread,
1598 struct perf_evsel *evsel,
1599 struct perf_sample *sample,
1600 struct symbol **parent,
1601 struct addr_location *root_al,
1602 int max_stack)
1603{
1604 struct branch_stack *branch = sample->branch_stack;
1605 struct ip_callchain *chain = sample->callchain;
1606 int chain_nr = min(max_stack, (int)chain->nr);
1607 u8 cpumode = PERF_RECORD_MISC_USER;
1513 int i, j, err; 1608 int i, j, err;
1514 int skip_idx = -1; 1609 int skip_idx = -1;
1515 int first_call = 0; 1610 int first_call = 0;
1516 1611
1612 callchain_cursor_reset(&callchain_cursor);
1613
1614 if (has_branch_callstack(evsel)) {
1615 err = resolve_lbr_callchain_sample(thread, sample, parent,
1616 root_al, max_stack);
1617 if (err)
1618 return (err < 0) ? err : 0;
1619 }
1620
1517 /* 1621 /*
1518 * Based on DWARF debug information, some architectures skip 1622 * Based on DWARF debug information, some architectures skip
1519 * a callchain entry saved by the kernel. 1623 * a callchain entry saved by the kernel.
@@ -1521,8 +1625,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1521 if (chain->nr < PERF_MAX_STACK_DEPTH) 1625 if (chain->nr < PERF_MAX_STACK_DEPTH)
1522 skip_idx = arch_skip_callchain_idx(thread, chain); 1626 skip_idx = arch_skip_callchain_idx(thread, chain);
1523 1627
1524 callchain_cursor_reset(&callchain_cursor);
1525
1526 /* 1628 /*
1527 * Add branches to call stack for easier browsing. This gives 1629 * Add branches to call stack for easier browsing. This gives
1528 * more context for a sample than just the callers. 1630 * more context for a sample than just the callers.
@@ -1568,10 +1670,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1568 1670
1569 for (i = 0; i < nr; i++) { 1671 for (i = 0; i < nr; i++) {
1570 err = add_callchain_ip(thread, parent, root_al, 1672 err = add_callchain_ip(thread, parent, root_al,
1571 true, be[i].to); 1673 NULL, be[i].to);
1572 if (!err) 1674 if (!err)
1573 err = add_callchain_ip(thread, parent, root_al, 1675 err = add_callchain_ip(thread, parent, root_al,
1574 true, be[i].from); 1676 NULL, be[i].from);
1575 if (err == -EINVAL) 1677 if (err == -EINVAL)
1576 break; 1678 break;
1577 if (err) 1679 if (err)
@@ -1600,7 +1702,7 @@ check_calls:
1600#endif 1702#endif
1601 ip = chain->ips[j]; 1703 ip = chain->ips[j];
1602 1704
1603 err = add_callchain_ip(thread, parent, root_al, false, ip); 1705 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
1604 1706
1605 if (err) 1707 if (err)
1606 return (err < 0) ? err : 0; 1708 return (err < 0) ? err : 0;
@@ -1623,9 +1725,9 @@ int thread__resolve_callchain(struct thread *thread,
1623 struct addr_location *root_al, 1725 struct addr_location *root_al,
1624 int max_stack) 1726 int max_stack)
1625{ 1727{
1626 int ret = thread__resolve_callchain_sample(thread, sample->callchain, 1728 int ret = thread__resolve_callchain_sample(thread, evsel,
1627 sample->branch_stack, 1729 sample, parent,
1628 parent, root_al, max_stack); 1730 root_al, max_stack);
1629 if (ret) 1731 if (ret)
1630 return ret; 1732 return ret;
1631 1733
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index e8b7779a0a3f..6d64cedb9d1e 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -118,9 +118,9 @@ void machines__set_comm_exec(struct machines *machines, bool comm_exec);
118struct machine *machine__new_host(void); 118struct machine *machine__new_host(void);
119int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 119int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
120void machine__exit(struct machine *machine); 120void machine__exit(struct machine *machine);
121void machine__delete_dead_threads(struct machine *machine);
122void machine__delete_threads(struct machine *machine); 121void machine__delete_threads(struct machine *machine);
123void machine__delete(struct machine *machine); 122void machine__delete(struct machine *machine);
123void machine__remove_thread(struct machine *machine, struct thread *th);
124 124
125struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 125struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
126 struct addr_location *al); 126 struct addr_location *al);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 62ca9f2607d5..a14f08f41686 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -778,3 +778,23 @@ struct map *maps__next(struct map *map)
778 return rb_entry(next, struct map, rb_node); 778 return rb_entry(next, struct map, rb_node);
779 return NULL; 779 return NULL;
780} 780}
781
782struct kmap *map__kmap(struct map *map)
783{
784 if (!map->dso || !map->dso->kernel) {
785 pr_err("Internal error: map__kmap with a non-kernel map\n");
786 return NULL;
787 }
788 return (struct kmap *)(map + 1);
789}
790
791struct map_groups *map__kmaps(struct map *map)
792{
793 struct kmap *kmap = map__kmap(map);
794
795 if (!kmap || !kmap->kmaps) {
796 pr_err("Internal error: map__kmaps with a non-kernel map\n");
797 return NULL;
798 }
799 return kmap->kmaps;
800}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 0e42438b1e59..ec19c59ca38e 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -76,10 +76,8 @@ static inline struct map_groups *map_groups__get(struct map_groups *mg)
76 76
77void map_groups__put(struct map_groups *mg); 77void map_groups__put(struct map_groups *mg);
78 78
79static inline struct kmap *map__kmap(struct map *map) 79struct kmap *map__kmap(struct map *map);
80{ 80struct map_groups *map__kmaps(struct map *map);
81 return (struct kmap *)(map + 1);
82}
83 81
84static inline u64 map__map_ip(struct map *map, u64 ip) 82static inline u64 map__map_ip(struct map *map, u64 ip)
85{ 83{
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index fd4be94125fb..52be201b9b25 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -2,7 +2,6 @@
2#include <linux/compiler.h> 2#include <linux/compiler.h>
3#include <linux/string.h> 3#include <linux/string.h>
4#include "ordered-events.h" 4#include "ordered-events.h"
5#include "evlist.h"
6#include "session.h" 5#include "session.h"
7#include "asm/bug.h" 6#include "asm/bug.h"
8#include "debug.h" 7#include "debug.h"
@@ -131,8 +130,8 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
131 return new; 130 return new;
132} 131}
133 132
134struct ordered_event * 133static struct ordered_event *
135ordered_events__new(struct ordered_events *oe, u64 timestamp, 134ordered_events__new_event(struct ordered_events *oe, u64 timestamp,
136 union perf_event *event) 135 union perf_event *event)
137{ 136{
138 struct ordered_event *new; 137 struct ordered_event *new;
@@ -153,20 +152,47 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
153 free_dup_event(oe, event->event); 152 free_dup_event(oe, event->event);
154} 153}
155 154
156static int __ordered_events__flush(struct perf_session *s, 155int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
157 struct perf_tool *tool) 156 struct perf_sample *sample, u64 file_offset)
157{
158 u64 timestamp = sample->time;
159 struct ordered_event *oevent;
160
161 if (!timestamp || timestamp == ~0ULL)
162 return -ETIME;
163
164 if (timestamp < oe->last_flush) {
165 pr_oe_time(timestamp, "out of order event\n");
166 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
167 oe->last_flush_type);
168
169 oe->nr_unordered_events++;
170 }
171
172 oevent = ordered_events__new_event(oe, timestamp, event);
173 if (!oevent) {
174 ordered_events__flush(oe, OE_FLUSH__HALF);
175 oevent = ordered_events__new_event(oe, timestamp, event);
176 }
177
178 if (!oevent)
179 return -ENOMEM;
180
181 oevent->file_offset = file_offset;
182 return 0;
183}
184
185static int __ordered_events__flush(struct ordered_events *oe)
158{ 186{
159 struct ordered_events *oe = &s->ordered_events;
160 struct list_head *head = &oe->events; 187 struct list_head *head = &oe->events;
161 struct ordered_event *tmp, *iter; 188 struct ordered_event *tmp, *iter;
162 struct perf_sample sample;
163 u64 limit = oe->next_flush; 189 u64 limit = oe->next_flush;
164 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL; 190 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
165 bool show_progress = limit == ULLONG_MAX; 191 bool show_progress = limit == ULLONG_MAX;
166 struct ui_progress prog; 192 struct ui_progress prog;
167 int ret; 193 int ret;
168 194
169 if (!tool->ordered_events || !limit) 195 if (!limit)
170 return 0; 196 return 0;
171 197
172 if (show_progress) 198 if (show_progress)
@@ -178,16 +204,9 @@ static int __ordered_events__flush(struct perf_session *s,
178 204
179 if (iter->timestamp > limit) 205 if (iter->timestamp > limit)
180 break; 206 break;
181 207 ret = oe->deliver(oe, iter);
182 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
183 if (ret) 208 if (ret)
184 pr_err("Can't parse sample, err = %d\n", ret); 209 return ret;
185 else {
186 ret = perf_session__deliver_event(s, iter->event, &sample, tool,
187 iter->file_offset);
188 if (ret)
189 return ret;
190 }
191 210
192 ordered_events__delete(oe, iter); 211 ordered_events__delete(oe, iter);
193 oe->last_flush = iter->timestamp; 212 oe->last_flush = iter->timestamp;
@@ -204,10 +223,8 @@ static int __ordered_events__flush(struct perf_session *s,
204 return 0; 223 return 0;
205} 224}
206 225
207int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, 226int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
208 enum oe_flush how)
209{ 227{
210 struct ordered_events *oe = &s->ordered_events;
211 static const char * const str[] = { 228 static const char * const str[] = {
212 "NONE", 229 "NONE",
213 "FINAL", 230 "FINAL",
@@ -216,6 +233,9 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
216 }; 233 };
217 int err; 234 int err;
218 235
236 if (oe->nr_events == 0)
237 return 0;
238
219 switch (how) { 239 switch (how) {
220 case OE_FLUSH__FINAL: 240 case OE_FLUSH__FINAL:
221 oe->next_flush = ULLONG_MAX; 241 oe->next_flush = ULLONG_MAX;
@@ -248,7 +268,7 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
248 str[how], oe->nr_events); 268 str[how], oe->nr_events);
249 pr_oe_time(oe->max_timestamp, "max_timestamp\n"); 269 pr_oe_time(oe->max_timestamp, "max_timestamp\n");
250 270
251 err = __ordered_events__flush(s, tool); 271 err = __ordered_events__flush(oe);
252 272
253 if (!err) { 273 if (!err) {
254 if (how == OE_FLUSH__ROUND) 274 if (how == OE_FLUSH__ROUND)
@@ -264,13 +284,14 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
264 return err; 284 return err;
265} 285}
266 286
267void ordered_events__init(struct ordered_events *oe) 287void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver)
268{ 288{
269 INIT_LIST_HEAD(&oe->events); 289 INIT_LIST_HEAD(&oe->events);
270 INIT_LIST_HEAD(&oe->cache); 290 INIT_LIST_HEAD(&oe->cache);
271 INIT_LIST_HEAD(&oe->to_free); 291 INIT_LIST_HEAD(&oe->to_free);
272 oe->max_alloc_size = (u64) -1; 292 oe->max_alloc_size = (u64) -1;
273 oe->cur_alloc_size = 0; 293 oe->cur_alloc_size = 0;
294 oe->deliver = deliver;
274} 295}
275 296
276void ordered_events__free(struct ordered_events *oe) 297void ordered_events__free(struct ordered_events *oe)
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 7b8f9b011f38..f403991e3bfd 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -2,9 +2,8 @@
2#define __ORDERED_EVENTS_H 2#define __ORDERED_EVENTS_H
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include "tool.h"
6 5
7struct perf_session; 6struct perf_sample;
8 7
9struct ordered_event { 8struct ordered_event {
10 u64 timestamp; 9 u64 timestamp;
@@ -20,6 +19,11 @@ enum oe_flush {
20 OE_FLUSH__HALF, 19 OE_FLUSH__HALF,
21}; 20};
22 21
22struct ordered_events;
23
24typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
25 struct ordered_event *event);
26
23struct ordered_events { 27struct ordered_events {
24 u64 last_flush; 28 u64 last_flush;
25 u64 next_flush; 29 u64 next_flush;
@@ -31,18 +35,19 @@ struct ordered_events {
31 struct list_head to_free; 35 struct list_head to_free;
32 struct ordered_event *buffer; 36 struct ordered_event *buffer;
33 struct ordered_event *last; 37 struct ordered_event *last;
38 ordered_events__deliver_t deliver;
34 int buffer_idx; 39 int buffer_idx;
35 unsigned int nr_events; 40 unsigned int nr_events;
36 enum oe_flush last_flush_type; 41 enum oe_flush last_flush_type;
42 u32 nr_unordered_events;
37 bool copy_on_queue; 43 bool copy_on_queue;
38}; 44};
39 45
40struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp, 46int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
41 union perf_event *event); 47 struct perf_sample *sample, u64 file_offset);
42void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event); 48void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
43int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, 49int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
44 enum oe_flush how); 50void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);
45void ordered_events__init(struct ordered_events *oe);
46void ordered_events__free(struct ordered_events *oe); 51void ordered_events__free(struct ordered_events *oe);
47 52
48static inline 53static inline
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 7f8ec6ce2823..be0655388b38 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -20,11 +20,6 @@
20 20
21#define MAX_NAME_LEN 100 21#define MAX_NAME_LEN 100
22 22
23struct event_symbol {
24 const char *symbol;
25 const char *alias;
26};
27
28#ifdef PARSER_DEBUG 23#ifdef PARSER_DEBUG
29extern int parse_events_debug; 24extern int parse_events_debug;
30#endif 25#endif
@@ -39,7 +34,7 @@ static struct perf_pmu_event_symbol *perf_pmu_events_list;
39 */ 34 */
40static int perf_pmu_events_list_num; 35static int perf_pmu_events_list_num;
41 36
42static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 37struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
43 [PERF_COUNT_HW_CPU_CYCLES] = { 38 [PERF_COUNT_HW_CPU_CYCLES] = {
44 .symbol = "cpu-cycles", 39 .symbol = "cpu-cycles",
45 .alias = "cycles", 40 .alias = "cycles",
@@ -82,7 +77,7 @@ static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
82 }, 77 },
83}; 78};
84 79
85static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { 80struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
86 [PERF_COUNT_SW_CPU_CLOCK] = { 81 [PERF_COUNT_SW_CPU_CLOCK] = {
87 .symbol = "cpu-clock", 82 .symbol = "cpu-clock",
88 .alias = "", 83 .alias = "",
@@ -175,9 +170,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
175 char evt_path[MAXPATHLEN]; 170 char evt_path[MAXPATHLEN];
176 char dir_path[MAXPATHLEN]; 171 char dir_path[MAXPATHLEN];
177 172
178 if (debugfs_valid_mountpoint(tracing_events_path))
179 return NULL;
180
181 sys_dir = opendir(tracing_events_path); 173 sys_dir = opendir(tracing_events_path);
182 if (!sys_dir) 174 if (!sys_dir)
183 return NULL; 175 return NULL;
@@ -473,12 +465,6 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
473int parse_events_add_tracepoint(struct list_head *list, int *idx, 465int parse_events_add_tracepoint(struct list_head *list, int *idx,
474 char *sys, char *event) 466 char *sys, char *event)
475{ 467{
476 int ret;
477
478 ret = debugfs_valid_mountpoint(tracing_events_path);
479 if (ret)
480 return ret;
481
482 if (strpbrk(sys, "*?")) 468 if (strpbrk(sys, "*?"))
483 return add_tracepoint_multi_sys(list, idx, sys, event); 469 return add_tracepoint_multi_sys(list, idx, sys, event);
484 else 470 else
@@ -723,6 +709,7 @@ struct event_modifier {
723 int eh; 709 int eh;
724 int eH; 710 int eH;
725 int eG; 711 int eG;
712 int eI;
726 int precise; 713 int precise;
727 int exclude_GH; 714 int exclude_GH;
728 int sample_read; 715 int sample_read;
@@ -737,6 +724,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
737 int eh = evsel ? evsel->attr.exclude_hv : 0; 724 int eh = evsel ? evsel->attr.exclude_hv : 0;
738 int eH = evsel ? evsel->attr.exclude_host : 0; 725 int eH = evsel ? evsel->attr.exclude_host : 0;
739 int eG = evsel ? evsel->attr.exclude_guest : 0; 726 int eG = evsel ? evsel->attr.exclude_guest : 0;
727 int eI = evsel ? evsel->attr.exclude_idle : 0;
740 int precise = evsel ? evsel->attr.precise_ip : 0; 728 int precise = evsel ? evsel->attr.precise_ip : 0;
741 int sample_read = 0; 729 int sample_read = 0;
742 int pinned = evsel ? evsel->attr.pinned : 0; 730 int pinned = evsel ? evsel->attr.pinned : 0;
@@ -767,6 +755,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
767 if (!exclude_GH) 755 if (!exclude_GH)
768 exclude_GH = eG = eH = 1; 756 exclude_GH = eG = eH = 1;
769 eH = 0; 757 eH = 0;
758 } else if (*str == 'I') {
759 eI = 1;
770 } else if (*str == 'p') { 760 } else if (*str == 'p') {
771 precise++; 761 precise++;
772 /* use of precise requires exclude_guest */ 762 /* use of precise requires exclude_guest */
@@ -800,6 +790,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
800 mod->eh = eh; 790 mod->eh = eh;
801 mod->eH = eH; 791 mod->eH = eH;
802 mod->eG = eG; 792 mod->eG = eG;
793 mod->eI = eI;
803 mod->precise = precise; 794 mod->precise = precise;
804 mod->exclude_GH = exclude_GH; 795 mod->exclude_GH = exclude_GH;
805 mod->sample_read = sample_read; 796 mod->sample_read = sample_read;
@@ -817,7 +808,7 @@ static int check_modifier(char *str)
817 char *p = str; 808 char *p = str;
818 809
819 /* The sizeof includes 0 byte as well. */ 810 /* The sizeof includes 0 byte as well. */
820 if (strlen(str) > (sizeof("ukhGHpppSD") - 1)) 811 if (strlen(str) > (sizeof("ukhGHpppSDI") - 1))
821 return -1; 812 return -1;
822 813
823 while (*p) { 814 while (*p) {
@@ -853,6 +844,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
853 evsel->attr.precise_ip = mod.precise; 844 evsel->attr.precise_ip = mod.precise;
854 evsel->attr.exclude_host = mod.eH; 845 evsel->attr.exclude_host = mod.eH;
855 evsel->attr.exclude_guest = mod.eG; 846 evsel->attr.exclude_guest = mod.eG;
847 evsel->attr.exclude_idle = mod.eI;
856 evsel->exclude_GH = mod.exclude_GH; 848 evsel->exclude_GH = mod.exclude_GH;
857 evsel->sample_read = mod.sample_read; 849 evsel->sample_read = mod.sample_read;
858 850
@@ -1098,6 +1090,14 @@ static const char * const event_type_descriptors[] = {
1098 "Hardware breakpoint", 1090 "Hardware breakpoint",
1099}; 1091};
1100 1092
1093static int cmp_string(const void *a, const void *b)
1094{
1095 const char * const *as = a;
1096 const char * const *bs = b;
1097
1098 return strcmp(*as, *bs);
1099}
1100
1101/* 1101/*
1102 * Print the events from <debugfs_mount_point>/tracing/events 1102 * Print the events from <debugfs_mount_point>/tracing/events
1103 */ 1103 */
@@ -1109,18 +1109,21 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1109 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1109 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1110 char evt_path[MAXPATHLEN]; 1110 char evt_path[MAXPATHLEN];
1111 char dir_path[MAXPATHLEN]; 1111 char dir_path[MAXPATHLEN];
1112 char sbuf[STRERR_BUFSIZE]; 1112 char **evt_list = NULL;
1113 1113 unsigned int evt_i = 0, evt_num = 0;
1114 if (debugfs_valid_mountpoint(tracing_events_path)) { 1114 bool evt_num_known = false;
1115 printf(" [ Tracepoints not available: %s ]\n",
1116 strerror_r(errno, sbuf, sizeof(sbuf)));
1117 return;
1118 }
1119 1115
1116restart:
1120 sys_dir = opendir(tracing_events_path); 1117 sys_dir = opendir(tracing_events_path);
1121 if (!sys_dir) 1118 if (!sys_dir)
1122 return; 1119 return;
1123 1120
1121 if (evt_num_known) {
1122 evt_list = zalloc(sizeof(char *) * evt_num);
1123 if (!evt_list)
1124 goto out_close_sys_dir;
1125 }
1126
1124 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1127 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
1125 if (subsys_glob != NULL && 1128 if (subsys_glob != NULL &&
1126 !strglobmatch(sys_dirent.d_name, subsys_glob)) 1129 !strglobmatch(sys_dirent.d_name, subsys_glob))
@@ -1137,19 +1140,56 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1137 !strglobmatch(evt_dirent.d_name, event_glob)) 1140 !strglobmatch(evt_dirent.d_name, event_glob))
1138 continue; 1141 continue;
1139 1142
1140 if (name_only) { 1143 if (!evt_num_known) {
1141 printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name); 1144 evt_num++;
1142 continue; 1145 continue;
1143 } 1146 }
1144 1147
1145 snprintf(evt_path, MAXPATHLEN, "%s:%s", 1148 snprintf(evt_path, MAXPATHLEN, "%s:%s",
1146 sys_dirent.d_name, evt_dirent.d_name); 1149 sys_dirent.d_name, evt_dirent.d_name);
1147 printf(" %-50s [%s]\n", evt_path, 1150
1148 event_type_descriptors[PERF_TYPE_TRACEPOINT]); 1151 evt_list[evt_i] = strdup(evt_path);
1152 if (evt_list[evt_i] == NULL)
1153 goto out_close_evt_dir;
1154 evt_i++;
1149 } 1155 }
1150 closedir(evt_dir); 1156 closedir(evt_dir);
1151 } 1157 }
1152 closedir(sys_dir); 1158 closedir(sys_dir);
1159
1160 if (!evt_num_known) {
1161 evt_num_known = true;
1162 goto restart;
1163 }
1164 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1165 evt_i = 0;
1166 while (evt_i < evt_num) {
1167 if (name_only) {
1168 printf("%s ", evt_list[evt_i++]);
1169 continue;
1170 }
1171 printf(" %-50s [%s]\n", evt_list[evt_i++],
1172 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1173 }
1174 if (evt_num)
1175 printf("\n");
1176
1177out_free:
1178 evt_num = evt_i;
1179 for (evt_i = 0; evt_i < evt_num; evt_i++)
1180 zfree(&evt_list[evt_i]);
1181 zfree(&evt_list);
1182 return;
1183
1184out_close_evt_dir:
1185 closedir(evt_dir);
1186out_close_sys_dir:
1187 closedir(sys_dir);
1188
1189 printf("FATAL: not enough memory to print %s\n",
1190 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1191 if (evt_list)
1192 goto out_free;
1153} 1193}
1154 1194
1155/* 1195/*
@@ -1163,9 +1203,6 @@ int is_valid_tracepoint(const char *event_string)
1163 char evt_path[MAXPATHLEN]; 1203 char evt_path[MAXPATHLEN];
1164 char dir_path[MAXPATHLEN]; 1204 char dir_path[MAXPATHLEN];
1165 1205
1166 if (debugfs_valid_mountpoint(tracing_events_path))
1167 return 0;
1168
1169 sys_dir = opendir(tracing_events_path); 1206 sys_dir = opendir(tracing_events_path);
1170 if (!sys_dir) 1207 if (!sys_dir)
1171 return 0; 1208 return 0;
@@ -1233,38 +1270,19 @@ static bool is_event_supported(u8 type, unsigned config)
1233 return ret; 1270 return ret;
1234} 1271}
1235 1272
1236static void __print_events_type(u8 type, struct event_symbol *syms,
1237 unsigned max)
1238{
1239 char name[64];
1240 unsigned i;
1241
1242 for (i = 0; i < max ; i++, syms++) {
1243 if (!is_event_supported(type, i))
1244 continue;
1245
1246 if (strlen(syms->alias))
1247 snprintf(name, sizeof(name), "%s OR %s",
1248 syms->symbol, syms->alias);
1249 else
1250 snprintf(name, sizeof(name), "%s", syms->symbol);
1251
1252 printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
1253 }
1254}
1255
1256void print_events_type(u8 type)
1257{
1258 if (type == PERF_TYPE_SOFTWARE)
1259 __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
1260 else
1261 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
1262}
1263
1264int print_hwcache_events(const char *event_glob, bool name_only) 1273int print_hwcache_events(const char *event_glob, bool name_only)
1265{ 1274{
1266 unsigned int type, op, i, printed = 0; 1275 unsigned int type, op, i, evt_i = 0, evt_num = 0;
1267 char name[64]; 1276 char name[64];
1277 char **evt_list = NULL;
1278 bool evt_num_known = false;
1279
1280restart:
1281 if (evt_num_known) {
1282 evt_list = zalloc(sizeof(char *) * evt_num);
1283 if (!evt_list)
1284 goto out_enomem;
1285 }
1268 1286
1269 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 1287 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1270 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 1288 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
@@ -1282,27 +1300,66 @@ int print_hwcache_events(const char *event_glob, bool name_only)
1282 type | (op << 8) | (i << 16))) 1300 type | (op << 8) | (i << 16)))
1283 continue; 1301 continue;
1284 1302
1285 if (name_only) 1303 if (!evt_num_known) {
1286 printf("%s ", name); 1304 evt_num++;
1287 else 1305 continue;
1288 printf(" %-50s [%s]\n", name, 1306 }
1289 event_type_descriptors[PERF_TYPE_HW_CACHE]); 1307
1290 ++printed; 1308 evt_list[evt_i] = strdup(name);
1309 if (evt_list[evt_i] == NULL)
1310 goto out_enomem;
1311 evt_i++;
1291 } 1312 }
1292 } 1313 }
1293 } 1314 }
1294 1315
1295 if (printed) 1316 if (!evt_num_known) {
1317 evt_num_known = true;
1318 goto restart;
1319 }
1320 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1321 evt_i = 0;
1322 while (evt_i < evt_num) {
1323 if (name_only) {
1324 printf("%s ", evt_list[evt_i++]);
1325 continue;
1326 }
1327 printf(" %-50s [%s]\n", evt_list[evt_i++],
1328 event_type_descriptors[PERF_TYPE_HW_CACHE]);
1329 }
1330 if (evt_num)
1296 printf("\n"); 1331 printf("\n");
1297 return printed; 1332
1333out_free:
1334 evt_num = evt_i;
1335 for (evt_i = 0; evt_i < evt_num; evt_i++)
1336 zfree(&evt_list[evt_i]);
1337 zfree(&evt_list);
1338 return evt_num;
1339
1340out_enomem:
1341 printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
1342 if (evt_list)
1343 goto out_free;
1344 return evt_num;
1298} 1345}
1299 1346
1300static void print_symbol_events(const char *event_glob, unsigned type, 1347void print_symbol_events(const char *event_glob, unsigned type,
1301 struct event_symbol *syms, unsigned max, 1348 struct event_symbol *syms, unsigned max,
1302 bool name_only) 1349 bool name_only)
1303{ 1350{
1304 unsigned i, printed = 0; 1351 unsigned int i, evt_i = 0, evt_num = 0;
1305 char name[MAX_NAME_LEN]; 1352 char name[MAX_NAME_LEN];
1353 char **evt_list = NULL;
1354 bool evt_num_known = false;
1355
1356restart:
1357 if (evt_num_known) {
1358 evt_list = zalloc(sizeof(char *) * evt_num);
1359 if (!evt_list)
1360 goto out_enomem;
1361 syms -= max;
1362 }
1306 1363
1307 for (i = 0; i < max; i++, syms++) { 1364 for (i = 0; i < max; i++, syms++) {
1308 1365
@@ -1314,23 +1371,49 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1314 if (!is_event_supported(type, i)) 1371 if (!is_event_supported(type, i))
1315 continue; 1372 continue;
1316 1373
1317 if (name_only) { 1374 if (!evt_num_known) {
1318 printf("%s ", syms->symbol); 1375 evt_num++;
1319 continue; 1376 continue;
1320 } 1377 }
1321 1378
1322 if (strlen(syms->alias)) 1379 if (!name_only && strlen(syms->alias))
1323 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 1380 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
1324 else 1381 else
1325 strncpy(name, syms->symbol, MAX_NAME_LEN); 1382 strncpy(name, syms->symbol, MAX_NAME_LEN);
1326 1383
1327 printf(" %-50s [%s]\n", name, event_type_descriptors[type]); 1384 evt_list[evt_i] = strdup(name);
1328 1385 if (evt_list[evt_i] == NULL)
1329 printed++; 1386 goto out_enomem;
1387 evt_i++;
1330 } 1388 }
1331 1389
1332 if (printed) 1390 if (!evt_num_known) {
1391 evt_num_known = true;
1392 goto restart;
1393 }
1394 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1395 evt_i = 0;
1396 while (evt_i < evt_num) {
1397 if (name_only) {
1398 printf("%s ", evt_list[evt_i++]);
1399 continue;
1400 }
1401 printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
1402 }
1403 if (evt_num)
1333 printf("\n"); 1404 printf("\n");
1405
1406out_free:
1407 evt_num = evt_i;
1408 for (evt_i = 0; evt_i < evt_num; evt_i++)
1409 zfree(&evt_list[evt_i]);
1410 zfree(&evt_list);
1411 return;
1412
1413out_enomem:
1414 printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
1415 if (evt_list)
1416 goto out_free;
1334} 1417}
1335 1418
1336/* 1419/*
@@ -1338,11 +1421,6 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1338 */ 1421 */
1339void print_events(const char *event_glob, bool name_only) 1422void print_events(const char *event_glob, bool name_only)
1340{ 1423{
1341 if (!name_only) {
1342 printf("\n");
1343 printf("List of pre-defined events (to be used in -e):\n");
1344 }
1345
1346 print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 1424 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
1347 event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 1425 event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
1348 1426
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ff6e1fa4111e..52a2dda4f954 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -116,12 +116,21 @@ void parse_events_update_lists(struct list_head *list_event,
116void parse_events_error(void *data, void *scanner, char const *msg); 116void parse_events_error(void *data, void *scanner, char const *msg);
117 117
118void print_events(const char *event_glob, bool name_only); 118void print_events(const char *event_glob, bool name_only);
119void print_events_type(u8 type); 119
120struct event_symbol {
121 const char *symbol;
122 const char *alias;
123};
124extern struct event_symbol event_symbols_hw[];
125extern struct event_symbol event_symbols_sw[];
126void print_symbol_events(const char *event_glob, unsigned type,
127 struct event_symbol *syms, unsigned max,
128 bool name_only);
120void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 129void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
121 bool name_only); 130 bool name_only);
122int print_hwcache_events(const char *event_glob, bool name_only); 131int print_hwcache_events(const char *event_glob, bool name_only);
123extern int is_valid_tracepoint(const char *event_string); 132extern int is_valid_tracepoint(const char *event_string);
124 133
125extern int valid_debugfs_mount(const char *debugfs); 134int valid_event_mount(const char *eventfs);
126 135
127#endif /* __PERF_PARSE_EVENTS_H */ 136#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 94eacb6c1ef7..8895cf3132ab 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -101,7 +101,7 @@ num_raw_hex [a-fA-F0-9]+
101name [a-zA-Z_*?][a-zA-Z0-9_*?]* 101name [a-zA-Z_*?][a-zA-Z0-9_*?]*
102name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* 102name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]*
103/* If you add a modifier you need to update check_modifier() */ 103/* If you add a modifier you need to update check_modifier() */
104modifier_event [ukhpGHSD]+ 104modifier_event [ukhpGHSDI]+
105modifier_bp [rwx]{1,3} 105modifier_bp [rwx]{1,3}
106 106
107%% 107%%
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 4a015f77e2b5..01626be2a8eb 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -37,6 +37,7 @@ static int get_value(struct parse_opt_ctx_t *p,
37{ 37{
38 const char *s, *arg = NULL; 38 const char *s, *arg = NULL;
39 const int unset = flags & OPT_UNSET; 39 const int unset = flags & OPT_UNSET;
40 int err;
40 41
41 if (unset && p->opt) 42 if (unset && p->opt)
42 return opterror(opt, "takes no value", flags); 43 return opterror(opt, "takes no value", flags);
@@ -114,13 +115,29 @@ static int get_value(struct parse_opt_ctx_t *p,
114 return 0; 115 return 0;
115 116
116 case OPTION_STRING: 117 case OPTION_STRING:
118 err = 0;
117 if (unset) 119 if (unset)
118 *(const char **)opt->value = NULL; 120 *(const char **)opt->value = NULL;
119 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) 121 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
120 *(const char **)opt->value = (const char *)opt->defval; 122 *(const char **)opt->value = (const char *)opt->defval;
121 else 123 else
122 return get_arg(p, opt, flags, (const char **)opt->value); 124 err = get_arg(p, opt, flags, (const char **)opt->value);
123 return 0; 125
126 /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
127 if (opt->flags & PARSE_OPT_NOEMPTY) {
128 const char *val = *(const char **)opt->value;
129
130 if (!val)
131 return err;
132
133 /* Similar to unset if we are given an empty string. */
134 if (val[0] == '\0') {
135 *(const char **)opt->value = NULL;
136 return 0;
137 }
138 }
139
140 return err;
124 141
125 case OPTION_CALLBACK: 142 case OPTION_CALLBACK:
126 if (unset) 143 if (unset)
@@ -505,13 +522,18 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
505 break; 522 break;
506 case PARSE_OPT_LIST_OPTS: 523 case PARSE_OPT_LIST_OPTS:
507 while (options->type != OPTION_END) { 524 while (options->type != OPTION_END) {
508 printf("--%s ", options->long_name); 525 if (options->long_name)
526 printf("--%s ", options->long_name);
509 options++; 527 options++;
510 } 528 }
529 putchar('\n');
511 exit(130); 530 exit(130);
512 case PARSE_OPT_LIST_SUBCMDS: 531 case PARSE_OPT_LIST_SUBCMDS:
513 for (int i = 0; subcommands[i]; i++) 532 if (subcommands) {
514 printf("%s ", subcommands[i]); 533 for (int i = 0; subcommands[i]; i++)
534 printf("%s ", subcommands[i]);
535 }
536 putchar('\n');
515 exit(130); 537 exit(130);
516 default: /* PARSE_OPT_UNKNOWN */ 538 default: /* PARSE_OPT_UNKNOWN */
517 if (ctx.argv[0][1] == '-') { 539 if (ctx.argv[0][1] == '-') {
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 97b153fb4999..59561fd86278 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -40,6 +40,7 @@ enum parse_opt_option_flags {
40 PARSE_OPT_LASTARG_DEFAULT = 16, 40 PARSE_OPT_LASTARG_DEFAULT = 16,
41 PARSE_OPT_DISABLED = 32, 41 PARSE_OPT_DISABLED = 32,
42 PARSE_OPT_EXCLUSIVE = 64, 42 PARSE_OPT_EXCLUSIVE = 64,
43 PARSE_OPT_NOEMPTY = 128,
43}; 44};
44 45
45struct option; 46struct option;
@@ -122,6 +123,7 @@ struct option {
122#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } 123#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
123#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } 124#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
124#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } 125#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
126#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
125#define OPT_DATE(s, l, v, h) \ 127#define OPT_DATE(s, l, v, h) \
126 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } 128 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
127#define OPT_CALLBACK(s, l, v, a, h, f) \ 129#define OPT_CALLBACK(s, l, v, a, h, f) \
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 919937eb0be2..d8bb616ff57c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -41,6 +41,7 @@
41#include "symbol.h" 41#include "symbol.h"
42#include "thread.h" 42#include "thread.h"
43#include <api/fs/debugfs.h> 43#include <api/fs/debugfs.h>
44#include <api/fs/tracefs.h>
44#include "trace-event.h" /* For __maybe_unused */ 45#include "trace-event.h" /* For __maybe_unused */
45#include "probe-event.h" 46#include "probe-event.h"
46#include "probe-finder.h" 47#include "probe-finder.h"
@@ -79,6 +80,7 @@ static int init_symbol_maps(bool user_only)
79 int ret; 80 int ret;
80 81
81 symbol_conf.sort_by_name = true; 82 symbol_conf.sort_by_name = true;
83 symbol_conf.allow_aliases = true;
82 ret = symbol__init(NULL); 84 ret = symbol__init(NULL);
83 if (ret < 0) { 85 if (ret < 0) {
84 pr_debug("Failed to init symbol map.\n"); 86 pr_debug("Failed to init symbol map.\n");
@@ -133,6 +135,8 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
133 return NULL; 135 return NULL;
134 136
135 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); 137 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
138 if (!kmap)
139 return NULL;
136 return kmap->ref_reloc_sym; 140 return kmap->ref_reloc_sym;
137} 141}
138 142
@@ -150,7 +154,7 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
150 sym = __find_kernel_function_by_name(name, &map); 154 sym = __find_kernel_function_by_name(name, &map);
151 if (sym) 155 if (sym)
152 return map->unmap_ip(map, sym->start) - 156 return map->unmap_ip(map, sym->start) -
153 (reloc) ? 0 : map->reloc; 157 ((reloc) ? 0 : map->reloc);
154 } 158 }
155 return 0; 159 return 0;
156} 160}
@@ -177,6 +181,25 @@ static struct map *kernel_get_module_map(const char *module)
177 return NULL; 181 return NULL;
178} 182}
179 183
184static struct map *get_target_map(const char *target, bool user)
185{
186 /* Init maps of given executable or kernel */
187 if (user)
188 return dso__new_map(target);
189 else
190 return kernel_get_module_map(target);
191}
192
193static void put_target_map(struct map *map, bool user)
194{
195 if (map && user) {
196 /* Only the user map needs to be released */
197 dso__delete(map->dso);
198 map__delete(map);
199 }
200}
201
202
180static struct dso *kernel_get_module_dso(const char *module) 203static struct dso *kernel_get_module_dso(const char *module)
181{ 204{
182 struct dso *dso; 205 struct dso *dso;
@@ -248,6 +271,13 @@ out:
248 return ret; 271 return ret;
249} 272}
250 273
274static void clear_perf_probe_point(struct perf_probe_point *pp)
275{
276 free(pp->file);
277 free(pp->function);
278 free(pp->lazy_line);
279}
280
251static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) 281static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
252{ 282{
253 int i; 283 int i;
@@ -257,6 +287,104 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
257} 287}
258 288
259#ifdef HAVE_DWARF_SUPPORT 289#ifdef HAVE_DWARF_SUPPORT
290/*
291 * Some binaries like glibc have special symbols which are on the symbol
292 * table, but not in the debuginfo. If we can find the address of the
293 * symbol from map, we can translate the address back to the probe point.
294 */
295static int find_alternative_probe_point(struct debuginfo *dinfo,
296 struct perf_probe_point *pp,
297 struct perf_probe_point *result,
298 const char *target, bool uprobes)
299{
300 struct map *map = NULL;
301 struct symbol *sym;
302 u64 address = 0;
303 int ret = -ENOENT;
304
305 /* This can work only for function-name based one */
306 if (!pp->function || pp->file)
307 return -ENOTSUP;
308
309 map = get_target_map(target, uprobes);
310 if (!map)
311 return -EINVAL;
312
313 /* Find the address of given function */
314 map__for_each_symbol_by_name(map, pp->function, sym) {
315 if (uprobes)
316 address = sym->start;
317 else
318 address = map->unmap_ip(map, sym->start);
319 break;
320 }
321 if (!address) {
322 ret = -ENOENT;
323 goto out;
324 }
325 pr_debug("Symbol %s address found : %" PRIx64 "\n",
326 pp->function, address);
327
328 ret = debuginfo__find_probe_point(dinfo, (unsigned long)address,
329 result);
330 if (ret <= 0)
331 ret = (!ret) ? -ENOENT : ret;
332 else {
333 result->offset += pp->offset;
334 result->line += pp->line;
335 result->retprobe = pp->retprobe;
336 ret = 0;
337 }
338
339out:
340 put_target_map(map, uprobes);
341 return ret;
342
343}
344
345static int get_alternative_probe_event(struct debuginfo *dinfo,
346 struct perf_probe_event *pev,
347 struct perf_probe_point *tmp,
348 const char *target)
349{
350 int ret;
351
352 memcpy(tmp, &pev->point, sizeof(*tmp));
353 memset(&pev->point, 0, sizeof(pev->point));
354 ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
355 target, pev->uprobes);
356 if (ret < 0)
357 memcpy(&pev->point, tmp, sizeof(*tmp));
358
359 return ret;
360}
361
362static int get_alternative_line_range(struct debuginfo *dinfo,
363 struct line_range *lr,
364 const char *target, bool user)
365{
366 struct perf_probe_point pp = { .function = lr->function,
367 .file = lr->file,
368 .line = lr->start };
369 struct perf_probe_point result;
370 int ret, len = 0;
371
372 memset(&result, 0, sizeof(result));
373
374 if (lr->end != INT_MAX)
375 len = lr->end - lr->start;
376 ret = find_alternative_probe_point(dinfo, &pp, &result,
377 target, user);
378 if (!ret) {
379 lr->function = result.function;
380 lr->file = result.file;
381 lr->start = result.line;
382 if (lr->end != INT_MAX)
383 lr->end = lr->start + len;
384 clear_perf_probe_point(&pp);
385 }
386 return ret;
387}
260 388
261/* Open new debuginfo of given module */ 389/* Open new debuginfo of given module */
262static struct debuginfo *open_debuginfo(const char *module, bool silent) 390static struct debuginfo *open_debuginfo(const char *module, bool silent)
@@ -465,6 +593,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
465 int max_tevs, const char *target) 593 int max_tevs, const char *target)
466{ 594{
467 bool need_dwarf = perf_probe_event_need_dwarf(pev); 595 bool need_dwarf = perf_probe_event_need_dwarf(pev);
596 struct perf_probe_point tmp;
468 struct debuginfo *dinfo; 597 struct debuginfo *dinfo;
469 int ntevs, ret = 0; 598 int ntevs, ret = 0;
470 599
@@ -481,6 +610,20 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
481 /* Searching trace events corresponding to a probe event */ 610 /* Searching trace events corresponding to a probe event */
482 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); 611 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
483 612
613 if (ntevs == 0) { /* Not found, retry with an alternative */
614 ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
615 if (!ret) {
616 ntevs = debuginfo__find_trace_events(dinfo, pev,
617 tevs, max_tevs);
618 /*
619 * Write back to the original probe_event for
620 * setting appropriate (user given) event name
621 */
622 clear_perf_probe_point(&pev->point);
623 memcpy(&pev->point, &tmp, sizeof(tmp));
624 }
625 }
626
484 debuginfo__delete(dinfo); 627 debuginfo__delete(dinfo);
485 628
486 if (ntevs > 0) { /* Succeeded to find trace events */ 629 if (ntevs > 0) { /* Succeeded to find trace events */
@@ -495,11 +638,9 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
495 } 638 }
496 639
497 if (ntevs == 0) { /* No error but failed to find probe point. */ 640 if (ntevs == 0) { /* No error but failed to find probe point. */
498 pr_warning("Probe point '%s' not found in debuginfo.\n", 641 pr_warning("Probe point '%s' not found.\n",
499 synthesize_perf_probe_point(&pev->point)); 642 synthesize_perf_probe_point(&pev->point));
500 if (need_dwarf) 643 return -ENOENT;
501 return -ENOENT;
502 return 0;
503 } 644 }
504 /* Error path : ntevs < 0 */ 645 /* Error path : ntevs < 0 */
505 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 646 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
@@ -514,63 +655,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
514 return ntevs; 655 return ntevs;
515} 656}
516 657
517/*
518 * Find a src file from a DWARF tag path. Prepend optional source path prefix
519 * and chop off leading directories that do not exist. Result is passed back as
520 * a newly allocated path on success.
521 * Return 0 if file was found and readable, -errno otherwise.
522 */
523static int get_real_path(const char *raw_path, const char *comp_dir,
524 char **new_path)
525{
526 const char *prefix = symbol_conf.source_prefix;
527
528 if (!prefix) {
529 if (raw_path[0] != '/' && comp_dir)
530 /* If not an absolute path, try to use comp_dir */
531 prefix = comp_dir;
532 else {
533 if (access(raw_path, R_OK) == 0) {
534 *new_path = strdup(raw_path);
535 return 0;
536 } else
537 return -errno;
538 }
539 }
540
541 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
542 if (!*new_path)
543 return -ENOMEM;
544
545 for (;;) {
546 sprintf(*new_path, "%s/%s", prefix, raw_path);
547
548 if (access(*new_path, R_OK) == 0)
549 return 0;
550
551 if (!symbol_conf.source_prefix)
552 /* In case of searching comp_dir, don't retry */
553 return -errno;
554
555 switch (errno) {
556 case ENAMETOOLONG:
557 case ENOENT:
558 case EROFS:
559 case EFAULT:
560 raw_path = strchr(++raw_path, '/');
561 if (!raw_path) {
562 zfree(new_path);
563 return -ENOENT;
564 }
565 continue;
566
567 default:
568 zfree(new_path);
569 return -errno;
570 }
571 }
572}
573
574#define LINEBUF_SIZE 256 658#define LINEBUF_SIZE 256
575#define NR_ADDITIONAL_LINES 2 659#define NR_ADDITIONAL_LINES 2
576 660
@@ -622,7 +706,8 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
622 * Show line-range always requires debuginfo to find source file and 706 * Show line-range always requires debuginfo to find source file and
623 * line number. 707 * line number.
624 */ 708 */
625static int __show_line_range(struct line_range *lr, const char *module) 709static int __show_line_range(struct line_range *lr, const char *module,
710 bool user)
626{ 711{
627 int l = 1; 712 int l = 1;
628 struct int_node *ln; 713 struct int_node *ln;
@@ -638,6 +723,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
638 return -ENOENT; 723 return -ENOENT;
639 724
640 ret = debuginfo__find_line_range(dinfo, lr); 725 ret = debuginfo__find_line_range(dinfo, lr);
726 if (!ret) { /* Not found, retry with an alternative */
727 ret = get_alternative_line_range(dinfo, lr, module, user);
728 if (!ret)
729 ret = debuginfo__find_line_range(dinfo, lr);
730 }
641 debuginfo__delete(dinfo); 731 debuginfo__delete(dinfo);
642 if (ret == 0 || ret == -ENOENT) { 732 if (ret == 0 || ret == -ENOENT) {
643 pr_warning("Specified source line is not found.\n"); 733 pr_warning("Specified source line is not found.\n");
@@ -650,7 +740,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
650 /* Convert source file path */ 740 /* Convert source file path */
651 tmp = lr->path; 741 tmp = lr->path;
652 ret = get_real_path(tmp, lr->comp_dir, &lr->path); 742 ret = get_real_path(tmp, lr->comp_dir, &lr->path);
653 free(tmp); /* Free old path */ 743
744 /* Free old path when new path is assigned */
745 if (tmp != lr->path)
746 free(tmp);
747
654 if (ret < 0) { 748 if (ret < 0) {
655 pr_warning("Failed to find source file path.\n"); 749 pr_warning("Failed to find source file path.\n");
656 return ret; 750 return ret;
@@ -707,7 +801,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
707 ret = init_symbol_maps(user); 801 ret = init_symbol_maps(user);
708 if (ret < 0) 802 if (ret < 0)
709 return ret; 803 return ret;
710 ret = __show_line_range(lr, module); 804 ret = __show_line_range(lr, module, user);
711 exit_symbol_maps(); 805 exit_symbol_maps();
712 806
713 return ret; 807 return ret;
@@ -716,12 +810,13 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
716static int show_available_vars_at(struct debuginfo *dinfo, 810static int show_available_vars_at(struct debuginfo *dinfo,
717 struct perf_probe_event *pev, 811 struct perf_probe_event *pev,
718 int max_vls, struct strfilter *_filter, 812 int max_vls, struct strfilter *_filter,
719 bool externs) 813 bool externs, const char *target)
720{ 814{
721 char *buf; 815 char *buf;
722 int ret, i, nvars; 816 int ret, i, nvars;
723 struct str_node *node; 817 struct str_node *node;
724 struct variable_list *vls = NULL, *vl; 818 struct variable_list *vls = NULL, *vl;
819 struct perf_probe_point tmp;
725 const char *var; 820 const char *var;
726 821
727 buf = synthesize_perf_probe_point(&pev->point); 822 buf = synthesize_perf_probe_point(&pev->point);
@@ -731,6 +826,15 @@ static int show_available_vars_at(struct debuginfo *dinfo,
731 826
732 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, 827 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
733 max_vls, externs); 828 max_vls, externs);
829 if (!ret) { /* Not found, retry with an alternative */
830 ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
831 if (!ret) {
832 ret = debuginfo__find_available_vars_at(dinfo, pev,
833 &vls, max_vls, externs);
834 /* Release the old probe_point */
835 clear_perf_probe_point(&tmp);
836 }
837 }
734 if (ret <= 0) { 838 if (ret <= 0) {
735 if (ret == 0 || ret == -ENOENT) { 839 if (ret == 0 || ret == -ENOENT) {
736 pr_err("Failed to find the address of %s\n", buf); 840 pr_err("Failed to find the address of %s\n", buf);
@@ -793,7 +897,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
793 897
794 for (i = 0; i < npevs && ret >= 0; i++) 898 for (i = 0; i < npevs && ret >= 0; i++)
795 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, 899 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
796 externs); 900 externs, module);
797 901
798 debuginfo__delete(dinfo); 902 debuginfo__delete(dinfo);
799out: 903out:
@@ -1739,15 +1843,13 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1739 1843
1740void clear_perf_probe_event(struct perf_probe_event *pev) 1844void clear_perf_probe_event(struct perf_probe_event *pev)
1741{ 1845{
1742 struct perf_probe_point *pp = &pev->point;
1743 struct perf_probe_arg_field *field, *next; 1846 struct perf_probe_arg_field *field, *next;
1744 int i; 1847 int i;
1745 1848
1746 free(pev->event); 1849 free(pev->event);
1747 free(pev->group); 1850 free(pev->group);
1748 free(pp->file); 1851 free(pev->target);
1749 free(pp->function); 1852 clear_perf_probe_point(&pev->point);
1750 free(pp->lazy_line);
1751 1853
1752 for (i = 0; i < pev->nargs; i++) { 1854 for (i = 0; i < pev->nargs; i++) {
1753 free(pev->args[i].name); 1855 free(pev->args[i].name);
@@ -1805,7 +1907,7 @@ static void print_open_warning(int err, bool is_kprobe)
1805 " - please rebuild kernel with %s.\n", 1907 " - please rebuild kernel with %s.\n",
1806 is_kprobe ? 'k' : 'u', config); 1908 is_kprobe ? 'k' : 'u', config);
1807 } else if (err == -ENOTSUP) 1909 } else if (err == -ENOTSUP)
1808 pr_warning("Debugfs is not mounted.\n"); 1910 pr_warning("Tracefs or debugfs is not mounted.\n");
1809 else 1911 else
1810 pr_warning("Failed to open %cprobe_events: %s\n", 1912 pr_warning("Failed to open %cprobe_events: %s\n",
1811 is_kprobe ? 'k' : 'u', 1913 is_kprobe ? 'k' : 'u',
@@ -1816,7 +1918,7 @@ static void print_both_open_warning(int kerr, int uerr)
1816{ 1918{
1817 /* Both kprobes and uprobes are disabled, warn it. */ 1919 /* Both kprobes and uprobes are disabled, warn it. */
1818 if (kerr == -ENOTSUP && uerr == -ENOTSUP) 1920 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1819 pr_warning("Debugfs is not mounted.\n"); 1921 pr_warning("Tracefs or debugfs is not mounted.\n");
1820 else if (kerr == -ENOENT && uerr == -ENOENT) 1922 else if (kerr == -ENOENT && uerr == -ENOENT)
1821 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS " 1923 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1822 "or/and CONFIG_UPROBE_EVENTS.\n"); 1924 "or/and CONFIG_UPROBE_EVENTS.\n");
@@ -1833,13 +1935,20 @@ static int open_probe_events(const char *trace_file, bool readwrite)
1833{ 1935{
1834 char buf[PATH_MAX]; 1936 char buf[PATH_MAX];
1835 const char *__debugfs; 1937 const char *__debugfs;
1938 const char *tracing_dir = "";
1836 int ret; 1939 int ret;
1837 1940
1838 __debugfs = debugfs_find_mountpoint(); 1941 __debugfs = tracefs_find_mountpoint();
1839 if (__debugfs == NULL) 1942 if (__debugfs == NULL) {
1840 return -ENOTSUP; 1943 tracing_dir = "tracing/";
1944
1945 __debugfs = debugfs_find_mountpoint();
1946 if (__debugfs == NULL)
1947 return -ENOTSUP;
1948 }
1841 1949
1842 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1950 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s",
1951 __debugfs, tracing_dir, trace_file);
1843 if (ret >= 0) { 1952 if (ret >= 0) {
1844 pr_debug("Opening %s write=%d\n", buf, readwrite); 1953 pr_debug("Opening %s write=%d\n", buf, readwrite);
1845 if (readwrite && !probe_event_dry_run) 1954 if (readwrite && !probe_event_dry_run)
@@ -1855,12 +1964,12 @@ static int open_probe_events(const char *trace_file, bool readwrite)
1855 1964
1856static int open_kprobe_events(bool readwrite) 1965static int open_kprobe_events(bool readwrite)
1857{ 1966{
1858 return open_probe_events("tracing/kprobe_events", readwrite); 1967 return open_probe_events("kprobe_events", readwrite);
1859} 1968}
1860 1969
1861static int open_uprobe_events(bool readwrite) 1970static int open_uprobe_events(bool readwrite)
1862{ 1971{
1863 return open_probe_events("tracing/uprobe_events", readwrite); 1972 return open_probe_events("uprobe_events", readwrite);
1864} 1973}
1865 1974
1866/* Get raw string list of current kprobe_events or uprobe_events */ 1975/* Get raw string list of current kprobe_events or uprobe_events */
@@ -1895,6 +2004,95 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1895 return sl; 2004 return sl;
1896} 2005}
1897 2006
2007struct kprobe_blacklist_node {
2008 struct list_head list;
2009 unsigned long start;
2010 unsigned long end;
2011 char *symbol;
2012};
2013
2014static void kprobe_blacklist__delete(struct list_head *blacklist)
2015{
2016 struct kprobe_blacklist_node *node;
2017
2018 while (!list_empty(blacklist)) {
2019 node = list_first_entry(blacklist,
2020 struct kprobe_blacklist_node, list);
2021 list_del(&node->list);
2022 free(node->symbol);
2023 free(node);
2024 }
2025}
2026
2027static int kprobe_blacklist__load(struct list_head *blacklist)
2028{
2029 struct kprobe_blacklist_node *node;
2030 const char *__debugfs = debugfs_find_mountpoint();
2031 char buf[PATH_MAX], *p;
2032 FILE *fp;
2033 int ret;
2034
2035 if (__debugfs == NULL)
2036 return -ENOTSUP;
2037
2038 ret = e_snprintf(buf, PATH_MAX, "%s/kprobes/blacklist", __debugfs);
2039 if (ret < 0)
2040 return ret;
2041
2042 fp = fopen(buf, "r");
2043 if (!fp)
2044 return -errno;
2045
2046 ret = 0;
2047 while (fgets(buf, PATH_MAX, fp)) {
2048 node = zalloc(sizeof(*node));
2049 if (!node) {
2050 ret = -ENOMEM;
2051 break;
2052 }
2053 INIT_LIST_HEAD(&node->list);
2054 list_add_tail(&node->list, blacklist);
2055 if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
2056 ret = -EINVAL;
2057 break;
2058 }
2059 p = strchr(buf, '\t');
2060 if (p) {
2061 p++;
2062 if (p[strlen(p) - 1] == '\n')
2063 p[strlen(p) - 1] = '\0';
2064 } else
2065 p = (char *)"unknown";
2066 node->symbol = strdup(p);
2067 if (!node->symbol) {
2068 ret = -ENOMEM;
2069 break;
2070 }
2071 pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
2072 node->start, node->end, node->symbol);
2073 ret++;
2074 }
2075 if (ret < 0)
2076 kprobe_blacklist__delete(blacklist);
2077 fclose(fp);
2078
2079 return ret;
2080}
2081
2082static struct kprobe_blacklist_node *
2083kprobe_blacklist__find_by_address(struct list_head *blacklist,
2084 unsigned long address)
2085{
2086 struct kprobe_blacklist_node *node;
2087
2088 list_for_each_entry(node, blacklist, list) {
2089 if (node->start <= address && address <= node->end)
2090 return node;
2091 }
2092
2093 return NULL;
2094}
2095
1898/* Show an event */ 2096/* Show an event */
1899static int show_perf_probe_event(struct perf_probe_event *pev, 2097static int show_perf_probe_event(struct perf_probe_event *pev,
1900 const char *module) 2098 const char *module)
@@ -2100,6 +2298,27 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2100 return ret; 2298 return ret;
2101} 2299}
2102 2300
2301/* Warn if the current kernel's uprobe implementation is old */
2302static void warn_uprobe_event_compat(struct probe_trace_event *tev)
2303{
2304 int i;
2305 char *buf = synthesize_probe_trace_command(tev);
2306
2307 /* Old uprobe event doesn't support memory dereference */
2308 if (!tev->uprobes || tev->nargs == 0 || !buf)
2309 goto out;
2310
2311 for (i = 0; i < tev->nargs; i++)
2312 if (strglobmatch(tev->args[i].value, "[$@+-]*")) {
2313 pr_warning("Please upgrade your kernel to at least "
2314 "3.14 to have access to feature %s\n",
2315 tev->args[i].value);
2316 break;
2317 }
2318out:
2319 free(buf);
2320}
2321
2103static int __add_probe_trace_events(struct perf_probe_event *pev, 2322static int __add_probe_trace_events(struct perf_probe_event *pev,
2104 struct probe_trace_event *tevs, 2323 struct probe_trace_event *tevs,
2105 int ntevs, bool allow_suffix) 2324 int ntevs, bool allow_suffix)
@@ -2109,6 +2328,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2109 char buf[64]; 2328 char buf[64];
2110 const char *event, *group; 2329 const char *event, *group;
2111 struct strlist *namelist; 2330 struct strlist *namelist;
2331 LIST_HEAD(blacklist);
2332 struct kprobe_blacklist_node *node;
2112 2333
2113 if (pev->uprobes) 2334 if (pev->uprobes)
2114 fd = open_uprobe_events(true); 2335 fd = open_uprobe_events(true);
@@ -2126,11 +2347,25 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2126 pr_debug("Failed to get current event list.\n"); 2347 pr_debug("Failed to get current event list.\n");
2127 return -EIO; 2348 return -EIO;
2128 } 2349 }
2350 /* Get kprobe blacklist if exists */
2351 if (!pev->uprobes) {
2352 ret = kprobe_blacklist__load(&blacklist);
2353 if (ret < 0)
2354 pr_debug("No kprobe blacklist support, ignored\n");
2355 }
2129 2356
2130 ret = 0; 2357 ret = 0;
2131 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2358 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2132 for (i = 0; i < ntevs; i++) { 2359 for (i = 0; i < ntevs; i++) {
2133 tev = &tevs[i]; 2360 tev = &tevs[i];
2361 /* Ensure that the address is NOT blacklisted */
2362 node = kprobe_blacklist__find_by_address(&blacklist,
2363 tev->point.address);
2364 if (node) {
2365 pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
2366 continue;
2367 }
2368
2134 if (pev->event) 2369 if (pev->event)
2135 event = pev->event; 2370 event = pev->event;
2136 else 2371 else
@@ -2180,14 +2415,18 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2180 */ 2415 */
2181 allow_suffix = true; 2416 allow_suffix = true;
2182 } 2417 }
2418 if (ret == -EINVAL && pev->uprobes)
2419 warn_uprobe_event_compat(tev);
2183 2420
2184 if (ret >= 0) { 2421 /* Note that it is possible to skip all events because of blacklist */
2422 if (ret >= 0 && tev->event) {
2185 /* Show how to use the event. */ 2423 /* Show how to use the event. */
2186 pr_info("\nYou can now use it in all perf tools, such as:\n\n"); 2424 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2187 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2425 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
2188 tev->event); 2426 tev->event);
2189 } 2427 }
2190 2428
2429 kprobe_blacklist__delete(&blacklist);
2191 strlist__delete(namelist); 2430 strlist__delete(namelist);
2192 close(fd); 2431 close(fd);
2193 return ret; 2432 return ret;
@@ -2199,8 +2438,7 @@ static int find_probe_functions(struct map *map, char *name)
2199 struct symbol *sym; 2438 struct symbol *sym;
2200 2439
2201 map__for_each_symbol_by_name(map, name, sym) { 2440 map__for_each_symbol_by_name(map, name, sym) {
2202 if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) 2441 found++;
2203 found++;
2204 } 2442 }
2205 2443
2206 return found; 2444 return found;
@@ -2218,7 +2456,6 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2218 int max_tevs, const char *target) 2456 int max_tevs, const char *target)
2219{ 2457{
2220 struct map *map = NULL; 2458 struct map *map = NULL;
2221 struct kmap *kmap = NULL;
2222 struct ref_reloc_sym *reloc_sym = NULL; 2459 struct ref_reloc_sym *reloc_sym = NULL;
2223 struct symbol *sym; 2460 struct symbol *sym;
2224 struct probe_trace_event *tev; 2461 struct probe_trace_event *tev;
@@ -2227,11 +2464,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2227 int num_matched_functions; 2464 int num_matched_functions;
2228 int ret, i; 2465 int ret, i;
2229 2466
2230 /* Init maps of given executable or kernel */ 2467 map = get_target_map(target, pev->uprobes);
2231 if (pev->uprobes)
2232 map = dso__new_map(target);
2233 else
2234 map = kernel_get_module_map(target);
2235 if (!map) { 2468 if (!map) {
2236 ret = -EINVAL; 2469 ret = -EINVAL;
2237 goto out; 2470 goto out;
@@ -2255,8 +2488,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2255 } 2488 }
2256 2489
2257 if (!pev->uprobes && !pp->retprobe) { 2490 if (!pev->uprobes && !pp->retprobe) {
2258 kmap = map__kmap(map); 2491 reloc_sym = kernel_get_ref_reloc_sym();
2259 reloc_sym = kmap->ref_reloc_sym;
2260 if (!reloc_sym) { 2492 if (!reloc_sym) {
2261 pr_warning("Relocated base symbol is not found!\n"); 2493 pr_warning("Relocated base symbol is not found!\n");
2262 ret = -EINVAL; 2494 ret = -EINVAL;
@@ -2324,11 +2556,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2324 } 2556 }
2325 2557
2326out: 2558out:
2327 if (map && pev->uprobes) { 2559 put_target_map(map, pev->uprobes);
2328 /* Only when using uprobe(exec) map needs to be released */
2329 dso__delete(map->dso);
2330 map__delete(map);
2331 }
2332 return ret; 2560 return ret;
2333 2561
2334nomem_out: 2562nomem_out:
@@ -2369,7 +2597,7 @@ struct __event_package {
2369}; 2597};
2370 2598
2371int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 2599int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2372 int max_tevs, const char *target, bool force_add) 2600 int max_tevs, bool force_add)
2373{ 2601{
2374 int i, j, ret; 2602 int i, j, ret;
2375 struct __event_package *pkgs; 2603 struct __event_package *pkgs;
@@ -2393,7 +2621,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2393 ret = convert_to_probe_trace_events(pkgs[i].pev, 2621 ret = convert_to_probe_trace_events(pkgs[i].pev,
2394 &pkgs[i].tevs, 2622 &pkgs[i].tevs,
2395 max_tevs, 2623 max_tevs,
2396 target); 2624 pkgs[i].pev->target);
2397 if (ret < 0) 2625 if (ret < 0)
2398 goto end; 2626 goto end;
2399 pkgs[i].ntevs = ret; 2627 pkgs[i].ntevs = ret;
@@ -2568,8 +2796,7 @@ static struct strfilter *available_func_filter;
2568static int filter_available_functions(struct map *map __maybe_unused, 2796static int filter_available_functions(struct map *map __maybe_unused,
2569 struct symbol *sym) 2797 struct symbol *sym)
2570{ 2798{
2571 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && 2799 if (strfilter__compare(available_func_filter, sym->name))
2572 strfilter__compare(available_func_filter, sym->name))
2573 return 0; 2800 return 0;
2574 return 1; 2801 return 1;
2575} 2802}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e01e9943139f..d6b783447be9 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -73,7 +73,8 @@ struct perf_probe_event {
73 char *group; /* Group name */ 73 char *group; /* Group name */
74 struct perf_probe_point point; /* Probe point */ 74 struct perf_probe_point point; /* Probe point */
75 int nargs; /* Number of arguments */ 75 int nargs; /* Number of arguments */
76 bool uprobes; 76 bool uprobes; /* Uprobe event flag */
77 char *target; /* Target binary */
77 struct perf_probe_arg *args; /* Arguments */ 78 struct perf_probe_arg *args; /* Arguments */
78}; 79};
79 80
@@ -124,8 +125,7 @@ extern int line_range__init(struct line_range *lr);
124extern const char *kernel_get_module_path(const char *module); 125extern const char *kernel_get_module_path(const char *module);
125 126
126extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 127extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
127 int max_probe_points, const char *module, 128 int max_probe_points, bool force_add);
128 bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist); 129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void); 130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module, 131extern int show_line_range(struct line_range *lr, const char *module,
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index b5247d777f0e..b5bf9d5efeaf 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -456,11 +456,12 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
456 return -EINVAL; 456 return -EINVAL;
457 } 457 }
458 if (field->name[0] == '[') { 458 if (field->name[0] == '[') {
459 pr_err("Semantic error: %s is not a pointor" 459 pr_err("Semantic error: %s is not a pointer"
460 " nor array.\n", varname); 460 " nor array.\n", varname);
461 return -EINVAL; 461 return -EINVAL;
462 } 462 }
463 if (field->ref) { 463 /* While prcessing unnamed field, we don't care about this */
464 if (field->ref && dwarf_diename(vr_die)) {
464 pr_err("Semantic error: %s must be referred by '.'\n", 465 pr_err("Semantic error: %s must be referred by '.'\n",
465 field->name); 466 field->name);
466 return -EINVAL; 467 return -EINVAL;
@@ -491,6 +492,11 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
491 } 492 }
492 ref->offset += (long)offs; 493 ref->offset += (long)offs;
493 494
495 /* If this member is unnamed, we need to reuse this field */
496 if (!dwarf_diename(die_mem))
497 return convert_variable_fields(die_mem, varname, field,
498 &ref, die_mem);
499
494next: 500next:
495 /* Converting next field */ 501 /* Converting next field */
496 if (field->next) 502 if (field->next)
@@ -849,11 +855,22 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
849static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) 855static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
850{ 856{
851 int ret = 0; 857 int ret = 0;
858 char *fpath;
852 859
853 if (intlist__empty(pf->lcache)) { 860 if (intlist__empty(pf->lcache)) {
861 const char *comp_dir;
862
863 comp_dir = cu_get_comp_dir(&pf->cu_die);
864 ret = get_real_path(pf->fname, comp_dir, &fpath);
865 if (ret < 0) {
866 pr_warning("Failed to find source file path.\n");
867 return ret;
868 }
869
854 /* Matching lazy line pattern */ 870 /* Matching lazy line pattern */
855 ret = find_lazy_match_lines(pf->lcache, pf->fname, 871 ret = find_lazy_match_lines(pf->lcache, fpath,
856 pf->pev->point.lazy_line); 872 pf->pev->point.lazy_line);
873 free(fpath);
857 if (ret <= 0) 874 if (ret <= 0)
858 return ret; 875 return ret;
859 } 876 }
@@ -915,17 +932,13 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
915 dwarf_decl_line(sp_die, &pf->lno); 932 dwarf_decl_line(sp_die, &pf->lno);
916 pf->lno += pp->line; 933 pf->lno += pp->line;
917 param->retval = find_probe_point_by_line(pf); 934 param->retval = find_probe_point_by_line(pf);
918 } else if (!dwarf_func_inline(sp_die)) { 935 } else if (die_is_func_instance(sp_die)) {
936 /* Instances always have the entry address */
937 dwarf_entrypc(sp_die, &pf->addr);
919 /* Real function */ 938 /* Real function */
920 if (pp->lazy_line) 939 if (pp->lazy_line)
921 param->retval = find_probe_point_lazy(sp_die, pf); 940 param->retval = find_probe_point_lazy(sp_die, pf);
922 else { 941 else {
923 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
924 pr_warning("Failed to get entry address of "
925 "%s.\n", dwarf_diename(sp_die));
926 param->retval = -ENOENT;
927 return DWARF_CB_ABORT;
928 }
929 pf->addr += pp->offset; 942 pf->addr += pp->offset;
930 /* TODO: Check the address in this function */ 943 /* TODO: Check the address in this function */
931 param->retval = call_probe_finder(sp_die, pf); 944 param->retval = call_probe_finder(sp_die, pf);
@@ -1053,7 +1066,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1053 if (pp->function) 1066 if (pp->function)
1054 ret = find_probe_point_by_func(pf); 1067 ret = find_probe_point_by_func(pf);
1055 else if (pp->lazy_line) 1068 else if (pp->lazy_line)
1056 ret = find_probe_point_lazy(NULL, pf); 1069 ret = find_probe_point_lazy(&pf->cu_die, pf);
1057 else { 1070 else {
1058 pf->lno = pp->line; 1071 pf->lno = pp->line;
1059 ret = find_probe_point_by_line(pf); 1072 ret = find_probe_point_by_line(pf);
@@ -1349,11 +1362,8 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1349 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1362 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1350 int baseline = 0, lineno = 0, ret = 0; 1363 int baseline = 0, lineno = 0, ret = 0;
1351 1364
1352 /* Adjust address with bias */
1353 addr += dbg->bias;
1354
1355 /* Find cu die */ 1365 /* Find cu die */
1356 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) { 1366 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
1357 pr_warning("Failed to find debug information for address %lx\n", 1367 pr_warning("Failed to find debug information for address %lx\n",
1358 addr); 1368 addr);
1359 ret = -EINVAL; 1369 ret = -EINVAL;
@@ -1536,7 +1546,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1536 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); 1546 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1537 lr->start = lf->lno_s; 1547 lr->start = lf->lno_s;
1538 lr->end = lf->lno_e; 1548 lr->end = lf->lno_e;
1539 if (dwarf_func_inline(sp_die)) 1549 if (!die_is_func_instance(sp_die))
1540 param->retval = die_walk_instances(sp_die, 1550 param->retval = die_walk_instances(sp_die,
1541 line_range_inline_cb, lf); 1551 line_range_inline_cb, lf);
1542 else 1552 else
@@ -1623,3 +1633,61 @@ found:
1623 return (ret < 0) ? ret : lf.found; 1633 return (ret < 0) ? ret : lf.found;
1624} 1634}
1625 1635
1636/*
1637 * Find a src file from a DWARF tag path. Prepend optional source path prefix
1638 * and chop off leading directories that do not exist. Result is passed back as
1639 * a newly allocated path on success.
1640 * Return 0 if file was found and readable, -errno otherwise.
1641 */
1642int get_real_path(const char *raw_path, const char *comp_dir,
1643 char **new_path)
1644{
1645 const char *prefix = symbol_conf.source_prefix;
1646
1647 if (!prefix) {
1648 if (raw_path[0] != '/' && comp_dir)
1649 /* If not an absolute path, try to use comp_dir */
1650 prefix = comp_dir;
1651 else {
1652 if (access(raw_path, R_OK) == 0) {
1653 *new_path = strdup(raw_path);
1654 return *new_path ? 0 : -ENOMEM;
1655 } else
1656 return -errno;
1657 }
1658 }
1659
1660 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
1661 if (!*new_path)
1662 return -ENOMEM;
1663
1664 for (;;) {
1665 sprintf(*new_path, "%s/%s", prefix, raw_path);
1666
1667 if (access(*new_path, R_OK) == 0)
1668 return 0;
1669
1670 if (!symbol_conf.source_prefix) {
1671 /* In case of searching comp_dir, don't retry */
1672 zfree(new_path);
1673 return -errno;
1674 }
1675
1676 switch (errno) {
1677 case ENAMETOOLONG:
1678 case ENOENT:
1679 case EROFS:
1680 case EFAULT:
1681 raw_path = strchr(++raw_path, '/');
1682 if (!raw_path) {
1683 zfree(new_path);
1684 return -ENOENT;
1685 }
1686 continue;
1687
1688 default:
1689 zfree(new_path);
1690 return -errno;
1691 }
1692 }
1693}
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 92590b2c7e1c..ebf8c8c81453 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -55,6 +55,10 @@ extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
55 struct variable_list **vls, 55 struct variable_list **vls,
56 int max_points, bool externs); 56 int max_points, bool externs);
57 57
58/* Find a src file from a DWARF tag path */
59int get_real_path(const char *raw_path, const char *comp_dir,
60 char **new_path);
61
58struct probe_finder { 62struct probe_finder {
59 struct perf_probe_event *pev; /* Target probe event */ 63 struct perf_probe_event *pev; /* Target probe event */
60 64
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 6c6a6953fa93..4d28624a1eca 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -17,6 +17,5 @@ util/xyarray.c
17util/cgroup.c 17util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/strlist.c 19util/strlist.c
20../lib/api/fs/fs.c
21util/trace-event.c 20util/trace-event.c
22../../lib/rbtree.c 21../../lib/rbtree.c
diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
new file mode 100644
index 000000000000..6516e220c247
--- /dev/null
+++ b/tools/perf/util/scripting-engines/Build
@@ -0,0 +1,6 @@
1libperf-$(CONFIG_LIBPERL) += trace-event-perl.o
2libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o
3
4CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default
5
6CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 22ebc46226e7..430b5d27828e 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -214,6 +214,11 @@ static void define_event_symbols(struct event_format *event,
214 define_event_symbols(event, ev_name, args->hex.field); 214 define_event_symbols(event, ev_name, args->hex.field);
215 define_event_symbols(event, ev_name, args->hex.size); 215 define_event_symbols(event, ev_name, args->hex.size);
216 break; 216 break;
217 case PRINT_INT_ARRAY:
218 define_event_symbols(event, ev_name, args->int_array.field);
219 define_event_symbols(event, ev_name, args->int_array.count);
220 define_event_symbols(event, ev_name, args->int_array.el_size);
221 break;
217 case PRINT_BSTRING: 222 case PRINT_BSTRING:
218 case PRINT_DYNAMIC_ARRAY: 223 case PRINT_DYNAMIC_ARRAY:
219 case PRINT_STRING: 224 case PRINT_STRING:
@@ -355,10 +360,9 @@ static void perl_process_event_generic(union perf_event *event,
355static void perl_process_event(union perf_event *event, 360static void perl_process_event(union perf_event *event,
356 struct perf_sample *sample, 361 struct perf_sample *sample,
357 struct perf_evsel *evsel, 362 struct perf_evsel *evsel,
358 struct thread *thread, 363 struct addr_location *al)
359 struct addr_location *al __maybe_unused)
360{ 364{
361 perl_process_tracepoint(sample, evsel, thread); 365 perl_process_tracepoint(sample, evsel, al->thread);
362 perl_process_event_generic(event, sample, evsel); 366 perl_process_event_generic(event, sample, evsel);
363} 367}
364 368
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 0c815a40a6e8..5544b8cdd1ee 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -231,6 +231,11 @@ static void define_event_symbols(struct event_format *event,
231 define_event_symbols(event, ev_name, args->hex.field); 231 define_event_symbols(event, ev_name, args->hex.field);
232 define_event_symbols(event, ev_name, args->hex.size); 232 define_event_symbols(event, ev_name, args->hex.size);
233 break; 233 break;
234 case PRINT_INT_ARRAY:
235 define_event_symbols(event, ev_name, args->int_array.field);
236 define_event_symbols(event, ev_name, args->int_array.count);
237 define_event_symbols(event, ev_name, args->int_array.el_size);
238 break;
234 case PRINT_STRING: 239 case PRINT_STRING:
235 break; 240 break;
236 case PRINT_TYPE: 241 case PRINT_TYPE:
@@ -376,7 +381,6 @@ exit:
376 381
377static void python_process_tracepoint(struct perf_sample *sample, 382static void python_process_tracepoint(struct perf_sample *sample,
378 struct perf_evsel *evsel, 383 struct perf_evsel *evsel,
379 struct thread *thread,
380 struct addr_location *al) 384 struct addr_location *al)
381{ 385{
382 struct event_format *event = evsel->tp_format; 386 struct event_format *event = evsel->tp_format;
@@ -390,7 +394,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
390 int cpu = sample->cpu; 394 int cpu = sample->cpu;
391 void *data = sample->raw_data; 395 void *data = sample->raw_data;
392 unsigned long long nsecs = sample->time; 396 unsigned long long nsecs = sample->time;
393 const char *comm = thread__comm_str(thread); 397 const char *comm = thread__comm_str(al->thread);
394 398
395 t = PyTuple_New(MAX_FIELDS); 399 t = PyTuple_New(MAX_FIELDS);
396 if (!t) 400 if (!t)
@@ -675,7 +679,7 @@ static int python_export_sample(struct db_export *dbe,
675 tuple_set_u64(t, 0, es->db_id); 679 tuple_set_u64(t, 0, es->db_id);
676 tuple_set_u64(t, 1, es->evsel->db_id); 680 tuple_set_u64(t, 1, es->evsel->db_id);
677 tuple_set_u64(t, 2, es->al->machine->db_id); 681 tuple_set_u64(t, 2, es->al->machine->db_id);
678 tuple_set_u64(t, 3, es->thread->db_id); 682 tuple_set_u64(t, 3, es->al->thread->db_id);
679 tuple_set_u64(t, 4, es->comm_db_id); 683 tuple_set_u64(t, 4, es->comm_db_id);
680 tuple_set_u64(t, 5, es->dso_db_id); 684 tuple_set_u64(t, 5, es->dso_db_id);
681 tuple_set_u64(t, 6, es->sym_db_id); 685 tuple_set_u64(t, 6, es->sym_db_id);
@@ -761,7 +765,6 @@ static int python_process_call_return(struct call_return *cr, void *data)
761 765
762static void python_process_general_event(struct perf_sample *sample, 766static void python_process_general_event(struct perf_sample *sample,
763 struct perf_evsel *evsel, 767 struct perf_evsel *evsel,
764 struct thread *thread,
765 struct addr_location *al) 768 struct addr_location *al)
766{ 769{
767 PyObject *handler, *t, *dict, *callchain, *dict_sample; 770 PyObject *handler, *t, *dict, *callchain, *dict_sample;
@@ -811,7 +814,7 @@ static void python_process_general_event(struct perf_sample *sample,
811 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 814 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
812 (const char *)sample->raw_data, sample->raw_size)); 815 (const char *)sample->raw_data, sample->raw_size));
813 pydict_set_item_string_decref(dict, "comm", 816 pydict_set_item_string_decref(dict, "comm",
814 PyString_FromString(thread__comm_str(thread))); 817 PyString_FromString(thread__comm_str(al->thread)));
815 if (al->map) { 818 if (al->map) {
816 pydict_set_item_string_decref(dict, "dso", 819 pydict_set_item_string_decref(dict, "dso",
817 PyString_FromString(al->map->dso->name)); 820 PyString_FromString(al->map->dso->name));
@@ -838,22 +841,20 @@ exit:
838static void python_process_event(union perf_event *event, 841static void python_process_event(union perf_event *event,
839 struct perf_sample *sample, 842 struct perf_sample *sample,
840 struct perf_evsel *evsel, 843 struct perf_evsel *evsel,
841 struct thread *thread,
842 struct addr_location *al) 844 struct addr_location *al)
843{ 845{
844 struct tables *tables = &tables_global; 846 struct tables *tables = &tables_global;
845 847
846 switch (evsel->attr.type) { 848 switch (evsel->attr.type) {
847 case PERF_TYPE_TRACEPOINT: 849 case PERF_TYPE_TRACEPOINT:
848 python_process_tracepoint(sample, evsel, thread, al); 850 python_process_tracepoint(sample, evsel, al);
849 break; 851 break;
850 /* Reserve for future process_hw/sw/raw APIs */ 852 /* Reserve for future process_hw/sw/raw APIs */
851 default: 853 default:
852 if (tables->db_export_mode) 854 if (tables->db_export_mode)
853 db_export__sample(&tables->dbe, event, sample, evsel, 855 db_export__sample(&tables->dbe, event, sample, evsel, al);
854 thread, al);
855 else 856 else
856 python_process_general_event(sample, evsel, thread, al); 857 python_process_general_event(sample, evsel, al);
857 } 858 }
858} 859}
859 860
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0baf75f12b7c..0c74012575ac 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,6 +16,12 @@
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "asm/bug.h" 17#include "asm/bug.h"
18 18
19static int machines__deliver_event(struct machines *machines,
20 struct perf_evlist *evlist,
21 union perf_event *event,
22 struct perf_sample *sample,
23 struct perf_tool *tool, u64 file_offset);
24
19static int perf_session__open(struct perf_session *session) 25static int perf_session__open(struct perf_session *session)
20{ 26{
21 struct perf_data_file *file = session->file; 27 struct perf_data_file *file = session->file;
@@ -86,6 +92,23 @@ static void perf_session__set_comm_exec(struct perf_session *session)
86 machines__set_comm_exec(&session->machines, comm_exec); 92 machines__set_comm_exec(&session->machines, comm_exec);
87} 93}
88 94
95static int ordered_events__deliver_event(struct ordered_events *oe,
96 struct ordered_event *event)
97{
98 struct perf_sample sample;
99 struct perf_session *session = container_of(oe, struct perf_session,
100 ordered_events);
101 int ret = perf_evlist__parse_sample(session->evlist, event->event, &sample);
102
103 if (ret) {
104 pr_err("Can't parse sample, err = %d\n", ret);
105 return ret;
106 }
107
108 return machines__deliver_event(&session->machines, session->evlist, event->event,
109 &sample, session->tool, event->file_offset);
110}
111
89struct perf_session *perf_session__new(struct perf_data_file *file, 112struct perf_session *perf_session__new(struct perf_data_file *file,
90 bool repipe, struct perf_tool *tool) 113 bool repipe, struct perf_tool *tool)
91{ 114{
@@ -95,8 +118,9 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
95 goto out; 118 goto out;
96 119
97 session->repipe = repipe; 120 session->repipe = repipe;
98 ordered_events__init(&session->ordered_events); 121 session->tool = tool;
99 machines__init(&session->machines); 122 machines__init(&session->machines);
123 ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
100 124
101 if (file) { 125 if (file) {
102 if (perf_data_file__open(file)) 126 if (perf_data_file__open(file))
@@ -138,11 +162,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
138 return NULL; 162 return NULL;
139} 163}
140 164
141static void perf_session__delete_dead_threads(struct perf_session *session)
142{
143 machine__delete_dead_threads(&session->machines.host);
144}
145
146static void perf_session__delete_threads(struct perf_session *session) 165static void perf_session__delete_threads(struct perf_session *session)
147{ 166{
148 machine__delete_threads(&session->machines.host); 167 machine__delete_threads(&session->machines.host);
@@ -167,7 +186,6 @@ static void perf_session_env__delete(struct perf_session_env *env)
167void perf_session__delete(struct perf_session *session) 186void perf_session__delete(struct perf_session *session)
168{ 187{
169 perf_session__destroy_kernel_maps(session); 188 perf_session__destroy_kernel_maps(session);
170 perf_session__delete_dead_threads(session);
171 perf_session__delete_threads(session); 189 perf_session__delete_threads(session);
172 perf_session_env__delete(&session->header.env); 190 perf_session_env__delete(&session->header.env);
173 machines__exit(&session->machines); 191 machines__exit(&session->machines);
@@ -215,10 +233,17 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,
215 return 0; 233 return 0;
216} 234}
217 235
236static int process_build_id_stub(struct perf_tool *tool __maybe_unused,
237 union perf_event *event __maybe_unused,
238 struct perf_session *session __maybe_unused)
239{
240 dump_printf(": unhandled!\n");
241 return 0;
242}
243
218static int process_finished_round_stub(struct perf_tool *tool __maybe_unused, 244static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
219 union perf_event *event __maybe_unused, 245 union perf_event *event __maybe_unused,
220 struct perf_session *perf_session 246 struct ordered_events *oe __maybe_unused)
221 __maybe_unused)
222{ 247{
223 dump_printf(": unhandled!\n"); 248 dump_printf(": unhandled!\n");
224 return 0; 249 return 0;
@@ -226,7 +251,7 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
226 251
227static int process_finished_round(struct perf_tool *tool, 252static int process_finished_round(struct perf_tool *tool,
228 union perf_event *event, 253 union perf_event *event,
229 struct perf_session *session); 254 struct ordered_events *oe);
230 255
231static int process_id_index_stub(struct perf_tool *tool __maybe_unused, 256static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
232 union perf_event *event __maybe_unused, 257 union perf_event *event __maybe_unused,
@@ -264,7 +289,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
264 if (tool->tracing_data == NULL) 289 if (tool->tracing_data == NULL)
265 tool->tracing_data = process_event_synth_tracing_data_stub; 290 tool->tracing_data = process_event_synth_tracing_data_stub;
266 if (tool->build_id == NULL) 291 if (tool->build_id == NULL)
267 tool->build_id = process_finished_round_stub; 292 tool->build_id = process_build_id_stub;
268 if (tool->finished_round == NULL) { 293 if (tool->finished_round == NULL) {
269 if (tool->ordered_events) 294 if (tool->ordered_events)
270 tool->finished_round = process_finished_round; 295 tool->finished_round = process_finished_round;
@@ -514,54 +539,80 @@ static perf_event__swap_op perf_event__swap_ops[] = {
514 * Flush every events below timestamp 7 539 * Flush every events below timestamp 7
515 * etc... 540 * etc...
516 */ 541 */
517static int process_finished_round(struct perf_tool *tool, 542static int process_finished_round(struct perf_tool *tool __maybe_unused,
518 union perf_event *event __maybe_unused, 543 union perf_event *event __maybe_unused,
519 struct perf_session *session) 544 struct ordered_events *oe)
520{ 545{
521 return ordered_events__flush(session, tool, OE_FLUSH__ROUND); 546 return ordered_events__flush(oe, OE_FLUSH__ROUND);
522} 547}
523 548
524int perf_session_queue_event(struct perf_session *s, union perf_event *event, 549int perf_session__queue_event(struct perf_session *s, union perf_event *event,
525 struct perf_tool *tool, struct perf_sample *sample, 550 struct perf_sample *sample, u64 file_offset)
526 u64 file_offset)
527{ 551{
528 struct ordered_events *oe = &s->ordered_events; 552 return ordered_events__queue(&s->ordered_events, event, sample, file_offset);
529 u64 timestamp = sample->time; 553}
530 struct ordered_event *new;
531
532 if (!timestamp || timestamp == ~0ULL)
533 return -ETIME;
534 554
535 if (timestamp < oe->last_flush) { 555static void callchain__lbr_callstack_printf(struct perf_sample *sample)
536 pr_oe_time(timestamp, "out of order event\n"); 556{
537 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n", 557 struct ip_callchain *callchain = sample->callchain;
538 oe->last_flush_type); 558 struct branch_stack *lbr_stack = sample->branch_stack;
559 u64 kernel_callchain_nr = callchain->nr;
560 unsigned int i;
539 561
540 s->stats.nr_unordered_events++; 562 for (i = 0; i < kernel_callchain_nr; i++) {
563 if (callchain->ips[i] == PERF_CONTEXT_USER)
564 break;
541 } 565 }
542 566
543 new = ordered_events__new(oe, timestamp, event); 567 if ((i != kernel_callchain_nr) && lbr_stack->nr) {
544 if (!new) { 568 u64 total_nr;
545 ordered_events__flush(s, tool, OE_FLUSH__HALF); 569 /*
546 new = ordered_events__new(oe, timestamp, event); 570 * LBR callstack can only get user call chain,
547 } 571 * i is kernel call chain number,
572 * 1 is PERF_CONTEXT_USER.
573 *
574 * The user call chain is stored in LBR registers.
575 * LBR are pair registers. The caller is stored
576 * in "from" register, while the callee is stored
577 * in "to" register.
578 * For example, there is a call stack
579 * "A"->"B"->"C"->"D".
580 * The LBR registers will recorde like
581 * "C"->"D", "B"->"C", "A"->"B".
582 * So only the first "to" register and all "from"
583 * registers are needed to construct the whole stack.
584 */
585 total_nr = i + 1 + lbr_stack->nr + 1;
586 kernel_callchain_nr = i + 1;
548 587
549 if (!new) 588 printf("... LBR call chain: nr:%" PRIu64 "\n", total_nr);
550 return -ENOMEM;
551 589
552 new->file_offset = file_offset; 590 for (i = 0; i < kernel_callchain_nr; i++)
553 return 0; 591 printf("..... %2d: %016" PRIx64 "\n",
592 i, callchain->ips[i]);
593
594 printf("..... %2d: %016" PRIx64 "\n",
595 (int)(kernel_callchain_nr), lbr_stack->entries[0].to);
596 for (i = 0; i < lbr_stack->nr; i++)
597 printf("..... %2d: %016" PRIx64 "\n",
598 (int)(i + kernel_callchain_nr + 1), lbr_stack->entries[i].from);
599 }
554} 600}
555 601
556static void callchain__printf(struct perf_sample *sample) 602static void callchain__printf(struct perf_evsel *evsel,
603 struct perf_sample *sample)
557{ 604{
558 unsigned int i; 605 unsigned int i;
606 struct ip_callchain *callchain = sample->callchain;
607
608 if (has_branch_callstack(evsel))
609 callchain__lbr_callstack_printf(sample);
559 610
560 printf("... chain: nr:%" PRIu64 "\n", sample->callchain->nr); 611 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
561 612
562 for (i = 0; i < sample->callchain->nr; i++) 613 for (i = 0; i < callchain->nr; i++)
563 printf("..... %2d: %016" PRIx64 "\n", 614 printf("..... %2d: %016" PRIx64 "\n",
564 i, sample->callchain->ips[i]); 615 i, callchain->ips[i]);
565} 616}
566 617
567static void branch_stack__printf(struct perf_sample *sample) 618static void branch_stack__printf(struct perf_sample *sample)
@@ -636,14 +687,14 @@ static void stack_user__printf(struct stack_dump *dump)
636 dump->size, dump->offset); 687 dump->size, dump->offset);
637} 688}
638 689
639static void perf_session__print_tstamp(struct perf_session *session, 690static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
640 union perf_event *event, 691 union perf_event *event,
641 struct perf_sample *sample) 692 struct perf_sample *sample)
642{ 693{
643 u64 sample_type = __perf_evlist__combined_sample_type(session->evlist); 694 u64 sample_type = __perf_evlist__combined_sample_type(evlist);
644 695
645 if (event->header.type != PERF_RECORD_SAMPLE && 696 if (event->header.type != PERF_RECORD_SAMPLE &&
646 !perf_evlist__sample_id_all(session->evlist)) { 697 !perf_evlist__sample_id_all(evlist)) {
647 fputs("-1 -1 ", stdout); 698 fputs("-1 -1 ", stdout);
648 return; 699 return;
649 } 700 }
@@ -685,7 +736,7 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
685 sample->read.one.id, sample->read.one.value); 736 sample->read.one.id, sample->read.one.value);
686} 737}
687 738
688static void dump_event(struct perf_session *session, union perf_event *event, 739static void dump_event(struct perf_evlist *evlist, union perf_event *event,
689 u64 file_offset, struct perf_sample *sample) 740 u64 file_offset, struct perf_sample *sample)
690{ 741{
691 if (!dump_trace) 742 if (!dump_trace)
@@ -697,7 +748,7 @@ static void dump_event(struct perf_session *session, union perf_event *event,
697 trace_event(event); 748 trace_event(event);
698 749
699 if (sample) 750 if (sample)
700 perf_session__print_tstamp(session, event, sample); 751 perf_evlist__print_tstamp(evlist, event, sample);
701 752
702 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset, 753 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
703 event->header.size, perf_event__name(event->header.type)); 754 event->header.size, perf_event__name(event->header.type));
@@ -718,9 +769,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
718 sample_type = evsel->attr.sample_type; 769 sample_type = evsel->attr.sample_type;
719 770
720 if (sample_type & PERF_SAMPLE_CALLCHAIN) 771 if (sample_type & PERF_SAMPLE_CALLCHAIN)
721 callchain__printf(sample); 772 callchain__printf(evsel, sample);
722 773
723 if (sample_type & PERF_SAMPLE_BRANCH_STACK) 774 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel))
724 branch_stack__printf(sample); 775 branch_stack__printf(sample);
725 776
726 if (sample_type & PERF_SAMPLE_REGS_USER) 777 if (sample_type & PERF_SAMPLE_REGS_USER)
@@ -745,8 +796,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
745 sample_read__printf(sample, evsel->attr.read_format); 796 sample_read__printf(sample, evsel->attr.read_format);
746} 797}
747 798
748static struct machine * 799static struct machine *machines__find_for_cpumode(struct machines *machines,
749 perf_session__find_machine_for_cpumode(struct perf_session *session,
750 union perf_event *event, 800 union perf_event *event,
751 struct perf_sample *sample) 801 struct perf_sample *sample)
752{ 802{
@@ -764,26 +814,24 @@ static struct machine *
764 else 814 else
765 pid = sample->pid; 815 pid = sample->pid;
766 816
767 machine = perf_session__find_machine(session, pid); 817 machine = machines__find(machines, pid);
768 if (!machine) 818 if (!machine)
769 machine = perf_session__findnew_machine(session, 819 machine = machines__find(machines, DEFAULT_GUEST_KERNEL_ID);
770 DEFAULT_GUEST_KERNEL_ID);
771 return machine; 820 return machine;
772 } 821 }
773 822
774 return &session->machines.host; 823 return &machines->host;
775} 824}
776 825
777static int deliver_sample_value(struct perf_session *session, 826static int deliver_sample_value(struct perf_evlist *evlist,
778 struct perf_tool *tool, 827 struct perf_tool *tool,
779 union perf_event *event, 828 union perf_event *event,
780 struct perf_sample *sample, 829 struct perf_sample *sample,
781 struct sample_read_value *v, 830 struct sample_read_value *v,
782 struct machine *machine) 831 struct machine *machine)
783{ 832{
784 struct perf_sample_id *sid; 833 struct perf_sample_id *sid = perf_evlist__id2sid(evlist, v->id);
785 834
786 sid = perf_evlist__id2sid(session->evlist, v->id);
787 if (sid) { 835 if (sid) {
788 sample->id = v->id; 836 sample->id = v->id;
789 sample->period = v->value - sid->period; 837 sample->period = v->value - sid->period;
@@ -791,14 +839,14 @@ static int deliver_sample_value(struct perf_session *session,
791 } 839 }
792 840
793 if (!sid || sid->evsel == NULL) { 841 if (!sid || sid->evsel == NULL) {
794 ++session->stats.nr_unknown_id; 842 ++evlist->stats.nr_unknown_id;
795 return 0; 843 return 0;
796 } 844 }
797 845
798 return tool->sample(tool, event, sample, sid->evsel, machine); 846 return tool->sample(tool, event, sample, sid->evsel, machine);
799} 847}
800 848
801static int deliver_sample_group(struct perf_session *session, 849static int deliver_sample_group(struct perf_evlist *evlist,
802 struct perf_tool *tool, 850 struct perf_tool *tool,
803 union perf_event *event, 851 union perf_event *event,
804 struct perf_sample *sample, 852 struct perf_sample *sample,
@@ -808,7 +856,7 @@ static int deliver_sample_group(struct perf_session *session,
808 u64 i; 856 u64 i;
809 857
810 for (i = 0; i < sample->read.group.nr; i++) { 858 for (i = 0; i < sample->read.group.nr; i++) {
811 ret = deliver_sample_value(session, tool, event, sample, 859 ret = deliver_sample_value(evlist, tool, event, sample,
812 &sample->read.group.values[i], 860 &sample->read.group.values[i],
813 machine); 861 machine);
814 if (ret) 862 if (ret)
@@ -819,7 +867,7 @@ static int deliver_sample_group(struct perf_session *session,
819} 867}
820 868
821static int 869static int
822perf_session__deliver_sample(struct perf_session *session, 870 perf_evlist__deliver_sample(struct perf_evlist *evlist,
823 struct perf_tool *tool, 871 struct perf_tool *tool,
824 union perf_event *event, 872 union perf_event *event,
825 struct perf_sample *sample, 873 struct perf_sample *sample,
@@ -836,41 +884,40 @@ perf_session__deliver_sample(struct perf_session *session,
836 884
837 /* For PERF_SAMPLE_READ we have either single or group mode. */ 885 /* For PERF_SAMPLE_READ we have either single or group mode. */
838 if (read_format & PERF_FORMAT_GROUP) 886 if (read_format & PERF_FORMAT_GROUP)
839 return deliver_sample_group(session, tool, event, sample, 887 return deliver_sample_group(evlist, tool, event, sample,
840 machine); 888 machine);
841 else 889 else
842 return deliver_sample_value(session, tool, event, sample, 890 return deliver_sample_value(evlist, tool, event, sample,
843 &sample->read.one, machine); 891 &sample->read.one, machine);
844} 892}
845 893
846int perf_session__deliver_event(struct perf_session *session, 894static int machines__deliver_event(struct machines *machines,
847 union perf_event *event, 895 struct perf_evlist *evlist,
848 struct perf_sample *sample, 896 union perf_event *event,
849 struct perf_tool *tool, u64 file_offset) 897 struct perf_sample *sample,
898 struct perf_tool *tool, u64 file_offset)
850{ 899{
851 struct perf_evsel *evsel; 900 struct perf_evsel *evsel;
852 struct machine *machine; 901 struct machine *machine;
853 902
854 dump_event(session, event, file_offset, sample); 903 dump_event(evlist, event, file_offset, sample);
855 904
856 evsel = perf_evlist__id2evsel(session->evlist, sample->id); 905 evsel = perf_evlist__id2evsel(evlist, sample->id);
857 906
858 machine = perf_session__find_machine_for_cpumode(session, event, 907 machine = machines__find_for_cpumode(machines, event, sample);
859 sample);
860 908
861 switch (event->header.type) { 909 switch (event->header.type) {
862 case PERF_RECORD_SAMPLE: 910 case PERF_RECORD_SAMPLE:
863 dump_sample(evsel, event, sample); 911 dump_sample(evsel, event, sample);
864 if (evsel == NULL) { 912 if (evsel == NULL) {
865 ++session->stats.nr_unknown_id; 913 ++evlist->stats.nr_unknown_id;
866 return 0; 914 return 0;
867 } 915 }
868 if (machine == NULL) { 916 if (machine == NULL) {
869 ++session->stats.nr_unprocessable_samples; 917 ++evlist->stats.nr_unprocessable_samples;
870 return 0; 918 return 0;
871 } 919 }
872 return perf_session__deliver_sample(session, tool, event, 920 return perf_evlist__deliver_sample(evlist, tool, event, sample, evsel, machine);
873 sample, evsel, machine);
874 case PERF_RECORD_MMAP: 921 case PERF_RECORD_MMAP:
875 return tool->mmap(tool, event, sample, machine); 922 return tool->mmap(tool, event, sample, machine);
876 case PERF_RECORD_MMAP2: 923 case PERF_RECORD_MMAP2:
@@ -883,7 +930,7 @@ int perf_session__deliver_event(struct perf_session *session,
883 return tool->exit(tool, event, sample, machine); 930 return tool->exit(tool, event, sample, machine);
884 case PERF_RECORD_LOST: 931 case PERF_RECORD_LOST:
885 if (tool->lost == perf_event__process_lost) 932 if (tool->lost == perf_event__process_lost)
886 session->stats.total_lost += event->lost.lost; 933 evlist->stats.total_lost += event->lost.lost;
887 return tool->lost(tool, event, sample, machine); 934 return tool->lost(tool, event, sample, machine);
888 case PERF_RECORD_READ: 935 case PERF_RECORD_READ:
889 return tool->read(tool, event, sample, evsel, machine); 936 return tool->read(tool, event, sample, evsel, machine);
@@ -892,20 +939,21 @@ int perf_session__deliver_event(struct perf_session *session,
892 case PERF_RECORD_UNTHROTTLE: 939 case PERF_RECORD_UNTHROTTLE:
893 return tool->unthrottle(tool, event, sample, machine); 940 return tool->unthrottle(tool, event, sample, machine);
894 default: 941 default:
895 ++session->stats.nr_unknown_events; 942 ++evlist->stats.nr_unknown_events;
896 return -1; 943 return -1;
897 } 944 }
898} 945}
899 946
900static s64 perf_session__process_user_event(struct perf_session *session, 947static s64 perf_session__process_user_event(struct perf_session *session,
901 union perf_event *event, 948 union perf_event *event,
902 struct perf_tool *tool,
903 u64 file_offset) 949 u64 file_offset)
904{ 950{
951 struct ordered_events *oe = &session->ordered_events;
952 struct perf_tool *tool = session->tool;
905 int fd = perf_data_file__fd(session->file); 953 int fd = perf_data_file__fd(session->file);
906 int err; 954 int err;
907 955
908 dump_event(session, event, file_offset, NULL); 956 dump_event(session->evlist, event, file_offset, NULL);
909 957
910 /* These events are processed right away */ 958 /* These events are processed right away */
911 switch (event->header.type) { 959 switch (event->header.type) {
@@ -929,7 +977,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
929 case PERF_RECORD_HEADER_BUILD_ID: 977 case PERF_RECORD_HEADER_BUILD_ID:
930 return tool->build_id(tool, event, session); 978 return tool->build_id(tool, event, session);
931 case PERF_RECORD_FINISHED_ROUND: 979 case PERF_RECORD_FINISHED_ROUND:
932 return tool->finished_round(tool, event, session); 980 return tool->finished_round(tool, event, oe);
933 case PERF_RECORD_ID_INDEX: 981 case PERF_RECORD_ID_INDEX:
934 return tool->id_index(tool, event, session); 982 return tool->id_index(tool, event, session);
935 default: 983 default:
@@ -939,15 +987,17 @@ static s64 perf_session__process_user_event(struct perf_session *session,
939 987
940int perf_session__deliver_synth_event(struct perf_session *session, 988int perf_session__deliver_synth_event(struct perf_session *session,
941 union perf_event *event, 989 union perf_event *event,
942 struct perf_sample *sample, 990 struct perf_sample *sample)
943 struct perf_tool *tool)
944{ 991{
945 events_stats__inc(&session->stats, event->header.type); 992 struct perf_evlist *evlist = session->evlist;
993 struct perf_tool *tool = session->tool;
994
995 events_stats__inc(&evlist->stats, event->header.type);
946 996
947 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 997 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
948 return perf_session__process_user_event(session, event, tool, 0); 998 return perf_session__process_user_event(session, event, 0);
949 999
950 return perf_session__deliver_event(session, event, sample, tool, 0); 1000 return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0);
951} 1001}
952 1002
953static void event_swap(union perf_event *event, bool sample_id_all) 1003static void event_swap(union perf_event *event, bool sample_id_all)
@@ -1015,40 +1065,39 @@ out_parse_sample:
1015} 1065}
1016 1066
1017static s64 perf_session__process_event(struct perf_session *session, 1067static s64 perf_session__process_event(struct perf_session *session,
1018 union perf_event *event, 1068 union perf_event *event, u64 file_offset)
1019 struct perf_tool *tool,
1020 u64 file_offset)
1021{ 1069{
1070 struct perf_evlist *evlist = session->evlist;
1071 struct perf_tool *tool = session->tool;
1022 struct perf_sample sample; 1072 struct perf_sample sample;
1023 int ret; 1073 int ret;
1024 1074
1025 if (session->header.needs_swap) 1075 if (session->header.needs_swap)
1026 event_swap(event, perf_evlist__sample_id_all(session->evlist)); 1076 event_swap(event, perf_evlist__sample_id_all(evlist));
1027 1077
1028 if (event->header.type >= PERF_RECORD_HEADER_MAX) 1078 if (event->header.type >= PERF_RECORD_HEADER_MAX)
1029 return -EINVAL; 1079 return -EINVAL;
1030 1080
1031 events_stats__inc(&session->stats, event->header.type); 1081 events_stats__inc(&evlist->stats, event->header.type);
1032 1082
1033 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 1083 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
1034 return perf_session__process_user_event(session, event, tool, file_offset); 1084 return perf_session__process_user_event(session, event, file_offset);
1035 1085
1036 /* 1086 /*
1037 * For all kernel events we get the sample data 1087 * For all kernel events we get the sample data
1038 */ 1088 */
1039 ret = perf_evlist__parse_sample(session->evlist, event, &sample); 1089 ret = perf_evlist__parse_sample(evlist, event, &sample);
1040 if (ret) 1090 if (ret)
1041 return ret; 1091 return ret;
1042 1092
1043 if (tool->ordered_events) { 1093 if (tool->ordered_events) {
1044 ret = perf_session_queue_event(session, event, tool, &sample, 1094 ret = perf_session__queue_event(session, event, &sample, file_offset);
1045 file_offset);
1046 if (ret != -ETIME) 1095 if (ret != -ETIME)
1047 return ret; 1096 return ret;
1048 } 1097 }
1049 1098
1050 return perf_session__deliver_event(session, event, &sample, tool, 1099 return machines__deliver_event(&session->machines, evlist, event,
1051 file_offset); 1100 &sample, tool, file_offset);
1052} 1101}
1053 1102
1054void perf_event_header__bswap(struct perf_event_header *hdr) 1103void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1076,54 +1125,57 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
1076 return thread; 1125 return thread;
1077} 1126}
1078 1127
1079static void perf_session__warn_about_errors(const struct perf_session *session, 1128static void perf_session__warn_about_errors(const struct perf_session *session)
1080 const struct perf_tool *tool)
1081{ 1129{
1082 if (tool->lost == perf_event__process_lost && 1130 const struct events_stats *stats = &session->evlist->stats;
1083 session->stats.nr_events[PERF_RECORD_LOST] != 0) { 1131 const struct ordered_events *oe = &session->ordered_events;
1132
1133 if (session->tool->lost == perf_event__process_lost &&
1134 stats->nr_events[PERF_RECORD_LOST] != 0) {
1084 ui__warning("Processed %d events and lost %d chunks!\n\n" 1135 ui__warning("Processed %d events and lost %d chunks!\n\n"
1085 "Check IO/CPU overload!\n\n", 1136 "Check IO/CPU overload!\n\n",
1086 session->stats.nr_events[0], 1137 stats->nr_events[0],
1087 session->stats.nr_events[PERF_RECORD_LOST]); 1138 stats->nr_events[PERF_RECORD_LOST]);
1088 } 1139 }
1089 1140
1090 if (session->stats.nr_unknown_events != 0) { 1141 if (stats->nr_unknown_events != 0) {
1091 ui__warning("Found %u unknown events!\n\n" 1142 ui__warning("Found %u unknown events!\n\n"
1092 "Is this an older tool processing a perf.data " 1143 "Is this an older tool processing a perf.data "
1093 "file generated by a more recent tool?\n\n" 1144 "file generated by a more recent tool?\n\n"
1094 "If that is not the case, consider " 1145 "If that is not the case, consider "
1095 "reporting to linux-kernel@vger.kernel.org.\n\n", 1146 "reporting to linux-kernel@vger.kernel.org.\n\n",
1096 session->stats.nr_unknown_events); 1147 stats->nr_unknown_events);
1097 } 1148 }
1098 1149
1099 if (session->stats.nr_unknown_id != 0) { 1150 if (stats->nr_unknown_id != 0) {
1100 ui__warning("%u samples with id not present in the header\n", 1151 ui__warning("%u samples with id not present in the header\n",
1101 session->stats.nr_unknown_id); 1152 stats->nr_unknown_id);
1102 } 1153 }
1103 1154
1104 if (session->stats.nr_invalid_chains != 0) { 1155 if (stats->nr_invalid_chains != 0) {
1105 ui__warning("Found invalid callchains!\n\n" 1156 ui__warning("Found invalid callchains!\n\n"
1106 "%u out of %u events were discarded for this reason.\n\n" 1157 "%u out of %u events were discarded for this reason.\n\n"
1107 "Consider reporting to linux-kernel@vger.kernel.org.\n\n", 1158 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
1108 session->stats.nr_invalid_chains, 1159 stats->nr_invalid_chains,
1109 session->stats.nr_events[PERF_RECORD_SAMPLE]); 1160 stats->nr_events[PERF_RECORD_SAMPLE]);
1110 } 1161 }
1111 1162
1112 if (session->stats.nr_unprocessable_samples != 0) { 1163 if (stats->nr_unprocessable_samples != 0) {
1113 ui__warning("%u unprocessable samples recorded.\n" 1164 ui__warning("%u unprocessable samples recorded.\n"
1114 "Do you have a KVM guest running and not using 'perf kvm'?\n", 1165 "Do you have a KVM guest running and not using 'perf kvm'?\n",
1115 session->stats.nr_unprocessable_samples); 1166 stats->nr_unprocessable_samples);
1116 } 1167 }
1117 1168
1118 if (session->stats.nr_unordered_events != 0) 1169 if (oe->nr_unordered_events != 0)
1119 ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events); 1170 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1120} 1171}
1121 1172
1122volatile int session_done; 1173volatile int session_done;
1123 1174
1124static int __perf_session__process_pipe_events(struct perf_session *session, 1175static int __perf_session__process_pipe_events(struct perf_session *session)
1125 struct perf_tool *tool)
1126{ 1176{
1177 struct ordered_events *oe = &session->ordered_events;
1178 struct perf_tool *tool = session->tool;
1127 int fd = perf_data_file__fd(session->file); 1179 int fd = perf_data_file__fd(session->file);
1128 union perf_event *event; 1180 union perf_event *event;
1129 uint32_t size, cur_size = 0; 1181 uint32_t size, cur_size = 0;
@@ -1187,7 +1239,7 @@ more:
1187 } 1239 }
1188 } 1240 }
1189 1241
1190 if ((skip = perf_session__process_event(session, event, tool, head)) < 0) { 1242 if ((skip = perf_session__process_event(session, event, head)) < 0) {
1191 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1243 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1192 head, event->header.size, event->header.type); 1244 head, event->header.size, event->header.type);
1193 err = -EINVAL; 1245 err = -EINVAL;
@@ -1203,10 +1255,10 @@ more:
1203 goto more; 1255 goto more;
1204done: 1256done:
1205 /* do the final flush for ordered samples */ 1257 /* do the final flush for ordered samples */
1206 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL); 1258 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1207out_err: 1259out_err:
1208 free(buf); 1260 free(buf);
1209 perf_session__warn_about_errors(session, tool); 1261 perf_session__warn_about_errors(session);
1210 ordered_events__free(&session->ordered_events); 1262 ordered_events__free(&session->ordered_events);
1211 return err; 1263 return err;
1212} 1264}
@@ -1253,8 +1305,10 @@ fetch_mmaped_event(struct perf_session *session,
1253 1305
1254static int __perf_session__process_events(struct perf_session *session, 1306static int __perf_session__process_events(struct perf_session *session,
1255 u64 data_offset, u64 data_size, 1307 u64 data_offset, u64 data_size,
1256 u64 file_size, struct perf_tool *tool) 1308 u64 file_size)
1257{ 1309{
1310 struct ordered_events *oe = &session->ordered_events;
1311 struct perf_tool *tool = session->tool;
1258 int fd = perf_data_file__fd(session->file); 1312 int fd = perf_data_file__fd(session->file);
1259 u64 head, page_offset, file_offset, file_pos, size; 1313 u64 head, page_offset, file_offset, file_pos, size;
1260 int err, mmap_prot, mmap_flags, map_idx = 0; 1314 int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1323,8 +1377,7 @@ more:
1323 size = event->header.size; 1377 size = event->header.size;
1324 1378
1325 if (size < sizeof(struct perf_event_header) || 1379 if (size < sizeof(struct perf_event_header) ||
1326 (skip = perf_session__process_event(session, event, tool, file_pos)) 1380 (skip = perf_session__process_event(session, event, file_pos)) < 0) {
1327 < 0) {
1328 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1381 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1329 file_offset + head, event->header.size, 1382 file_offset + head, event->header.size,
1330 event->header.type); 1383 event->header.type);
@@ -1348,17 +1401,16 @@ more:
1348 1401
1349out: 1402out:
1350 /* do the final flush for ordered samples */ 1403 /* do the final flush for ordered samples */
1351 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL); 1404 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1352out_err: 1405out_err:
1353 ui_progress__finish(); 1406 ui_progress__finish();
1354 perf_session__warn_about_errors(session, tool); 1407 perf_session__warn_about_errors(session);
1355 ordered_events__free(&session->ordered_events); 1408 ordered_events__free(&session->ordered_events);
1356 session->one_mmap = false; 1409 session->one_mmap = false;
1357 return err; 1410 return err;
1358} 1411}
1359 1412
1360int perf_session__process_events(struct perf_session *session, 1413int perf_session__process_events(struct perf_session *session)
1361 struct perf_tool *tool)
1362{ 1414{
1363 u64 size = perf_data_file__size(session->file); 1415 u64 size = perf_data_file__size(session->file);
1364 int err; 1416 int err;
@@ -1369,10 +1421,9 @@ int perf_session__process_events(struct perf_session *session,
1369 if (!perf_data_file__is_pipe(session->file)) 1421 if (!perf_data_file__is_pipe(session->file))
1370 err = __perf_session__process_events(session, 1422 err = __perf_session__process_events(session,
1371 session->header.data_offset, 1423 session->header.data_offset,
1372 session->header.data_size, 1424 session->header.data_size, size);
1373 size, tool);
1374 else 1425 else
1375 err = __perf_session__process_pipe_events(session, tool); 1426 err = __perf_session__process_pipe_events(session);
1376 1427
1377 return err; 1428 return err;
1378} 1429}
@@ -1415,6 +1466,9 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1415 1466
1416 for (i = 0; i < MAP__NR_TYPES; ++i) { 1467 for (i = 0; i < MAP__NR_TYPES; ++i) {
1417 struct kmap *kmap = map__kmap(maps[i]); 1468 struct kmap *kmap = map__kmap(maps[i]);
1469
1470 if (!kmap)
1471 continue;
1418 kmap->ref_reloc_sym = ref; 1472 kmap->ref_reloc_sym = ref;
1419 } 1473 }
1420 1474
@@ -1436,7 +1490,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1436{ 1490{
1437 size_t ret = fprintf(fp, "Aggregated stats:\n"); 1491 size_t ret = fprintf(fp, "Aggregated stats:\n");
1438 1492
1439 ret += events_stats__fprintf(&session->stats, fp); 1493 ret += events_stats__fprintf(&session->evlist->stats, fp);
1440 return ret; 1494 return ret;
1441} 1495}
1442 1496
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6d663dc76404..d5fa7b7916ef 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -20,13 +20,13 @@ struct perf_session {
20 struct machines machines; 20 struct machines machines;
21 struct perf_evlist *evlist; 21 struct perf_evlist *evlist;
22 struct trace_event tevent; 22 struct trace_event tevent;
23 struct events_stats stats;
24 bool repipe; 23 bool repipe;
25 bool one_mmap; 24 bool one_mmap;
26 void *one_mmap_addr; 25 void *one_mmap_addr;
27 u64 one_mmap_offset; 26 u64 one_mmap_offset;
28 struct ordered_events ordered_events; 27 struct ordered_events ordered_events;
29 struct perf_data_file *file; 28 struct perf_data_file *file;
29 struct perf_tool *tool;
30}; 30};
31 31
32#define PRINT_IP_OPT_IP (1<<0) 32#define PRINT_IP_OPT_IP (1<<0)
@@ -49,20 +49,13 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
49 union perf_event **event_ptr, 49 union perf_event **event_ptr,
50 struct perf_sample *sample); 50 struct perf_sample *sample);
51 51
52int perf_session__process_events(struct perf_session *session, 52int perf_session__process_events(struct perf_session *session);
53 struct perf_tool *tool);
54 53
55int perf_session_queue_event(struct perf_session *s, union perf_event *event, 54int perf_session__queue_event(struct perf_session *s, union perf_event *event,
56 struct perf_tool *tool, struct perf_sample *sample, 55 struct perf_sample *sample, u64 file_offset);
57 u64 file_offset);
58 56
59void perf_tool__fill_defaults(struct perf_tool *tool); 57void perf_tool__fill_defaults(struct perf_tool *tool);
60 58
61int perf_session__deliver_event(struct perf_session *session,
62 union perf_event *event,
63 struct perf_sample *sample,
64 struct perf_tool *tool, u64 file_offset);
65
66int perf_session__resolve_callchain(struct perf_session *session, 59int perf_session__resolve_callchain(struct perf_session *session,
67 struct perf_evsel *evsel, 60 struct perf_evsel *evsel,
68 struct thread *thread, 61 struct thread *thread,
@@ -126,8 +119,7 @@ extern volatile int session_done;
126 119
127int perf_session__deliver_synth_event(struct perf_session *session, 120int perf_session__deliver_synth_event(struct perf_session *session,
128 union perf_event *event, 121 union perf_event *event,
129 struct perf_sample *sample, 122 struct perf_sample *sample);
130 struct perf_tool *tool);
131 123
132int perf_event__process_id_index(struct perf_tool *tool, 124int perf_event__process_id_index(struct perf_tool *tool,
133 union perf_event *event, 125 union perf_event *event,
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index d0aee4b9dfd4..1833103768cb 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter'
25build_lib = getenv('PYTHON_EXTBUILD_LIB') 25build_lib = getenv('PYTHON_EXTBUILD_LIB')
26build_tmp = getenv('PYTHON_EXTBUILD_TMP') 26build_tmp = getenv('PYTHON_EXTBUILD_TMP')
27libtraceevent = getenv('LIBTRACEEVENT') 27libtraceevent = getenv('LIBTRACEEVENT')
28libapikfs = getenv('LIBAPIKFS') 28libapikfs = getenv('LIBAPI')
29 29
30ext_sources = [f.strip() for f in file('util/python-ext-sources') 30ext_sources = [f.strip() for f in file('util/python-ext-sources')
31 if len(f.strip()) > 0 and f[0] != '#'] 31 if len(f.strip()) > 0 and f[0] != '#']
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 7a39c1ed8d37..4593f36ecc4c 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1463,6 +1463,15 @@ int sort_dimension__add(const char *tok)
1463 sort__has_parent = 1; 1463 sort__has_parent = 1;
1464 } else if (sd->entry == &sort_sym) { 1464 } else if (sd->entry == &sort_sym) {
1465 sort__has_sym = 1; 1465 sort__has_sym = 1;
1466 /*
1467 * perf diff displays the performance difference amongst
1468 * two or more perf.data files. Those files could come
1469 * from different binaries. So we should not compare
1470 * their ips, but the name of symbol.
1471 */
1472 if (sort__mode == SORT_MODE__DIFF)
1473 sd->entry->se_collapse = sort__sym_sort;
1474
1466 } else if (sd->entry == &sort_dso) { 1475 } else if (sd->entry == &sort_dso) {
1467 sort__has_dso = 1; 1476 sort__has_dso = 1;
1468 } 1477 }
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index c03e4ff8beff..846036a921dc 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -44,6 +44,7 @@ extern struct sort_entry sort_dso_to;
44extern struct sort_entry sort_sym_from; 44extern struct sort_entry sort_sym_from;
45extern struct sort_entry sort_sym_to; 45extern struct sort_entry sort_sym_to;
46extern enum sort_type sort__first_dimension; 46extern enum sort_type sort__first_dimension;
47extern const char default_mem_sort_order[];
47 48
48struct he_stat { 49struct he_stat {
49 u64 period; 50 u64 period;
@@ -102,7 +103,6 @@ struct hist_entry {
102 103
103 bool init_have_children; 104 bool init_have_children;
104 char level; 105 char level;
105 bool used;
106 u8 filtered; 106 u8 filtered;
107 char *srcline; 107 char *srcline;
108 struct symbol *parent; 108 struct symbol *parent;
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index b24f9d8727a8..a7ab6063e038 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -11,6 +11,11 @@
11#include <symbol/kallsyms.h> 11#include <symbol/kallsyms.h>
12#include "debug.h" 12#include "debug.h"
13 13
14#ifndef EM_AARCH64
15#define EM_AARCH64 183 /* ARM 64 bit */
16#endif
17
18
14#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT 19#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
15extern char *cplus_demangle(const char *, int); 20extern char *cplus_demangle(const char *, int);
16 21
@@ -69,6 +74,10 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
69 return GELF_ST_TYPE(sym->st_info); 74 return GELF_ST_TYPE(sym->st_info);
70} 75}
71 76
77#ifndef STT_GNU_IFUNC
78#define STT_GNU_IFUNC 10
79#endif
80
72static inline int elf_sym__is_function(const GElf_Sym *sym) 81static inline int elf_sym__is_function(const GElf_Sym *sym)
73{ 82{
74 return (elf_sym__type(sym) == STT_FUNC || 83 return (elf_sym__type(sym) == STT_FUNC ||
@@ -570,32 +579,37 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
570static int decompress_kmodule(struct dso *dso, const char *name, 579static int decompress_kmodule(struct dso *dso, const char *name,
571 enum dso_binary_type type) 580 enum dso_binary_type type)
572{ 581{
573 int fd; 582 int fd = -1;
574 const char *ext = strrchr(name, '.');
575 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; 583 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
584 struct kmod_path m;
576 585
577 if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && 586 if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
578 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP && 587 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP &&
579 type != DSO_BINARY_TYPE__BUILD_ID_CACHE) 588 type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
580 return -1; 589 return -1;
581 590
582 if (!ext || !is_supported_compression(ext + 1)) { 591 if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
583 ext = strrchr(dso->name, '.'); 592 name = dso->long_name;
584 if (!ext || !is_supported_compression(ext + 1))
585 return -1;
586 }
587 593
588 fd = mkstemp(tmpbuf); 594 if (kmod_path__parse_ext(&m, name) || !m.comp)
589 if (fd < 0)
590 return -1; 595 return -1;
591 596
592 if (!decompress_to_file(ext + 1, name, fd)) { 597 fd = mkstemp(tmpbuf);
598 if (fd < 0) {
599 dso->load_errno = errno;
600 goto out;
601 }
602
603 if (!decompress_to_file(m.ext, name, fd)) {
604 dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
593 close(fd); 605 close(fd);
594 fd = -1; 606 fd = -1;
595 } 607 }
596 608
597 unlink(tmpbuf); 609 unlink(tmpbuf);
598 610
611out:
612 free(m.ext);
599 return fd; 613 return fd;
600} 614}
601 615
@@ -624,37 +638,49 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
624 Elf *elf; 638 Elf *elf;
625 int fd; 639 int fd;
626 640
627 if (dso__needs_decompress(dso)) 641 if (dso__needs_decompress(dso)) {
628 fd = decompress_kmodule(dso, name, type); 642 fd = decompress_kmodule(dso, name, type);
629 else 643 if (fd < 0)
644 return -1;
645 } else {
630 fd = open(name, O_RDONLY); 646 fd = open(name, O_RDONLY);
631 647 if (fd < 0) {
632 if (fd < 0) 648 dso->load_errno = errno;
633 return -1; 649 return -1;
650 }
651 }
634 652
635 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 653 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
636 if (elf == NULL) { 654 if (elf == NULL) {
637 pr_debug("%s: cannot read %s ELF file.\n", __func__, name); 655 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
656 dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
638 goto out_close; 657 goto out_close;
639 } 658 }
640 659
641 if (gelf_getehdr(elf, &ehdr) == NULL) { 660 if (gelf_getehdr(elf, &ehdr) == NULL) {
661 dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
642 pr_debug("%s: cannot get elf header.\n", __func__); 662 pr_debug("%s: cannot get elf header.\n", __func__);
643 goto out_elf_end; 663 goto out_elf_end;
644 } 664 }
645 665
646 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) 666 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) {
667 dso->load_errno = DSO_LOAD_ERRNO__INTERNAL_ERROR;
647 goto out_elf_end; 668 goto out_elf_end;
669 }
648 670
649 /* Always reject images with a mismatched build-id: */ 671 /* Always reject images with a mismatched build-id: */
650 if (dso->has_build_id) { 672 if (dso->has_build_id) {
651 u8 build_id[BUILD_ID_SIZE]; 673 u8 build_id[BUILD_ID_SIZE];
652 674
653 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) 675 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) {
676 dso->load_errno = DSO_LOAD_ERRNO__CANNOT_READ_BUILDID;
654 goto out_elf_end; 677 goto out_elf_end;
678 }
655 679
656 if (!dso__build_id_equal(dso, build_id)) 680 if (!dso__build_id_equal(dso, build_id)) {
681 dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID;
657 goto out_elf_end; 682 goto out_elf_end;
683 }
658 } 684 }
659 685
660 ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64); 686 ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
@@ -690,8 +716,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
690 } 716 }
691 717
692 ss->name = strdup(name); 718 ss->name = strdup(name);
693 if (!ss->name) 719 if (!ss->name) {
720 dso->load_errno = errno;
694 goto out_elf_end; 721 goto out_elf_end;
722 }
695 723
696 ss->elf = elf; 724 ss->elf = elf;
697 ss->fd = fd; 725 ss->fd = fd;
@@ -748,6 +776,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
748 symbol_filter_t filter, int kmodule) 776 symbol_filter_t filter, int kmodule)
749{ 777{
750 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; 778 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
779 struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL;
751 struct map *curr_map = map; 780 struct map *curr_map = map;
752 struct dso *curr_dso = dso; 781 struct dso *curr_dso = dso;
753 Elf_Data *symstrs, *secstrs; 782 Elf_Data *symstrs, *secstrs;
@@ -763,6 +792,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
763 int nr = 0; 792 int nr = 0;
764 bool remap_kernel = false, adjust_kernel_syms = false; 793 bool remap_kernel = false, adjust_kernel_syms = false;
765 794
795 if (kmap && !kmaps)
796 return -1;
797
766 dso->symtab_type = syms_ss->type; 798 dso->symtab_type = syms_ss->type;
767 dso->is_64_bit = syms_ss->is_64_bit; 799 dso->is_64_bit = syms_ss->is_64_bit;
768 dso->rel = syms_ss->ehdr.e_type == ET_REL; 800 dso->rel = syms_ss->ehdr.e_type == ET_REL;
@@ -859,10 +891,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
859 /* Reject ARM ELF "mapping symbols": these aren't unique and 891 /* Reject ARM ELF "mapping symbols": these aren't unique and
860 * don't identify functions, so will confuse the profile 892 * don't identify functions, so will confuse the profile
861 * output: */ 893 * output: */
862 if (ehdr.e_machine == EM_ARM) { 894 if (ehdr.e_machine == EM_ARM || ehdr.e_machine == EM_AARCH64) {
863 if (!strcmp(elf_name, "$a") || 895 if (elf_name[0] == '$' && strchr("adtx", elf_name[1])
864 !strcmp(elf_name, "$d") || 896 && (elf_name[2] == '\0' || elf_name[2] == '.'))
865 !strcmp(elf_name, "$t"))
866 continue; 897 continue;
867 } 898 }
868 899
@@ -931,8 +962,10 @@ int dso__load_sym(struct dso *dso, struct map *map,
931 map->map_ip = map__map_ip; 962 map->map_ip = map__map_ip;
932 map->unmap_ip = map__unmap_ip; 963 map->unmap_ip = map__unmap_ip;
933 /* Ensure maps are correctly ordered */ 964 /* Ensure maps are correctly ordered */
934 map_groups__remove(kmap->kmaps, map); 965 if (kmaps) {
935 map_groups__insert(kmap->kmaps, map); 966 map_groups__remove(kmaps, map);
967 map_groups__insert(kmaps, map);
968 }
936 } 969 }
937 970
938 /* 971 /*
@@ -956,7 +989,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
956 snprintf(dso_name, sizeof(dso_name), 989 snprintf(dso_name, sizeof(dso_name),
957 "%s%s", dso->short_name, section_name); 990 "%s%s", dso->short_name, section_name);
958 991
959 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); 992 curr_map = map_groups__find_by_name(kmaps, map->type, dso_name);
960 if (curr_map == NULL) { 993 if (curr_map == NULL) {
961 u64 start = sym.st_value; 994 u64 start = sym.st_value;
962 995
@@ -986,7 +1019,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
986 curr_map->unmap_ip = identity__map_ip; 1019 curr_map->unmap_ip = identity__map_ip;
987 } 1020 }
988 curr_dso->symtab_type = dso->symtab_type; 1021 curr_dso->symtab_type = dso->symtab_type;
989 map_groups__insert(kmap->kmaps, curr_map); 1022 map_groups__insert(kmaps, curr_map);
990 /* 1023 /*
991 * The new DSO should go to the kernel DSOS 1024 * The new DSO should go to the kernel DSOS
992 */ 1025 */
@@ -1040,14 +1073,15 @@ new_symbol:
1040 * For misannotated, zeroed, ASM function sizes. 1073 * For misannotated, zeroed, ASM function sizes.
1041 */ 1074 */
1042 if (nr > 0) { 1075 if (nr > 0) {
1043 symbols__fixup_duplicate(&dso->symbols[map->type]); 1076 if (!symbol_conf.allow_aliases)
1077 symbols__fixup_duplicate(&dso->symbols[map->type]);
1044 symbols__fixup_end(&dso->symbols[map->type]); 1078 symbols__fixup_end(&dso->symbols[map->type]);
1045 if (kmap) { 1079 if (kmap) {
1046 /* 1080 /*
1047 * We need to fixup this here too because we create new 1081 * We need to fixup this here too because we create new
1048 * maps here, for things like vsyscall sections. 1082 * maps here, for things like vsyscall sections.
1049 */ 1083 */
1050 __map_groups__fixup_end(kmap->kmaps, map->type); 1084 __map_groups__fixup_end(kmaps, map->type);
1051 } 1085 }
1052 } 1086 }
1053 err = nr; 1087 err = nr;
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index d7efb03b3f9a..fd8477cacf88 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -246,13 +246,12 @@ out:
246 return ret; 246 return ret;
247} 247}
248 248
249int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused, 249int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
250 const char *name,
251 enum dso_binary_type type) 250 enum dso_binary_type type)
252{ 251{
253 int fd = open(name, O_RDONLY); 252 int fd = open(name, O_RDONLY);
254 if (fd < 0) 253 if (fd < 0)
255 return -1; 254 goto out_errno;
256 255
257 ss->name = strdup(name); 256 ss->name = strdup(name);
258 if (!ss->name) 257 if (!ss->name)
@@ -264,6 +263,8 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
264 return 0; 263 return 0;
265out_close: 264out_close:
266 close(fd); 265 close(fd);
266out_errno:
267 dso->load_errno = errno;
267 return -1; 268 return -1;
268} 269}
269 270
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index a69066865a55..201f6c4ca738 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,6 +15,7 @@
15#include "machine.h" 15#include "machine.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
18#include "intlist.h"
18#include "header.h" 19#include "header.h"
19 20
20#include <elf.h> 21#include <elf.h>
@@ -629,13 +630,16 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
629static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, 630static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
630 symbol_filter_t filter) 631 symbol_filter_t filter)
631{ 632{
632 struct map_groups *kmaps = map__kmap(map)->kmaps; 633 struct map_groups *kmaps = map__kmaps(map);
633 struct map *curr_map; 634 struct map *curr_map;
634 struct symbol *pos; 635 struct symbol *pos;
635 int count = 0, moved = 0; 636 int count = 0, moved = 0;
636 struct rb_root *root = &dso->symbols[map->type]; 637 struct rb_root *root = &dso->symbols[map->type];
637 struct rb_node *next = rb_first(root); 638 struct rb_node *next = rb_first(root);
638 639
640 if (!kmaps)
641 return -1;
642
639 while (next) { 643 while (next) {
640 char *module; 644 char *module;
641 645
@@ -681,8 +685,8 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
681static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, 685static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
682 symbol_filter_t filter) 686 symbol_filter_t filter)
683{ 687{
684 struct map_groups *kmaps = map__kmap(map)->kmaps; 688 struct map_groups *kmaps = map__kmaps(map);
685 struct machine *machine = kmaps->machine; 689 struct machine *machine;
686 struct map *curr_map = map; 690 struct map *curr_map = map;
687 struct symbol *pos; 691 struct symbol *pos;
688 int count = 0, moved = 0; 692 int count = 0, moved = 0;
@@ -690,6 +694,11 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
690 struct rb_node *next = rb_first(root); 694 struct rb_node *next = rb_first(root);
691 int kernel_range = 0; 695 int kernel_range = 0;
692 696
697 if (!kmaps)
698 return -1;
699
700 machine = kmaps->machine;
701
693 while (next) { 702 while (next) {
694 char *module; 703 char *module;
695 704
@@ -1024,9 +1033,12 @@ static bool filename_from_kallsyms_filename(char *filename,
1024static int validate_kcore_modules(const char *kallsyms_filename, 1033static int validate_kcore_modules(const char *kallsyms_filename,
1025 struct map *map) 1034 struct map *map)
1026{ 1035{
1027 struct map_groups *kmaps = map__kmap(map)->kmaps; 1036 struct map_groups *kmaps = map__kmaps(map);
1028 char modules_filename[PATH_MAX]; 1037 char modules_filename[PATH_MAX];
1029 1038
1039 if (!kmaps)
1040 return -EINVAL;
1041
1030 if (!filename_from_kallsyms_filename(modules_filename, "modules", 1042 if (!filename_from_kallsyms_filename(modules_filename, "modules",
1031 kallsyms_filename)) 1043 kallsyms_filename))
1032 return -EINVAL; 1044 return -EINVAL;
@@ -1042,6 +1054,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename,
1042{ 1054{
1043 struct kmap *kmap = map__kmap(map); 1055 struct kmap *kmap = map__kmap(map);
1044 1056
1057 if (!kmap)
1058 return -EINVAL;
1059
1045 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { 1060 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
1046 u64 start; 1061 u64 start;
1047 1062
@@ -1080,8 +1095,8 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
1080static int dso__load_kcore(struct dso *dso, struct map *map, 1095static int dso__load_kcore(struct dso *dso, struct map *map,
1081 const char *kallsyms_filename) 1096 const char *kallsyms_filename)
1082{ 1097{
1083 struct map_groups *kmaps = map__kmap(map)->kmaps; 1098 struct map_groups *kmaps = map__kmaps(map);
1084 struct machine *machine = kmaps->machine; 1099 struct machine *machine;
1085 struct kcore_mapfn_data md; 1100 struct kcore_mapfn_data md;
1086 struct map *old_map, *new_map, *replacement_map = NULL; 1101 struct map *old_map, *new_map, *replacement_map = NULL;
1087 bool is_64_bit; 1102 bool is_64_bit;
@@ -1089,6 +1104,11 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1089 char kcore_filename[PATH_MAX]; 1104 char kcore_filename[PATH_MAX];
1090 struct symbol *sym; 1105 struct symbol *sym;
1091 1106
1107 if (!kmaps)
1108 return -EINVAL;
1109
1110 machine = kmaps->machine;
1111
1092 /* This function requires that the map is the kernel map */ 1112 /* This function requires that the map is the kernel map */
1093 if (map != machine->vmlinux_maps[map->type]) 1113 if (map != machine->vmlinux_maps[map->type])
1094 return -EINVAL; 1114 return -EINVAL;
@@ -1201,6 +1221,9 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1201 struct kmap *kmap = map__kmap(map); 1221 struct kmap *kmap = map__kmap(map);
1202 u64 addr; 1222 u64 addr;
1203 1223
1224 if (!kmap)
1225 return -1;
1226
1204 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) 1227 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
1205 return 0; 1228 return 0;
1206 1229
@@ -1859,6 +1882,20 @@ int setup_list(struct strlist **list, const char *list_str,
1859 return 0; 1882 return 0;
1860} 1883}
1861 1884
1885int setup_intlist(struct intlist **list, const char *list_str,
1886 const char *list_name)
1887{
1888 if (list_str == NULL)
1889 return 0;
1890
1891 *list = intlist__new(list_str);
1892 if (!*list) {
1893 pr_err("problems parsing %s list\n", list_name);
1894 return -1;
1895 }
1896 return 0;
1897}
1898
1862static bool symbol__read_kptr_restrict(void) 1899static bool symbol__read_kptr_restrict(void)
1863{ 1900{
1864 bool value = false; 1901 bool value = false;
@@ -1909,9 +1946,17 @@ int symbol__init(struct perf_session_env *env)
1909 symbol_conf.comm_list_str, "comm") < 0) 1946 symbol_conf.comm_list_str, "comm") < 0)
1910 goto out_free_dso_list; 1947 goto out_free_dso_list;
1911 1948
1949 if (setup_intlist(&symbol_conf.pid_list,
1950 symbol_conf.pid_list_str, "pid") < 0)
1951 goto out_free_comm_list;
1952
1953 if (setup_intlist(&symbol_conf.tid_list,
1954 symbol_conf.tid_list_str, "tid") < 0)
1955 goto out_free_pid_list;
1956
1912 if (setup_list(&symbol_conf.sym_list, 1957 if (setup_list(&symbol_conf.sym_list,
1913 symbol_conf.sym_list_str, "symbol") < 0) 1958 symbol_conf.sym_list_str, "symbol") < 0)
1914 goto out_free_comm_list; 1959 goto out_free_tid_list;
1915 1960
1916 /* 1961 /*
1917 * A path to symbols of "/" is identical to "" 1962 * A path to symbols of "/" is identical to ""
@@ -1930,6 +1975,10 @@ int symbol__init(struct perf_session_env *env)
1930 symbol_conf.initialized = true; 1975 symbol_conf.initialized = true;
1931 return 0; 1976 return 0;
1932 1977
1978out_free_tid_list:
1979 intlist__delete(symbol_conf.tid_list);
1980out_free_pid_list:
1981 intlist__delete(symbol_conf.pid_list);
1933out_free_comm_list: 1982out_free_comm_list:
1934 strlist__delete(symbol_conf.comm_list); 1983 strlist__delete(symbol_conf.comm_list);
1935out_free_dso_list: 1984out_free_dso_list:
@@ -1944,6 +1993,8 @@ void symbol__exit(void)
1944 strlist__delete(symbol_conf.sym_list); 1993 strlist__delete(symbol_conf.sym_list);
1945 strlist__delete(symbol_conf.dso_list); 1994 strlist__delete(symbol_conf.dso_list);
1946 strlist__delete(symbol_conf.comm_list); 1995 strlist__delete(symbol_conf.comm_list);
1996 intlist__delete(symbol_conf.tid_list);
1997 intlist__delete(symbol_conf.pid_list);
1947 vmlinux_path__exit(); 1998 vmlinux_path__exit();
1948 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 1999 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
1949 symbol_conf.initialized = false; 2000 symbol_conf.initialized = false;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 1650dcb3a67b..09561500164a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -78,6 +78,7 @@ static inline size_t symbol__size(const struct symbol *sym)
78} 78}
79 79
80struct strlist; 80struct strlist;
81struct intlist;
81 82
82struct symbol_conf { 83struct symbol_conf {
83 unsigned short priv_size; 84 unsigned short priv_size;
@@ -87,6 +88,7 @@ struct symbol_conf {
87 ignore_vmlinux_buildid, 88 ignore_vmlinux_buildid,
88 show_kernel_path, 89 show_kernel_path,
89 use_modules, 90 use_modules,
91 allow_aliases,
90 sort_by_name, 92 sort_by_name,
91 show_nr_samples, 93 show_nr_samples,
92 show_total_period, 94 show_total_period,
@@ -114,6 +116,8 @@ struct symbol_conf {
114 const char *guestmount; 116 const char *guestmount;
115 const char *dso_list_str, 117 const char *dso_list_str,
116 *comm_list_str, 118 *comm_list_str,
119 *pid_list_str,
120 *tid_list_str,
117 *sym_list_str, 121 *sym_list_str,
118 *col_width_list_str; 122 *col_width_list_str;
119 struct strlist *dso_list, 123 struct strlist *dso_list,
@@ -123,6 +127,8 @@ struct symbol_conf {
123 *dso_to_list, 127 *dso_to_list,
124 *sym_from_list, 128 *sym_from_list,
125 *sym_to_list; 129 *sym_to_list;
130 struct intlist *pid_list,
131 *tid_list;
126 const char *symfs; 132 const char *symfs;
127}; 133};
128 134
@@ -294,5 +300,7 @@ int compare_proc_modules(const char *from, const char *to);
294 300
295int setup_list(struct strlist **list, const char *list_str, 301int setup_list(struct strlist **list, const char *list_str,
296 const char *list_name); 302 const char *list_name);
303int setup_intlist(struct intlist **list, const char *list_str,
304 const char *list_name);
297 305
298#endif /* __PERF_SYMBOL */ 306#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index e74c5963dc7a..a53603b27e52 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -123,11 +123,8 @@ int target__strerror(struct target *target, int errnum,
123 if (errnum >= 0) { 123 if (errnum >= 0) {
124 const char *err = strerror_r(errnum, buf, buflen); 124 const char *err = strerror_r(errnum, buf, buflen);
125 125
126 if (err != buf) { 126 if (err != buf)
127 size_t len = strlen(err); 127 scnprintf(buf, buflen, "%s", err);
128 memcpy(buf, err, min(buflen - 1, len));
129 *(buf + min(buflen - 1, len)) = '\0';
130 }
131 128
132 return 0; 129 return 0;
133 } 130 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 9ebc8b1f9be5..1c8fbc9588c5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -82,6 +82,20 @@ void thread__delete(struct thread *thread)
82 free(thread); 82 free(thread);
83} 83}
84 84
85struct thread *thread__get(struct thread *thread)
86{
87 ++thread->refcnt;
88 return thread;
89}
90
91void thread__put(struct thread *thread)
92{
93 if (thread && --thread->refcnt == 0) {
94 list_del_init(&thread->node);
95 thread__delete(thread);
96 }
97}
98
85struct comm *thread__comm(const struct thread *thread) 99struct comm *thread__comm(const struct thread *thread)
86{ 100{
87 if (list_empty(&thread->comm_list)) 101 if (list_empty(&thread->comm_list))
@@ -192,7 +206,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
192 err = thread__set_comm(thread, comm, timestamp); 206 err = thread__set_comm(thread, comm, timestamp);
193 if (err) 207 if (err)
194 return err; 208 return err;
195 thread->comm_set = true;
196 } 209 }
197 210
198 thread->ppid = parent->tid; 211 thread->ppid = parent->tid;
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 160fd066a7d1..9b8a54dc34a8 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -7,6 +7,7 @@
7#include <sys/types.h> 7#include <sys/types.h>
8#include "symbol.h" 8#include "symbol.h"
9#include <strlist.h> 9#include <strlist.h>
10#include <intlist.h>
10 11
11struct thread_stack; 12struct thread_stack;
12 13
@@ -20,6 +21,7 @@ struct thread {
20 pid_t tid; 21 pid_t tid;
21 pid_t ppid; 22 pid_t ppid;
22 int cpu; 23 int cpu;
24 int refcnt;
23 char shortname[3]; 25 char shortname[3];
24 bool comm_set; 26 bool comm_set;
25 bool dead; /* if set thread has exited */ 27 bool dead; /* if set thread has exited */
@@ -37,6 +39,18 @@ struct comm;
37struct thread *thread__new(pid_t pid, pid_t tid); 39struct thread *thread__new(pid_t pid, pid_t tid);
38int thread__init_map_groups(struct thread *thread, struct machine *machine); 40int thread__init_map_groups(struct thread *thread, struct machine *machine);
39void thread__delete(struct thread *thread); 41void thread__delete(struct thread *thread);
42
43struct thread *thread__get(struct thread *thread);
44void thread__put(struct thread *thread);
45
46static inline void __thread__zput(struct thread **thread)
47{
48 thread__put(*thread);
49 *thread = NULL;
50}
51
52#define thread__zput(thread) __thread__zput(&thread)
53
40static inline void thread__exited(struct thread *thread) 54static inline void thread__exited(struct thread *thread)
41{ 55{
42 thread->dead = true; 56 thread->dead = true;
@@ -87,6 +101,16 @@ static inline bool thread__is_filtered(struct thread *thread)
87 return true; 101 return true;
88 } 102 }
89 103
104 if (symbol_conf.pid_list &&
105 !intlist__has_entry(symbol_conf.pid_list, thread->pid_)) {
106 return true;
107 }
108
109 if (symbol_conf.tid_list &&
110 !intlist__has_entry(symbol_conf.tid_list, thread->tid)) {
111 return true;
112 }
113
90 return false; 114 return false;
91} 115}
92 116
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index bb2708bbfaca..51d9e56c0f84 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -10,6 +10,7 @@ struct perf_evsel;
10struct perf_sample; 10struct perf_sample;
11struct perf_tool; 11struct perf_tool;
12struct machine; 12struct machine;
13struct ordered_events;
13 14
14typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event, 15typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
15 struct perf_sample *sample, 16 struct perf_sample *sample,
@@ -25,6 +26,9 @@ typedef int (*event_attr_op)(struct perf_tool *tool,
25typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event, 26typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
26 struct perf_session *session); 27 struct perf_session *session);
27 28
29typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
30 struct ordered_events *oe);
31
28struct perf_tool { 32struct perf_tool {
29 event_sample sample, 33 event_sample sample,
30 read; 34 read;
@@ -38,8 +42,8 @@ struct perf_tool {
38 unthrottle; 42 unthrottle;
39 event_attr_op attr; 43 event_attr_op attr;
40 event_op2 tracing_data; 44 event_op2 tracing_data;
41 event_op2 finished_round, 45 event_oe finished_round;
42 build_id, 46 event_op2 build_id,
43 id_index; 47 id_index;
44 bool ordered_events; 48 bool ordered_events;
45 bool ordering_requires_timestamps; 49 bool ordering_requires_timestamps;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index c36636fd825b..25d6c737be3e 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -112,8 +112,8 @@ unsigned long long read_size(struct event_format *event, void *ptr, int size)
112 return pevent_read_number(event->pevent, ptr, size); 112 return pevent_read_number(event->pevent, ptr, size);
113} 113}
114 114
115void event_format__print(struct event_format *event, 115void event_format__fprintf(struct event_format *event,
116 int cpu, void *data, int size) 116 int cpu, void *data, int size, FILE *fp)
117{ 117{
118 struct pevent_record record; 118 struct pevent_record record;
119 struct trace_seq s; 119 struct trace_seq s;
@@ -125,10 +125,16 @@ void event_format__print(struct event_format *event,
125 125
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_fprintf(&s, fp);
129 trace_seq_destroy(&s); 129 trace_seq_destroy(&s);
130} 130}
131 131
132void event_format__print(struct event_format *event,
133 int cpu, void *data, int size)
134{
135 return event_format__fprintf(event, cpu, data, size, stdout);
136}
137
132void parse_proc_kallsyms(struct pevent *pevent, 138void parse_proc_kallsyms(struct pevent *pevent,
133 char *file, unsigned int size __maybe_unused) 139 char *file, unsigned int size __maybe_unused)
134{ 140{
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 5c9bdd1591a9..9df61059a85d 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -43,7 +43,6 @@ static int stop_script_unsupported(void)
43static void process_event_unsupported(union perf_event *event __maybe_unused, 43static void process_event_unsupported(union perf_event *event __maybe_unused,
44 struct perf_sample *sample __maybe_unused, 44 struct perf_sample *sample __maybe_unused,
45 struct perf_evsel *evsel __maybe_unused, 45 struct perf_evsel *evsel __maybe_unused,
46 struct thread *thread __maybe_unused,
47 struct addr_location *al __maybe_unused) 46 struct addr_location *al __maybe_unused)
48{ 47{
49} 48}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 52aaa19e1eb1..d5168f0be4ec 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -23,6 +23,9 @@ trace_event__tp_format(const char *sys, const char *name);
23 23
24int bigendian(void); 24int bigendian(void);
25 25
26void event_format__fprintf(struct event_format *event,
27 int cpu, void *data, int size, FILE *fp);
28
26void event_format__print(struct event_format *event, 29void event_format__print(struct event_format *event,
27 int cpu, void *data, int size); 30 int cpu, void *data, int size);
28 31
@@ -69,8 +72,7 @@ struct scripting_ops {
69 void (*process_event) (union perf_event *event, 72 void (*process_event) (union perf_event *event,
70 struct perf_sample *sample, 73 struct perf_sample *sample,
71 struct perf_evsel *evsel, 74 struct perf_evsel *evsel,
72 struct thread *thread, 75 struct addr_location *al);
73 struct addr_location *al);
74 int (*generate_script) (struct pevent *pevent, const char *outfile); 76 int (*generate_script) (struct pevent *pevent, const char *outfile);
75}; 77};
76 78
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index e3c40a520a25..7b09a443a280 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -266,7 +266,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
266 u64 *fde_count) 266 u64 *fde_count)
267{ 267{
268 int ret = -EINVAL, fd; 268 int ret = -EINVAL, fd;
269 u64 offset = dso->data.frame_offset; 269 u64 offset = dso->data.eh_frame_hdr_offset;
270 270
271 if (offset == 0) { 271 if (offset == 0) {
272 fd = dso__data_fd(dso, machine); 272 fd = dso__data_fd(dso, machine);
@@ -275,7 +275,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
275 275
276 /* Check the .eh_frame section for unwinding info */ 276 /* Check the .eh_frame section for unwinding info */
277 offset = elf_section_offset(fd, ".eh_frame_hdr"); 277 offset = elf_section_offset(fd, ".eh_frame_hdr");
278 dso->data.frame_offset = offset; 278 dso->data.eh_frame_hdr_offset = offset;
279 } 279 }
280 280
281 if (offset) 281 if (offset)
@@ -291,7 +291,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
291 struct machine *machine, u64 *offset) 291 struct machine *machine, u64 *offset)
292{ 292{
293 int fd; 293 int fd;
294 u64 ofs = dso->data.frame_offset; 294 u64 ofs = dso->data.debug_frame_offset;
295 295
296 if (ofs == 0) { 296 if (ofs == 0) {
297 fd = dso__data_fd(dso, machine); 297 fd = dso__data_fd(dso, machine);
@@ -300,7 +300,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
300 300
301 /* Check the .debug_frame section for unwinding info */ 301 /* Check the .debug_frame section for unwinding info */
302 ofs = elf_section_offset(fd, ".debug_frame"); 302 ofs = elf_section_offset(fd, ".debug_frame");
303 dso->data.frame_offset = ofs; 303 dso->data.debug_frame_offset = ofs;
304 } 304 }
305 305
306 *offset = ofs; 306 *offset = ofs;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index b86744f29eef..4ee6d0d4c993 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -269,6 +269,13 @@ void dump_stack(void)
269void dump_stack(void) {} 269void dump_stack(void) {}
270#endif 270#endif
271 271
272void sighandler_dump_stack(int sig)
273{
274 psignal(sig, "perf");
275 dump_stack();
276 exit(sig);
277}
278
272void get_term_dimensions(struct winsize *ws) 279void get_term_dimensions(struct winsize *ws)
273{ 280{
274 char *s = getenv("LINES"); 281 char *s = getenv("LINES");
@@ -303,13 +310,26 @@ void set_term_quiet_input(struct termios *old)
303 tcsetattr(0, TCSANOW, &tc); 310 tcsetattr(0, TCSANOW, &tc);
304} 311}
305 312
306static void set_tracing_events_path(const char *mountpoint) 313static void set_tracing_events_path(const char *tracing, const char *mountpoint)
307{ 314{
308 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 315 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
309 mountpoint, "tracing/events"); 316 mountpoint, tracing, "events");
310} 317}
311 318
312const char *perf_debugfs_mount(const char *mountpoint) 319static const char *__perf_tracefs_mount(const char *mountpoint)
320{
321 const char *mnt;
322
323 mnt = tracefs_mount(mountpoint);
324 if (!mnt)
325 return NULL;
326
327 set_tracing_events_path("", mnt);
328
329 return mnt;
330}
331
332static const char *__perf_debugfs_mount(const char *mountpoint)
313{ 333{
314 const char *mnt; 334 const char *mnt;
315 335
@@ -317,7 +337,20 @@ const char *perf_debugfs_mount(const char *mountpoint)
317 if (!mnt) 337 if (!mnt)
318 return NULL; 338 return NULL;
319 339
320 set_tracing_events_path(mnt); 340 set_tracing_events_path("tracing/", mnt);
341
342 return mnt;
343}
344
345const char *perf_debugfs_mount(const char *mountpoint)
346{
347 const char *mnt;
348
349 mnt = __perf_tracefs_mount(mountpoint);
350 if (mnt)
351 return mnt;
352
353 mnt = __perf_debugfs_mount(mountpoint);
321 354
322 return mnt; 355 return mnt;
323} 356}
@@ -325,12 +358,19 @@ const char *perf_debugfs_mount(const char *mountpoint)
325void perf_debugfs_set_path(const char *mntpt) 358void perf_debugfs_set_path(const char *mntpt)
326{ 359{
327 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt); 360 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
328 set_tracing_events_path(mntpt); 361 set_tracing_events_path("tracing/", mntpt);
362}
363
364static const char *find_tracefs(void)
365{
366 const char *path = __perf_tracefs_mount(NULL);
367
368 return path;
329} 369}
330 370
331static const char *find_debugfs(void) 371static const char *find_debugfs(void)
332{ 372{
333 const char *path = perf_debugfs_mount(NULL); 373 const char *path = __perf_debugfs_mount(NULL);
334 374
335 if (!path) 375 if (!path)
336 fprintf(stderr, "Your kernel does not support the debugfs filesystem"); 376 fprintf(stderr, "Your kernel does not support the debugfs filesystem");
@@ -344,6 +384,7 @@ static const char *find_debugfs(void)
344 */ 384 */
345const char *find_tracing_dir(void) 385const char *find_tracing_dir(void)
346{ 386{
387 const char *tracing_dir = "";
347 static char *tracing; 388 static char *tracing;
348 static int tracing_found; 389 static int tracing_found;
349 const char *debugfs; 390 const char *debugfs;
@@ -351,11 +392,15 @@ const char *find_tracing_dir(void)
351 if (tracing_found) 392 if (tracing_found)
352 return tracing; 393 return tracing;
353 394
354 debugfs = find_debugfs(); 395 debugfs = find_tracefs();
355 if (!debugfs) 396 if (!debugfs) {
356 return NULL; 397 tracing_dir = "/tracing";
398 debugfs = find_debugfs();
399 if (!debugfs)
400 return NULL;
401 }
357 402
358 if (asprintf(&tracing, "%s/tracing", debugfs) < 0) 403 if (asprintf(&tracing, "%s%s", debugfs, tracing_dir) < 0)
359 return NULL; 404 return NULL;
360 405
361 tracing_found = 1; 406 tracing_found = 1;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 027a5153495c..1ff23e04ad27 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -75,6 +75,7 @@
75#include <linux/types.h> 75#include <linux/types.h>
76#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
77#include <api/fs/debugfs.h> 77#include <api/fs/debugfs.h>
78#include <api/fs/tracefs.h>
78#include <termios.h> 79#include <termios.h>
79#include <linux/bitops.h> 80#include <linux/bitops.h>
80#include <termios.h> 81#include <termios.h>
@@ -276,6 +277,7 @@ char *ltrim(char *s);
276char *rtrim(char *s); 277char *rtrim(char *s);
277 278
278void dump_stack(void); 279void dump_stack(void);
280void sighandler_dump_stack(int sig);
279 281
280extern unsigned int page_size; 282extern unsigned int page_size;
281extern int cacheline_size; 283extern int cacheline_size;
@@ -327,4 +329,8 @@ bool find_process(const char *name);
327int gzip_decompress_to_file(const char *input, int output_fd); 329int gzip_decompress_to_file(const char *input, int output_fd);
328#endif 330#endif
329 331
332#ifdef HAVE_LZMA_SUPPORT
333int lzma_decompress_to_file(const char *input, int output_fd);
334#endif
335
330#endif /* GIT_COMPAT_UTIL_H */ 336#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
index 92f1fd700344..db15c9d2049e 100644
--- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -1156,7 +1156,7 @@ osl_table_name_from_file(char *filename, char *signature, u32 *instance)
1156 /* Extract instance number */ 1156 /* Extract instance number */
1157 1157
1158 if (isdigit((int)filename[ACPI_NAME_SIZE])) { 1158 if (isdigit((int)filename[ACPI_NAME_SIZE])) {
1159 sscanf(&filename[ACPI_NAME_SIZE], "%d", instance); 1159 sscanf(&filename[ACPI_NAME_SIZE], "%u", instance);
1160 } else if (strlen(filename) != ACPI_NAME_SIZE) { 1160 } else if (strlen(filename) != ACPI_NAME_SIZE) {
1161 return (AE_BAD_SIGNATURE); 1161 return (AE_BAD_SIGNATURE);
1162 } else { 1162 } else {
diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c
index 3853a7350440..0b1fa290245a 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixmap.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c
@@ -146,6 +146,6 @@ void acpi_os_unmap_memory(void *where, acpi_size length)
146 acpi_size page_size; 146 acpi_size page_size;
147 147
148 page_size = acpi_os_get_page_size(); 148 page_size = acpi_os_get_page_size();
149 offset = (acpi_physical_address) where % page_size; 149 offset = ACPI_TO_INTEGER(where) % page_size;
150 munmap((u8 *)where - offset, (length + offset)); 150 munmap((u8 *)where - offset, (length + offset));
151} 151}
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index 3ed7c0476d48..2e2ba2efa0d9 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -209,7 +209,7 @@ $(OUTPUT)%.o: %.c
209 209
210$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ) 210$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ)
211 $(ECHO) " CC " $@ 211 $(ECHO) " CC " $@
212 $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lcpupower -Wl,-rpath=./ -lrt -lpci -L$(OUTPUT) -o $@ 212 $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lcpupower -lrt -lpci -L$(OUTPUT) -o $@
213 $(QUIET) $(STRIPCMD) $@ 213 $(QUIET) $(STRIPCMD) $@
214 214
215$(OUTPUT)po/$(PACKAGE).pot: $(UTIL_SRC) 215$(OUTPUT)po/$(PACKAGE).pot: $(UTIL_SRC)
diff --git a/tools/power/cpupower/utils/helpers/pci.c b/tools/power/cpupower/utils/helpers/pci.c
index 9690798e6446..8b278983cfc5 100644
--- a/tools/power/cpupower/utils/helpers/pci.c
+++ b/tools/power/cpupower/utils/helpers/pci.c
@@ -25,14 +25,21 @@
25struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus, 25struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus,
26 int slot, int func, int vendor, int dev) 26 int slot, int func, int vendor, int dev)
27{ 27{
28 struct pci_filter filter_nb_link = { domain, bus, slot, func, 28 struct pci_filter filter_nb_link;
29 vendor, dev };
30 struct pci_dev *device; 29 struct pci_dev *device;
31 30
32 *pacc = pci_alloc(); 31 *pacc = pci_alloc();
33 if (*pacc == NULL) 32 if (*pacc == NULL)
34 return NULL; 33 return NULL;
35 34
35 pci_filter_init(*pacc, &filter_nb_link);
36 filter_nb_link.domain = domain;
37 filter_nb_link.bus = bus;
38 filter_nb_link.slot = slot;
39 filter_nb_link.func = func;
40 filter_nb_link.vendor = vendor;
41 filter_nb_link.device = dev;
42
36 pci_init(*pacc); 43 pci_init(*pacc);
37 pci_scan_bus(*pacc); 44 pci_scan_bus(*pacc);
38 45
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index d1b3a361e526..4039854560d0 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -1,8 +1,12 @@
1CC = $(CROSS_COMPILE)gcc 1CC = $(CROSS_COMPILE)gcc
2BUILD_OUTPUT := $(PWD) 2BUILD_OUTPUT := $(CURDIR)
3PREFIX := /usr 3PREFIX := /usr
4DESTDIR := 4DESTDIR :=
5 5
6ifeq ("$(origin O)", "command line")
7 BUILD_OUTPUT := $(O)
8endif
9
6turbostat : turbostat.c 10turbostat : turbostat.c
7CFLAGS += -Wall 11CFLAGS += -Wall
8CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"' 12CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/uapi/asm/msr-index.h"'
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index feea7ad9500b..05b8fc38dc8b 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -20,9 +20,11 @@ upon its completion.
20The second method is to omit the command, 20The second method is to omit the command,
21and turbostat displays statistics every 5 seconds. 21and turbostat displays statistics every 5 seconds.
22The 5-second interval can be changed using the --interval option. 22The 5-second interval can be changed using the --interval option.
23 23.PP
24Some information is not available on older processors. 24Some information is not available on older processors.
25.SS Options 25.SS Options
26Options can be specified with a single or double '-', and only as much of the option
27name as necessary to disambiguate it from others is necessary. Note that options are case-sensitive.
26\fB--Counter MSR#\fP shows the delta of the specified 64-bit MSR counter. 28\fB--Counter MSR#\fP shows the delta of the specified 64-bit MSR counter.
27.PP 29.PP
28\fB--counter MSR#\fP shows the delta of the specified 32-bit MSR counter. 30\fB--counter MSR#\fP shows the delta of the specified 32-bit MSR counter.
@@ -55,16 +57,20 @@ more than once may also enable internal turbostat debug information.
55The \fBcommand\fP parameter forks \fBcommand\fP, and upon its exit, 57The \fBcommand\fP parameter forks \fBcommand\fP, and upon its exit,
56displays the statistics gathered since it was forked. 58displays the statistics gathered since it was forked.
57.PP 59.PP
58.SH FIELD DESCRIPTIONS 60.SH DEFAULT FIELD DESCRIPTIONS
59.nf 61.nf
60\fBPackage\fP processor package number. 62\fBCPU\fP Linux CPU (logical processor) number. Yes, it is okay that on many systems the CPUs are not listed in numerical order -- for efficiency reasons, turbostat runs in topology order, so HT siblings appear together.
61\fBCore\fP processor core number.
62\fBCPU\fP Linux CPU (logical processor) number.
63Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology.
64\fBAVG_MHz\fP number of cycles executed divided by time elapsed. 63\fBAVG_MHz\fP number of cycles executed divided by time elapsed.
65\fB%Busy\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state. 64\fB%Busy\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state.
66\fBBzy_MHz\fP average clock rate while the CPU was busy (in "c0" state). 65\fBBzy_MHz\fP average clock rate while the CPU was busy (in "c0" state).
67\fBTSC_MHz\fP average MHz that the TSC ran during the entire interval. 66\fBTSC_MHz\fP average MHz that the TSC ran during the entire interval.
67.fi
68.PP
69.SH DEBUG FIELD DESCRIPTIONS
70.nf
71\fBPackage\fP processor package number.
72\fBCore\fP processor core number.
73Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology (HT).
68\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states. 74\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states.
69\fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor. 75\fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor.
70\fBPkgTtmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor. 76\fBPkgTtmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor.
@@ -81,63 +87,76 @@ Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading T
81Without any parameters, turbostat displays statistics ever 5 seconds. 87Without any parameters, turbostat displays statistics ever 5 seconds.
82(override interval with "-i sec" option, or specify a command 88(override interval with "-i sec" option, or specify a command
83for turbostat to fork). 89for turbostat to fork).
90.nf
91[root@hsw]# ./turbostat
92 CPU Avg_MHz %Busy Bzy_MHz TSC_MHz
93 - 488 12.51 3898 3498
94 0 0 0.01 3885 3498
95 4 3897 99.99 3898 3498
96 1 0 0.00 3861 3498
97 5 0 0.00 3882 3498
98 2 1 0.02 3894 3498
99 6 2 0.06 3898 3498
100 3 0 0.00 3849 3498
101 7 0 0.00 3877 3498
102
103.fi
104.SH DEBUG EXAMPLE
105The "--debug" option prints additional system information before measurements:
84 106
85The first row of statistics is a summary for the entire system. 107The first row of statistics is a summary for the entire system.
86For residency % columns, the summary is a weighted average. 108For residency % columns, the summary is a weighted average.
87For Temperature columns, the summary is the column maximum. 109For Temperature columns, the summary is the column maximum.
88For Watts columns, the summary is a system total. 110For Watts columns, the summary is a system total.
89Subsequent rows show per-CPU statistics. 111Subsequent rows show per-CPU statistics.
90
91.nf
92[root@ivy]# ./turbostat
93 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
94 - - 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
95 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
96 0 4 1 0.07 1596 3492 0 0.79
97 1 1 10 0.65 1596 3492 0 0.59 0.00 98.76 0.00 23
98 1 5 5 0.28 1596 3492 0 0.95
99 2 2 10 0.66 1596 3492 0 0.41 0.01 98.92 0.00 23
100 2 6 2 0.10 1597 3492 0 0.97
101 3 3 3 0.20 1596 3492 0 0.44 0.00 99.37 0.00 23
102 3 7 5 0.31 1596 3492 0 0.33
103.fi
104.SH DEBUG EXAMPLE
105The "--debug" option prints additional system information before measurements:
106
107.nf 112.nf
108turbostat version 4.0 10-Feb, 2015 - Len Brown <lenb@kernel.org> 113turbostat version 4.1 10-Feb, 2015 - Len Brown <lenb@kernel.org>
109CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:3a:9 (6:58:9) 114CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:3c:3 (6:60:3)
110CPUID(6): APERF, DTS, PTM, EPB 115CPUID(6): APERF, DTS, PTM, EPB
111RAPL: 851 sec. Joule Counter Range, at 77 Watts 116RAPL: 3121 sec. Joule Counter Range, at 84 Watts
112cpu0: MSR_NHM_PLATFORM_INFO: 0x81010f0012300 117cpu0: MSR_NHM_PLATFORM_INFO: 0x80838f3012300
11316 * 100 = 1600 MHz max efficiency 1188 * 100 = 800 MHz max efficiency
11435 * 100 = 3500 MHz TSC frequency 11935 * 100 = 3500 MHz TSC frequency
115cpu0: MSR_IA32_POWER_CTL: 0x0014005d (C1E auto-promotion: DISabled) 120cpu0: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
116cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e008402 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, locked: pkg-cstate-limit=2: pc6n) 121cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0)
117cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x25262727 122cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x25262727
11837 * 100 = 3700 MHz max turbo 4 active cores 12337 * 100 = 3700 MHz max turbo 4 active cores
11938 * 100 = 3800 MHz max turbo 3 active cores 12438 * 100 = 3800 MHz max turbo 3 active cores
12039 * 100 = 3900 MHz max turbo 2 active cores 12539 * 100 = 3900 MHz max turbo 2 active cores
12139 * 100 = 3900 MHz max turbo 1 active cores 12639 * 100 = 3900 MHz max turbo 1 active cores
122cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced) 127cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced)
123cpu0: MSR_RAPL_POWER_UNIT: 0x000a1003 (0.125000 Watts, 0.000015 Joules, 0.000977 sec.) 128cpu0: MSR_CORE_PERF_LIMIT_REASONS, 0x31200000 (Active: ) (Logged: Auto-HWP, Amps, MultiCoreTurbo, Transitions, )
124cpu0: MSR_PKG_POWER_INFO: 0x01e00268 (77 W TDP, RAPL 60 - 0 W, 0.000000 sec.) 129cpu0: MSR_GFX_PERF_LIMIT_REASONS, 0x00000000 (Active: ) (Logged: )
125cpu0: MSR_PKG_POWER_LIMIT: 0x30000148268 (UNlocked) 130cpu0: MSR_RING_PERF_LIMIT_REASONS, 0x0d000000 (Active: ) (Logged: Amps, PkgPwrL1, PkgPwrL2, )
126cpu0: PKG Limit #1: ENabled (77.000000 Watts, 1.000000 sec, clamp DISabled) 131cpu0: MSR_RAPL_POWER_UNIT: 0x000a0e03 (0.125000 Watts, 0.000061 Joules, 0.000977 sec.)
127cpu0: PKG Limit #2: DISabled (96.000000 Watts, 0.000977* sec, clamp DISabled) 132cpu0: MSR_PKG_POWER_INFO: 0x000002a0 (84 W TDP, RAPL 0 - 0 W, 0.000000 sec.)
133cpu0: MSR_PKG_POWER_LIMIT: 0x428348001a82a0 (UNlocked)
134cpu0: PKG Limit #1: ENabled (84.000000 Watts, 8.000000 sec, clamp DISabled)
135cpu0: PKG Limit #2: ENabled (105.000000 Watts, 0.002441* sec, clamp DISabled)
128cpu0: MSR_PP0_POLICY: 0 136cpu0: MSR_PP0_POLICY: 0
129cpu0: MSR_PP0_POWER_LIMIT: 0x00000000 (UNlocked) 137cpu0: MSR_PP0_POWER_LIMIT: 0x00000000 (UNlocked)
130cpu0: Cores Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled) 138cpu0: Cores Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled)
131cpu0: MSR_PP1_POLICY: 0 139cpu0: MSR_PP1_POLICY: 0
132cpu0: MSR_PP1_POWER_LIMIT: 0x00000000 (UNlocked) 140cpu0: MSR_PP1_POWER_LIMIT: 0x00000000 (UNlocked)
133cpu0: GFX Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled) 141cpu0: GFX Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled)
134cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x00691400 (105 C) 142cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x00641400 (100 C)
135cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x884e0000 (27 C) 143cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x88340800 (48 C)
136cpu0: MSR_IA32_THERM_STATUS: 0x88580000 (17 C +/- 1) 144cpu0: MSR_IA32_THERM_STATUS: 0x88340000 (48 C +/- 1)
137cpu1: MSR_IA32_THERM_STATUS: 0x885a0000 (15 C +/- 1) 145cpu1: MSR_IA32_THERM_STATUS: 0x88440000 (32 C +/- 1)
138cpu2: MSR_IA32_THERM_STATUS: 0x88570000 (18 C +/- 1) 146cpu2: MSR_IA32_THERM_STATUS: 0x88450000 (31 C +/- 1)
139cpu3: MSR_IA32_THERM_STATUS: 0x884e0000 (27 C +/- 1) 147cpu3: MSR_IA32_THERM_STATUS: 0x88490000 (27 C +/- 1)
140 ... 148 Core CPU Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp PkgWatt CorWatt GFXWatt
149 - - 493 12.64 3898 3498 0 12.64 0.00 0.00 74.72 47 47 21.62 13.74 0.00
150 0 0 4 0.11 3894 3498 0 99.89 0.00 0.00 0.00 47 47 21.62 13.74 0.00
151 0 4 3897 99.98 3898 3498 0 0.02
152 1 1 7 0.17 3887 3498 0 0.04 0.00 0.00 99.79 32
153 1 5 0 0.00 3885 3498 0 0.21
154 2 2 29 0.76 3895 3498 0 0.10 0.01 0.01 99.13 32
155 2 6 2 0.06 3896 3498 0 0.80
156 3 3 1 0.02 3832 3498 0 0.03 0.00 0.00 99.95 28
157 3 7 0 0.00 3879 3498 0 0.04
158^C
159
141.fi 160.fi
142The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency 161The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency
143available at the minimum package voltage. The \fBTSC frequency\fP is the base 162available at the minimum package voltage. The \fBTSC frequency\fP is the base
@@ -147,6 +166,9 @@ should be sustainable on all CPUs indefinitely, given nominal power and cooling.
147The remaining rows show what maximum turbo frequency is possible 166The remaining rows show what maximum turbo frequency is possible
148depending on the number of idle cores. Note that not all information is 167depending on the number of idle cores. Note that not all information is
149available on all processors. 168available on all processors.
169.PP
170The --debug option adds additional columns to the measurement ouput, including CPU idle power-state residency processor temperature sensor readinds.
171See the field definitions above.
150.SH FORK EXAMPLE 172.SH FORK EXAMPLE
151If turbostat is invoked with a command, it will fork that command 173If turbostat is invoked with a command, it will fork that command
152and output the statistics gathered when the command exits. 174and output the statistics gathered when the command exits.
@@ -154,27 +176,23 @@ 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: 176until ^C while the other CPUs are mostly idle:
155 177
156.nf 178.nf
157root@ivy: turbostat cat /dev/zero > /dev/null 179root@hsw: turbostat cat /dev/zero > /dev/null
158^C 180^C
159 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 181 CPU Avg_MHz %Busy Bzy_MHz TSC_MHz
160 - - 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 182 - 482 12.51 3854 3498
161 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 183 0 0 0.01 1960 3498
162 0 4 9 0.24 3829 3492 0 1.15 184 4 0 0.00 2128 3498
163 1 1 4 0.09 3783 3492 0 99.91 0.00 0.00 0.00 36 185 1 0 0.00 3003 3498
164 1 5 3880 99.82 3888 3492 0 0.18 186 5 3854 99.98 3855 3498
165 2 2 17 0.44 3813 3492 0 0.77 0.04 98.75 0.00 28 187 2 0 0.01 3504 3498
166 2 6 12 0.32 3823 3492 0 0.89 188 6 3 0.08 3884 3498
167 3 3 16 0.43 3844 3492 0 0.63 0.11 98.84 0.00 30 189 3 0 0.00 2553 3498
168 3 7 4 0.11 3827 3492 0 0.94 190 7 0 0.00 2126 3498
16930.372243 sec 19110.783983 sec
170 192
171.fi 193.fi
172Above the cycle soaker drives cpu5 up its 3.8 GHz turbo limit 194Above the cycle soaker drives cpu5 up its 3.9 GHz turbo limit.
173while the other processors are generally in various states of idle. 195The first row shows the average MHz and %Busy across all the processors in the system.
174
175Note that cpu1 and cpu5 are HT siblings within core1.
176As cpu5 is very busy, it prevents its sibling, cpu1,
177from entering a c-state deeper than c1.
178 196
179Note that the Avg_MHz column reflects the total number of cycles executed 197Note that the Avg_MHz column reflects the total number of cycles executed
180divided by the measurement interval. If the %Busy column is 100%, 198divided by the measurement interval. If the %Busy column is 100%,
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 2d089cac8580..bac98ca3d4ca 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -57,6 +57,7 @@ unsigned int do_pc3;
57unsigned int do_pc6; 57unsigned int do_pc6;
58unsigned int do_pc7; 58unsigned int do_pc7;
59unsigned int do_c8_c9_c10; 59unsigned int do_c8_c9_c10;
60unsigned int do_skl_residency;
60unsigned int do_slm_cstates; 61unsigned int do_slm_cstates;
61unsigned int use_c1_residency_msr; 62unsigned int use_c1_residency_msr;
62unsigned int has_aperf; 63unsigned int has_aperf;
@@ -65,8 +66,6 @@ unsigned int units = 1000000; /* MHz etc */
65unsigned int genuine_intel; 66unsigned int genuine_intel;
66unsigned int has_invariant_tsc; 67unsigned int has_invariant_tsc;
67unsigned int do_nhm_platform_info; 68unsigned int do_nhm_platform_info;
68unsigned int do_nhm_turbo_ratio_limit;
69unsigned int do_ivt_turbo_ratio_limit;
70unsigned int extra_msr_offset32; 69unsigned int extra_msr_offset32;
71unsigned int extra_msr_offset64; 70unsigned int extra_msr_offset64;
72unsigned int extra_delta_offset32; 71unsigned int extra_delta_offset32;
@@ -84,11 +83,14 @@ unsigned int do_dts;
84unsigned int do_ptm; 83unsigned int do_ptm;
85unsigned int tcc_activation_temp; 84unsigned int tcc_activation_temp;
86unsigned int tcc_activation_temp_override; 85unsigned int tcc_activation_temp_override;
87double rapl_power_units, rapl_energy_units, rapl_time_units; 86double rapl_power_units, rapl_time_units;
87double rapl_dram_energy_units, rapl_energy_units;
88double rapl_joule_counter_range; 88double rapl_joule_counter_range;
89unsigned int do_core_perf_limit_reasons; 89unsigned int do_core_perf_limit_reasons;
90unsigned int do_gfx_perf_limit_reasons; 90unsigned int do_gfx_perf_limit_reasons;
91unsigned int do_ring_perf_limit_reasons; 91unsigned int do_ring_perf_limit_reasons;
92unsigned int crystal_hz;
93unsigned long long tsc_hz;
92 94
93#define RAPL_PKG (1 << 0) 95#define RAPL_PKG (1 << 0)
94 /* 0x610 MSR_PKG_POWER_LIMIT */ 96 /* 0x610 MSR_PKG_POWER_LIMIT */
@@ -101,18 +103,18 @@ unsigned int do_ring_perf_limit_reasons;
101#define RAPL_DRAM (1 << 3) 103#define RAPL_DRAM (1 << 3)
102 /* 0x618 MSR_DRAM_POWER_LIMIT */ 104 /* 0x618 MSR_DRAM_POWER_LIMIT */
103 /* 0x619 MSR_DRAM_ENERGY_STATUS */ 105 /* 0x619 MSR_DRAM_ENERGY_STATUS */
104 /* 0x61c MSR_DRAM_POWER_INFO */
105#define RAPL_DRAM_PERF_STATUS (1 << 4) 106#define RAPL_DRAM_PERF_STATUS (1 << 4)
106 /* 0x61b MSR_DRAM_PERF_STATUS */ 107 /* 0x61b MSR_DRAM_PERF_STATUS */
108#define RAPL_DRAM_POWER_INFO (1 << 5)
109 /* 0x61c MSR_DRAM_POWER_INFO */
107 110
108#define RAPL_CORES (1 << 5) 111#define RAPL_CORES (1 << 6)
109 /* 0x638 MSR_PP0_POWER_LIMIT */ 112 /* 0x638 MSR_PP0_POWER_LIMIT */
110 /* 0x639 MSR_PP0_ENERGY_STATUS */ 113 /* 0x639 MSR_PP0_ENERGY_STATUS */
111#define RAPL_CORE_POLICY (1 << 6) 114#define RAPL_CORE_POLICY (1 << 7)
112 /* 0x63a MSR_PP0_POLICY */ 115 /* 0x63a MSR_PP0_POLICY */
113 116
114 117#define RAPL_GFX (1 << 8)
115#define RAPL_GFX (1 << 7)
116 /* 0x640 MSR_PP1_POWER_LIMIT */ 118 /* 0x640 MSR_PP1_POWER_LIMIT */
117 /* 0x641 MSR_PP1_ENERGY_STATUS */ 119 /* 0x641 MSR_PP1_ENERGY_STATUS */
118 /* 0x642 MSR_PP1_POLICY */ 120 /* 0x642 MSR_PP1_POLICY */
@@ -159,6 +161,10 @@ struct pkg_data {
159 unsigned long long pc8; 161 unsigned long long pc8;
160 unsigned long long pc9; 162 unsigned long long pc9;
161 unsigned long long pc10; 163 unsigned long long pc10;
164 unsigned long long pkg_wtd_core_c0;
165 unsigned long long pkg_any_core_c0;
166 unsigned long long pkg_any_gfxe_c0;
167 unsigned long long pkg_both_core_gfxe_c0;
162 unsigned int package_id; 168 unsigned int package_id;
163 unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */ 169 unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */
164 unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */ 170 unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */
@@ -292,8 +298,7 @@ void print_header(void)
292 if (has_aperf) 298 if (has_aperf)
293 outp += sprintf(outp, " Bzy_MHz"); 299 outp += sprintf(outp, " Bzy_MHz");
294 outp += sprintf(outp, " TSC_MHz"); 300 outp += sprintf(outp, " TSC_MHz");
295 if (do_smi) 301
296 outp += sprintf(outp, " SMI");
297 if (extra_delta_offset32) 302 if (extra_delta_offset32)
298 outp += sprintf(outp, " count 0x%03X", extra_delta_offset32); 303 outp += sprintf(outp, " count 0x%03X", extra_delta_offset32);
299 if (extra_delta_offset64) 304 if (extra_delta_offset64)
@@ -302,6 +307,13 @@ void print_header(void)
302 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32); 307 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32);
303 if (extra_msr_offset64) 308 if (extra_msr_offset64)
304 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64); 309 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
310
311 if (!debug)
312 goto done;
313
314 if (do_smi)
315 outp += sprintf(outp, " SMI");
316
305 if (do_nhm_cstates) 317 if (do_nhm_cstates)
306 outp += sprintf(outp, " CPU%%c1"); 318 outp += sprintf(outp, " CPU%%c1");
307 if (do_nhm_cstates && !do_slm_cstates) 319 if (do_nhm_cstates && !do_slm_cstates)
@@ -316,6 +328,13 @@ void print_header(void)
316 if (do_ptm) 328 if (do_ptm)
317 outp += sprintf(outp, " PkgTmp"); 329 outp += sprintf(outp, " PkgTmp");
318 330
331 if (do_skl_residency) {
332 outp += sprintf(outp, " Totl%%C0");
333 outp += sprintf(outp, " Any%%C0");
334 outp += sprintf(outp, " GFX%%C0");
335 outp += sprintf(outp, " CPUGFX%%");
336 }
337
319 if (do_pc2) 338 if (do_pc2)
320 outp += sprintf(outp, " Pkg%%pc2"); 339 outp += sprintf(outp, " Pkg%%pc2");
321 if (do_pc3) 340 if (do_pc3)
@@ -359,6 +378,7 @@ void print_header(void)
359 outp += sprintf(outp, " time"); 378 outp += sprintf(outp, " time");
360 379
361 } 380 }
381 done:
362 outp += sprintf(outp, "\n"); 382 outp += sprintf(outp, "\n");
363} 383}
364 384
@@ -396,6 +416,12 @@ int dump_counters(struct thread_data *t, struct core_data *c,
396 416
397 if (p) { 417 if (p) {
398 outp += sprintf(outp, "package: %d\n", p->package_id); 418 outp += sprintf(outp, "package: %d\n", p->package_id);
419
420 outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0);
421 outp += sprintf(outp, "Any cores: %016llX\n", p->pkg_any_core_c0);
422 outp += sprintf(outp, "Any GFX: %016llX\n", p->pkg_any_gfxe_c0);
423 outp += sprintf(outp, "CPU + GFX: %016llX\n", p->pkg_both_core_gfxe_c0);
424
399 outp += sprintf(outp, "pc2: %016llX\n", p->pc2); 425 outp += sprintf(outp, "pc2: %016llX\n", p->pc2);
400 if (do_pc3) 426 if (do_pc3)
401 outp += sprintf(outp, "pc3: %016llX\n", p->pc3); 427 outp += sprintf(outp, "pc3: %016llX\n", p->pc3);
@@ -487,10 +513,6 @@ int format_counters(struct thread_data *t, struct core_data *c,
487 /* TSC_MHz */ 513 /* TSC_MHz */
488 outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float); 514 outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float);
489 515
490 /* SMI */
491 if (do_smi)
492 outp += sprintf(outp, "%8d", t->smi_count);
493
494 /* delta */ 516 /* delta */
495 if (extra_delta_offset32) 517 if (extra_delta_offset32)
496 outp += sprintf(outp, " %11llu", t->extra_delta32); 518 outp += sprintf(outp, " %11llu", t->extra_delta32);
@@ -506,6 +528,13 @@ int format_counters(struct thread_data *t, struct core_data *c,
506 if (extra_msr_offset64) 528 if (extra_msr_offset64)
507 outp += sprintf(outp, " 0x%016llx", t->extra_msr64); 529 outp += sprintf(outp, " 0x%016llx", t->extra_msr64);
508 530
531 if (!debug)
532 goto done;
533
534 /* SMI */
535 if (do_smi)
536 outp += sprintf(outp, "%8d", t->smi_count);
537
509 if (do_nhm_cstates) { 538 if (do_nhm_cstates) {
510 if (!skip_c1) 539 if (!skip_c1)
511 outp += sprintf(outp, "%8.2f", 100.0 * t->c1/t->tsc); 540 outp += sprintf(outp, "%8.2f", 100.0 * t->c1/t->tsc);
@@ -531,9 +560,18 @@ int format_counters(struct thread_data *t, struct core_data *c,
531 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 560 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
532 goto done; 561 goto done;
533 562
563 /* PkgTmp */
534 if (do_ptm) 564 if (do_ptm)
535 outp += sprintf(outp, "%8d", p->pkg_temp_c); 565 outp += sprintf(outp, "%8d", p->pkg_temp_c);
536 566
567 /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
568 if (do_skl_residency) {
569 outp += sprintf(outp, "%8.2f", 100.0 * p->pkg_wtd_core_c0/t->tsc);
570 outp += sprintf(outp, "%8.2f", 100.0 * p->pkg_any_core_c0/t->tsc);
571 outp += sprintf(outp, "%8.2f", 100.0 * p->pkg_any_gfxe_c0/t->tsc);
572 outp += sprintf(outp, "%8.2f", 100.0 * p->pkg_both_core_gfxe_c0/t->tsc);
573 }
574
537 if (do_pc2) 575 if (do_pc2)
538 outp += sprintf(outp, "%8.2f", 100.0 * p->pc2/t->tsc); 576 outp += sprintf(outp, "%8.2f", 100.0 * p->pc2/t->tsc);
539 if (do_pc3) 577 if (do_pc3)
@@ -565,7 +603,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
565 if (do_rapl & RAPL_GFX) 603 if (do_rapl & RAPL_GFX)
566 outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float); 604 outp += sprintf(outp, fmt8, p->energy_gfx * rapl_energy_units / interval_float);
567 if (do_rapl & RAPL_DRAM) 605 if (do_rapl & RAPL_DRAM)
568 outp += sprintf(outp, fmt8, p->energy_dram * rapl_energy_units / interval_float); 606 outp += sprintf(outp, fmt8, p->energy_dram * rapl_dram_energy_units / interval_float);
569 if (do_rapl & RAPL_PKG_PERF_STATUS) 607 if (do_rapl & RAPL_PKG_PERF_STATUS)
570 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 608 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
571 if (do_rapl & RAPL_DRAM_PERF_STATUS) 609 if (do_rapl & RAPL_DRAM_PERF_STATUS)
@@ -582,7 +620,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
582 p->energy_gfx * rapl_energy_units); 620 p->energy_gfx * rapl_energy_units);
583 if (do_rapl & RAPL_DRAM) 621 if (do_rapl & RAPL_DRAM)
584 outp += sprintf(outp, fmt8, 622 outp += sprintf(outp, fmt8,
585 p->energy_dram * rapl_energy_units); 623 p->energy_dram * rapl_dram_energy_units);
586 if (do_rapl & RAPL_PKG_PERF_STATUS) 624 if (do_rapl & RAPL_PKG_PERF_STATUS)
587 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); 625 outp += sprintf(outp, fmt8, 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
588 if (do_rapl & RAPL_DRAM_PERF_STATUS) 626 if (do_rapl & RAPL_DRAM_PERF_STATUS)
@@ -636,6 +674,13 @@ void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_
636void 674void
637delta_package(struct pkg_data *new, struct pkg_data *old) 675delta_package(struct pkg_data *new, struct pkg_data *old)
638{ 676{
677
678 if (do_skl_residency) {
679 old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0;
680 old->pkg_any_core_c0 = new->pkg_any_core_c0 - old->pkg_any_core_c0;
681 old->pkg_any_gfxe_c0 = new->pkg_any_gfxe_c0 - old->pkg_any_gfxe_c0;
682 old->pkg_both_core_gfxe_c0 = new->pkg_both_core_gfxe_c0 - old->pkg_both_core_gfxe_c0;
683 }
639 old->pc2 = new->pc2 - old->pc2; 684 old->pc2 = new->pc2 - old->pc2;
640 if (do_pc3) 685 if (do_pc3)
641 old->pc3 = new->pc3 - old->pc3; 686 old->pc3 = new->pc3 - old->pc3;
@@ -782,6 +827,11 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
782 c->c7 = 0; 827 c->c7 = 0;
783 c->core_temp_c = 0; 828 c->core_temp_c = 0;
784 829
830 p->pkg_wtd_core_c0 = 0;
831 p->pkg_any_core_c0 = 0;
832 p->pkg_any_gfxe_c0 = 0;
833 p->pkg_both_core_gfxe_c0 = 0;
834
785 p->pc2 = 0; 835 p->pc2 = 0;
786 if (do_pc3) 836 if (do_pc3)
787 p->pc3 = 0; 837 p->pc3 = 0;
@@ -826,6 +876,13 @@ int sum_counters(struct thread_data *t, struct core_data *c,
826 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 876 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
827 return 0; 877 return 0;
828 878
879 if (do_skl_residency) {
880 average.packages.pkg_wtd_core_c0 += p->pkg_wtd_core_c0;
881 average.packages.pkg_any_core_c0 += p->pkg_any_core_c0;
882 average.packages.pkg_any_gfxe_c0 += p->pkg_any_gfxe_c0;
883 average.packages.pkg_both_core_gfxe_c0 += p->pkg_both_core_gfxe_c0;
884 }
885
829 average.packages.pc2 += p->pc2; 886 average.packages.pc2 += p->pc2;
830 if (do_pc3) 887 if (do_pc3)
831 average.packages.pc3 += p->pc3; 888 average.packages.pc3 += p->pc3;
@@ -873,6 +930,13 @@ void compute_average(struct thread_data *t, struct core_data *c,
873 average.cores.c6 /= topo.num_cores; 930 average.cores.c6 /= topo.num_cores;
874 average.cores.c7 /= topo.num_cores; 931 average.cores.c7 /= topo.num_cores;
875 932
933 if (do_skl_residency) {
934 average.packages.pkg_wtd_core_c0 /= topo.num_packages;
935 average.packages.pkg_any_core_c0 /= topo.num_packages;
936 average.packages.pkg_any_gfxe_c0 /= topo.num_packages;
937 average.packages.pkg_both_core_gfxe_c0 /= topo.num_packages;
938 }
939
876 average.packages.pc2 /= topo.num_packages; 940 average.packages.pc2 /= topo.num_packages;
877 if (do_pc3) 941 if (do_pc3)
878 average.packages.pc3 /= topo.num_packages; 942 average.packages.pc3 /= topo.num_packages;
@@ -979,6 +1043,16 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
979 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) 1043 if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
980 return 0; 1044 return 0;
981 1045
1046 if (do_skl_residency) {
1047 if (get_msr(cpu, MSR_PKG_WEIGHTED_CORE_C0_RES, &p->pkg_wtd_core_c0))
1048 return -10;
1049 if (get_msr(cpu, MSR_PKG_ANY_CORE_C0_RES, &p->pkg_any_core_c0))
1050 return -11;
1051 if (get_msr(cpu, MSR_PKG_ANY_GFXE_C0_RES, &p->pkg_any_gfxe_c0))
1052 return -12;
1053 if (get_msr(cpu, MSR_PKG_BOTH_CORE_GFXE_C0_RES, &p->pkg_both_core_gfxe_c0))
1054 return -13;
1055 }
982 if (do_pc3) 1056 if (do_pc3)
983 if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3)) 1057 if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
984 return -9; 1058 return -9;
@@ -1055,49 +1129,77 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
1055#define PCL_6R 9 /* PC6 Retention */ 1129#define PCL_6R 9 /* PC6 Retention */
1056#define PCL__7 10 /* PC7 */ 1130#define PCL__7 10 /* PC7 */
1057#define PCL_7S 11 /* PC7 Shrink */ 1131#define PCL_7S 11 /* PC7 Shrink */
1058#define PCLUNL 12 /* Unlimited */ 1132#define PCL__8 12 /* PC8 */
1133#define PCL__9 13 /* PC9 */
1134#define PCLUNL 14 /* Unlimited */
1059 1135
1060int pkg_cstate_limit = PCLUKN; 1136int pkg_cstate_limit = PCLUKN;
1061char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2", 1137char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
1062 "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "unlimited"}; 1138 "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "unlimited"};
1063 1139
1064int nhm_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL}; 1140int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1065int snb_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL}; 1141int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1066int hsw_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCLRSV, PCLUNL}; 1142int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1067int slv_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7}; 1143int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1068int amt_pkg_cstate_limits[8] = {PCL__0, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7}; 1144int amt_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1069int phi_pkg_cstate_limits[8] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL}; 1145int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
1070 1146
1071void print_verbose_header(void) 1147static void
1148dump_nhm_platform_info(void)
1072{ 1149{
1073 unsigned long long msr; 1150 unsigned long long msr;
1074 unsigned int ratio; 1151 unsigned int ratio;
1075 1152
1076 if (!do_nhm_platform_info)
1077 return;
1078
1079 get_msr(0, MSR_NHM_PLATFORM_INFO, &msr); 1153 get_msr(0, MSR_NHM_PLATFORM_INFO, &msr);
1080 1154
1081 fprintf(stderr, "cpu0: MSR_NHM_PLATFORM_INFO: 0x%08llx\n", msr); 1155 fprintf(stderr, "cpu0: MSR_NHM_PLATFORM_INFO: 0x%08llx\n", msr);
1082 1156
1083 ratio = (msr >> 40) & 0xFF; 1157 ratio = (msr >> 40) & 0xFF;
1084 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", 1158 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency frequency\n",
1085 ratio, bclk, ratio * bclk); 1159 ratio, bclk, ratio * bclk);
1086 1160
1087 ratio = (msr >> 8) & 0xFF; 1161 ratio = (msr >> 8) & 0xFF;
1088 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n", 1162 fprintf(stderr, "%d * %.0f = %.0f MHz base frequency\n",
1089 ratio, bclk, ratio * bclk); 1163 ratio, bclk, ratio * bclk);
1090 1164
1091 get_msr(0, MSR_IA32_POWER_CTL, &msr); 1165 get_msr(0, MSR_IA32_POWER_CTL, &msr);
1092 fprintf(stderr, "cpu0: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n", 1166 fprintf(stderr, "cpu0: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
1093 msr, msr & 0x2 ? "EN" : "DIS"); 1167 msr, msr & 0x2 ? "EN" : "DIS");
1094 1168
1095 if (!do_ivt_turbo_ratio_limit) 1169 return;
1096 goto print_nhm_turbo_ratio_limits; 1170}
1171
1172static void
1173dump_hsw_turbo_ratio_limits(void)
1174{
1175 unsigned long long msr;
1176 unsigned int ratio;
1177
1178 get_msr(0, MSR_TURBO_RATIO_LIMIT2, &msr);
1179
1180 fprintf(stderr, "cpu0: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", msr);
1181
1182 ratio = (msr >> 8) & 0xFF;
1183 if (ratio)
1184 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 18 active cores\n",
1185 ratio, bclk, ratio * bclk);
1186
1187 ratio = (msr >> 0) & 0xFF;
1188 if (ratio)
1189 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 17 active cores\n",
1190 ratio, bclk, ratio * bclk);
1191 return;
1192}
1193
1194static void
1195dump_ivt_turbo_ratio_limits(void)
1196{
1197 unsigned long long msr;
1198 unsigned int ratio;
1097 1199
1098 get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr); 1200 get_msr(0, MSR_TURBO_RATIO_LIMIT1, &msr);
1099 1201
1100 fprintf(stderr, "cpu0: MSR_IVT_TURBO_RATIO_LIMIT: 0x%08llx\n", msr); 1202 fprintf(stderr, "cpu0: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", msr);
1101 1203
1102 ratio = (msr >> 56) & 0xFF; 1204 ratio = (msr >> 56) & 0xFF;
1103 if (ratio) 1205 if (ratio)
@@ -1138,30 +1240,18 @@ void print_verbose_header(void)
1138 if (ratio) 1240 if (ratio)
1139 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n", 1241 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
1140 ratio, bclk, ratio * bclk); 1242 ratio, bclk, ratio * bclk);
1243 return;
1244}
1141 1245
1142print_nhm_turbo_ratio_limits: 1246static void
1143 get_msr(0, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); 1247dump_nhm_turbo_ratio_limits(void)
1144 1248{
1145#define SNB_C1_AUTO_UNDEMOTE (1UL << 27) 1249 unsigned long long msr;
1146#define SNB_C3_AUTO_UNDEMOTE (1UL << 28) 1250 unsigned int ratio;
1147
1148 fprintf(stderr, "cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", msr);
1149
1150 fprintf(stderr, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n",
1151 (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
1152 (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
1153 (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
1154 (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
1155 (msr & (1 << 15)) ? "" : "UN",
1156 (unsigned int)msr & 7,
1157 pkg_cstate_limit_strings[pkg_cstate_limit]);
1158
1159 if (!do_nhm_turbo_ratio_limit)
1160 return;
1161 1251
1162 get_msr(0, MSR_NHM_TURBO_RATIO_LIMIT, &msr); 1252 get_msr(0, MSR_TURBO_RATIO_LIMIT, &msr);
1163 1253
1164 fprintf(stderr, "cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x%08llx\n", msr); 1254 fprintf(stderr, "cpu0: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", msr);
1165 1255
1166 ratio = (msr >> 56) & 0xFF; 1256 ratio = (msr >> 56) & 0xFF;
1167 if (ratio) 1257 if (ratio)
@@ -1202,7 +1292,30 @@ print_nhm_turbo_ratio_limits:
1202 if (ratio) 1292 if (ratio)
1203 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", 1293 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
1204 ratio, bclk, ratio * bclk); 1294 ratio, bclk, ratio * bclk);
1295 return;
1296}
1297
1298static void
1299dump_nhm_cst_cfg(void)
1300{
1301 unsigned long long msr;
1302
1303 get_msr(0, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr);
1304
1305#define SNB_C1_AUTO_UNDEMOTE (1UL << 27)
1306#define SNB_C3_AUTO_UNDEMOTE (1UL << 28)
1205 1307
1308 fprintf(stderr, "cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", msr);
1309
1310 fprintf(stderr, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n",
1311 (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
1312 (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
1313 (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
1314 (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
1315 (msr & (1 << 15)) ? "" : "UN",
1316 (unsigned int)msr & 7,
1317 pkg_cstate_limit_strings[pkg_cstate_limit]);
1318 return;
1206} 1319}
1207 1320
1208void free_all_buffers(void) 1321void free_all_buffers(void)
@@ -1483,7 +1596,8 @@ void check_dev_msr()
1483 struct stat sb; 1596 struct stat sb;
1484 1597
1485 if (stat("/dev/cpu/0/msr", &sb)) 1598 if (stat("/dev/cpu/0/msr", &sb))
1486 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" "); 1599 if (system("/sbin/modprobe msr > /dev/null 2>&1"))
1600 err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
1487} 1601}
1488 1602
1489void check_permissions() 1603void check_permissions()
@@ -1573,6 +1687,8 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
1573 case 0x47: /* BDW */ 1687 case 0x47: /* BDW */
1574 case 0x4F: /* BDX */ 1688 case 0x4F: /* BDX */
1575 case 0x56: /* BDX-DE */ 1689 case 0x56: /* BDX-DE */
1690 case 0x4E: /* SKL */
1691 case 0x5E: /* SKL */
1576 pkg_cstate_limits = hsw_pkg_cstate_limits; 1692 pkg_cstate_limits = hsw_pkg_cstate_limits;
1577 break; 1693 break;
1578 case 0x37: /* BYT */ 1694 case 0x37: /* BYT */
@@ -1590,7 +1706,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
1590 } 1706 }
1591 get_msr(0, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr); 1707 get_msr(0, MSR_NHM_SNB_PKG_CST_CFG_CTL, &msr);
1592 1708
1593 pkg_cstate_limit = pkg_cstate_limits[msr & 0x7]; 1709 pkg_cstate_limit = pkg_cstate_limits[msr & 0xF];
1594 1710
1595 return 1; 1711 return 1;
1596} 1712}
@@ -1615,12 +1731,49 @@ int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
1615 1731
1616 switch (model) { 1732 switch (model) {
1617 case 0x3E: /* IVB Xeon */ 1733 case 0x3E: /* IVB Xeon */
1734 case 0x3F: /* HSW Xeon */
1735 return 1;
1736 default:
1737 return 0;
1738 }
1739}
1740int has_hsw_turbo_ratio_limit(unsigned int family, unsigned int model)
1741{
1742 if (!genuine_intel)
1743 return 0;
1744
1745 if (family != 6)
1746 return 0;
1747
1748 switch (model) {
1749 case 0x3F: /* HSW Xeon */
1618 return 1; 1750 return 1;
1619 default: 1751 default:
1620 return 0; 1752 return 0;
1621 } 1753 }
1622} 1754}
1623 1755
1756static void
1757dump_cstate_pstate_config_info(family, model)
1758{
1759 if (!do_nhm_platform_info)
1760 return;
1761
1762 dump_nhm_platform_info();
1763
1764 if (has_hsw_turbo_ratio_limit(family, model))
1765 dump_hsw_turbo_ratio_limits();
1766
1767 if (has_ivt_turbo_ratio_limit(family, model))
1768 dump_ivt_turbo_ratio_limits();
1769
1770 if (has_nhm_turbo_ratio_limit(family, model))
1771 dump_nhm_turbo_ratio_limits();
1772
1773 dump_nhm_cst_cfg();
1774}
1775
1776
1624/* 1777/*
1625 * print_epb() 1778 * print_epb()
1626 * Decode the ENERGY_PERF_BIAS MSR 1779 * Decode the ENERGY_PERF_BIAS MSR
@@ -1690,35 +1843,35 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
1690 get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr); 1843 get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);
1691 fprintf(stderr, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr); 1844 fprintf(stderr, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
1692 fprintf(stderr, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)", 1845 fprintf(stderr, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",
1693 (msr & 1 << 0) ? "PROCHOT, " : "", 1846 (msr & 1 << 15) ? "bit15, " : "",
1694 (msr & 1 << 1) ? "ThermStatus, " : "",
1695 (msr & 1 << 2) ? "bit2, " : "",
1696 (msr & 1 << 4) ? "Graphics, " : "",
1697 (msr & 1 << 5) ? "Auto-HWP, " : "",
1698 (msr & 1 << 6) ? "VR-Therm, " : "",
1699 (msr & 1 << 8) ? "Amps, " : "",
1700 (msr & 1 << 9) ? "CorePwr, " : "",
1701 (msr & 1 << 10) ? "PkgPwrL1, " : "",
1702 (msr & 1 << 11) ? "PkgPwrL2, " : "",
1703 (msr & 1 << 12) ? "MultiCoreTurbo, " : "",
1704 (msr & 1 << 13) ? "Transitions, " : "",
1705 (msr & 1 << 14) ? "bit14, " : "", 1847 (msr & 1 << 14) ? "bit14, " : "",
1706 (msr & 1 << 15) ? "bit15, " : ""); 1848 (msr & 1 << 13) ? "Transitions, " : "",
1849 (msr & 1 << 12) ? "MultiCoreTurbo, " : "",
1850 (msr & 1 << 11) ? "PkgPwrL2, " : "",
1851 (msr & 1 << 10) ? "PkgPwrL1, " : "",
1852 (msr & 1 << 9) ? "CorePwr, " : "",
1853 (msr & 1 << 8) ? "Amps, " : "",
1854 (msr & 1 << 6) ? "VR-Therm, " : "",
1855 (msr & 1 << 5) ? "Auto-HWP, " : "",
1856 (msr & 1 << 4) ? "Graphics, " : "",
1857 (msr & 1 << 2) ? "bit2, " : "",
1858 (msr & 1 << 1) ? "ThermStatus, " : "",
1859 (msr & 1 << 0) ? "PROCHOT, " : "");
1707 fprintf(stderr, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n", 1860 fprintf(stderr, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
1708 (msr & 1 << 16) ? "PROCHOT, " : "", 1861 (msr & 1 << 31) ? "bit31, " : "",
1709 (msr & 1 << 17) ? "ThermStatus, " : "",
1710 (msr & 1 << 18) ? "bit18, " : "",
1711 (msr & 1 << 20) ? "Graphics, " : "",
1712 (msr & 1 << 21) ? "Auto-HWP, " : "",
1713 (msr & 1 << 22) ? "VR-Therm, " : "",
1714 (msr & 1 << 24) ? "Amps, " : "",
1715 (msr & 1 << 25) ? "CorePwr, " : "",
1716 (msr & 1 << 26) ? "PkgPwrL1, " : "",
1717 (msr & 1 << 27) ? "PkgPwrL2, " : "",
1718 (msr & 1 << 28) ? "MultiCoreTurbo, " : "",
1719 (msr & 1 << 29) ? "Transitions, " : "",
1720 (msr & 1 << 30) ? "bit30, " : "", 1862 (msr & 1 << 30) ? "bit30, " : "",
1721 (msr & 1 << 31) ? "bit31, " : ""); 1863 (msr & 1 << 29) ? "Transitions, " : "",
1864 (msr & 1 << 28) ? "MultiCoreTurbo, " : "",
1865 (msr & 1 << 27) ? "PkgPwrL2, " : "",
1866 (msr & 1 << 26) ? "PkgPwrL1, " : "",
1867 (msr & 1 << 25) ? "CorePwr, " : "",
1868 (msr & 1 << 24) ? "Amps, " : "",
1869 (msr & 1 << 22) ? "VR-Therm, " : "",
1870 (msr & 1 << 21) ? "Auto-HWP, " : "",
1871 (msr & 1 << 20) ? "Graphics, " : "",
1872 (msr & 1 << 18) ? "bit18, " : "",
1873 (msr & 1 << 17) ? "ThermStatus, " : "",
1874 (msr & 1 << 16) ? "PROCHOT, " : "");
1722 1875
1723 } 1876 }
1724 if (do_gfx_perf_limit_reasons) { 1877 if (do_gfx_perf_limit_reasons) {
@@ -1784,6 +1937,25 @@ double get_tdp(model)
1784 } 1937 }
1785} 1938}
1786 1939
1940/*
1941 * rapl_dram_energy_units_probe()
1942 * Energy units are either hard-coded, or come from RAPL Energy Unit MSR.
1943 */
1944static double
1945rapl_dram_energy_units_probe(int model, double rapl_energy_units)
1946{
1947 /* only called for genuine_intel, family 6 */
1948
1949 switch (model) {
1950 case 0x3F: /* HSX */
1951 case 0x4F: /* BDX */
1952 case 0x56: /* BDX-DE */
1953 return (rapl_dram_energy_units = 15.3 / 1000000);
1954 default:
1955 return (rapl_energy_units);
1956 }
1957}
1958
1787 1959
1788/* 1960/*
1789 * rapl_probe() 1961 * rapl_probe()
@@ -1812,14 +1984,18 @@ void rapl_probe(unsigned int family, unsigned int model)
1812 case 0x47: /* BDW */ 1984 case 0x47: /* BDW */
1813 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO; 1985 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
1814 break; 1986 break;
1987 case 0x4E: /* SKL */
1988 case 0x5E: /* SKL */
1989 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
1990 break;
1815 case 0x3F: /* HSX */ 1991 case 0x3F: /* HSX */
1816 case 0x4F: /* BDX */ 1992 case 0x4F: /* BDX */
1817 case 0x56: /* BDX-DE */ 1993 case 0x56: /* BDX-DE */
1818 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO; 1994 do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
1819 break; 1995 break;
1820 case 0x2D: 1996 case 0x2D:
1821 case 0x3E: 1997 case 0x3E:
1822 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO; 1998 do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
1823 break; 1999 break;
1824 case 0x37: /* BYT */ 2000 case 0x37: /* BYT */
1825 case 0x4D: /* AVN */ 2001 case 0x4D: /* AVN */
@@ -1839,6 +2015,8 @@ void rapl_probe(unsigned int family, unsigned int model)
1839 else 2015 else
1840 rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F)); 2016 rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
1841 2017
2018 rapl_dram_energy_units = rapl_dram_energy_units_probe(model, rapl_energy_units);
2019
1842 time_unit = msr >> 16 & 0xF; 2020 time_unit = msr >> 16 & 0xF;
1843 if (time_unit == 0) 2021 if (time_unit == 0)
1844 time_unit = 0xA; 2022 time_unit = 0xA;
@@ -2009,19 +2187,18 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
2009 ((msr >> 48) & 1) ? "EN" : "DIS"); 2187 ((msr >> 48) & 1) ? "EN" : "DIS");
2010 } 2188 }
2011 2189
2012 if (do_rapl & RAPL_DRAM) { 2190 if (do_rapl & RAPL_DRAM_POWER_INFO) {
2013 if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr)) 2191 if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))
2014 return -6; 2192 return -6;
2015 2193
2016
2017 fprintf(stderr, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n", 2194 fprintf(stderr, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
2018 cpu, msr, 2195 cpu, msr,
2019 ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units, 2196 ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
2020 ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units, 2197 ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
2021 ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units, 2198 ((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
2022 ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units); 2199 ((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
2023 2200 }
2024 2201 if (do_rapl & RAPL_DRAM) {
2025 if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr)) 2202 if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
2026 return -9; 2203 return -9;
2027 fprintf(stderr, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n", 2204 fprintf(stderr, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
@@ -2090,6 +2267,8 @@ int has_snb_msrs(unsigned int family, unsigned int model)
2090 case 0x47: /* BDW */ 2267 case 0x47: /* BDW */
2091 case 0x4F: /* BDX */ 2268 case 0x4F: /* BDX */
2092 case 0x56: /* BDX-DE */ 2269 case 0x56: /* BDX-DE */
2270 case 0x4E: /* SKL */
2271 case 0x5E: /* SKL */
2093 return 1; 2272 return 1;
2094 } 2273 }
2095 return 0; 2274 return 0;
@@ -2110,11 +2289,35 @@ int has_hsw_msrs(unsigned int family, unsigned int model)
2110 switch (model) { 2289 switch (model) {
2111 case 0x45: /* HSW */ 2290 case 0x45: /* HSW */
2112 case 0x3D: /* BDW */ 2291 case 0x3D: /* BDW */
2292 case 0x4E: /* SKL */
2293 case 0x5E: /* SKL */
2113 return 1; 2294 return 1;
2114 } 2295 }
2115 return 0; 2296 return 0;
2116} 2297}
2117 2298
2299/*
2300 * SKL adds support for additional MSRS:
2301 *
2302 * MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658
2303 * MSR_PKG_ANY_CORE_C0_RES 0x00000659
2304 * MSR_PKG_ANY_GFXE_C0_RES 0x0000065A
2305 * MSR_PKG_BOTH_CORE_GFXE_C0_RES 0x0000065B
2306 */
2307int has_skl_msrs(unsigned int family, unsigned int model)
2308{
2309 if (!genuine_intel)
2310 return 0;
2311
2312 switch (model) {
2313 case 0x4E: /* SKL */
2314 case 0x5E: /* SKL */
2315 return 1;
2316 }
2317 return 0;
2318}
2319
2320
2118 2321
2119int is_slm(unsigned int family, unsigned int model) 2322int is_slm(unsigned int family, unsigned int model)
2120{ 2323{
@@ -2228,7 +2431,7 @@ guess:
2228 2431
2229 return 0; 2432 return 0;
2230} 2433}
2231void check_cpuid() 2434void process_cpuid()
2232{ 2435{
2233 unsigned int eax, ebx, ecx, edx, max_level; 2436 unsigned int eax, ebx, ecx, edx, max_level;
2234 unsigned int fms, family, model, stepping; 2437 unsigned int fms, family, model, stepping;
@@ -2294,6 +2497,41 @@ void check_cpuid()
2294 do_ptm ? "" : "No ", 2497 do_ptm ? "" : "No ",
2295 has_epb ? "" : "No "); 2498 has_epb ? "" : "No ");
2296 2499
2500 if (max_level > 0x15) {
2501 unsigned int eax_crystal;
2502 unsigned int ebx_tsc;
2503
2504 /*
2505 * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz
2506 */
2507 eax_crystal = ebx_tsc = crystal_hz = edx = 0;
2508 __get_cpuid(0x15, &eax_crystal, &ebx_tsc, &crystal_hz, &edx);
2509
2510 if (ebx_tsc != 0) {
2511
2512 if (debug && (ebx != 0))
2513 fprintf(stderr, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
2514 eax_crystal, ebx_tsc, crystal_hz);
2515
2516 if (crystal_hz == 0)
2517 switch(model) {
2518 case 0x4E: /* SKL */
2519 case 0x5E: /* SKL */
2520 crystal_hz = 24000000; /* 24 MHz */
2521 break;
2522 default:
2523 crystal_hz = 0;
2524 }
2525
2526 if (crystal_hz) {
2527 tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal;
2528 if (debug)
2529 fprintf(stderr, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
2530 tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);
2531 }
2532 }
2533 }
2534
2297 do_nhm_platform_info = do_nhm_cstates = do_smi = probe_nhm_msrs(family, model); 2535 do_nhm_platform_info = do_nhm_cstates = do_smi = probe_nhm_msrs(family, model);
2298 do_snb_cstates = has_snb_msrs(family, model); 2536 do_snb_cstates = has_snb_msrs(family, model);
2299 do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2); 2537 do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2);
@@ -2301,18 +2539,19 @@ void check_cpuid()
2301 do_pc6 = (pkg_cstate_limit >= PCL__6); 2539 do_pc6 = (pkg_cstate_limit >= PCL__6);
2302 do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7); 2540 do_pc7 = do_snb_cstates && (pkg_cstate_limit >= PCL__7);
2303 do_c8_c9_c10 = has_hsw_msrs(family, model); 2541 do_c8_c9_c10 = has_hsw_msrs(family, model);
2542 do_skl_residency = has_skl_msrs(family, model);
2304 do_slm_cstates = is_slm(family, model); 2543 do_slm_cstates = is_slm(family, model);
2305 bclk = discover_bclk(family, model); 2544 bclk = discover_bclk(family, model);
2306 2545
2307 do_nhm_turbo_ratio_limit = do_nhm_platform_info && has_nhm_turbo_ratio_limit(family, model);
2308 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
2309 rapl_probe(family, model); 2546 rapl_probe(family, model);
2310 perf_limit_reasons_probe(family, model); 2547 perf_limit_reasons_probe(family, model);
2311 2548
2549 if (debug)
2550 dump_cstate_pstate_config_info();
2551
2312 return; 2552 return;
2313} 2553}
2314 2554
2315
2316void help() 2555void help()
2317{ 2556{
2318 fprintf(stderr, 2557 fprintf(stderr,
@@ -2428,14 +2667,14 @@ void topology_probe()
2428 if (debug > 1) 2667 if (debug > 1)
2429 fprintf(stderr, "max_core_id %d, sizing for %d cores per package\n", 2668 fprintf(stderr, "max_core_id %d, sizing for %d cores per package\n",
2430 max_core_id, topo.num_cores_per_pkg); 2669 max_core_id, topo.num_cores_per_pkg);
2431 if (!summary_only && topo.num_cores_per_pkg > 1) 2670 if (debug && !summary_only && topo.num_cores_per_pkg > 1)
2432 show_core = 1; 2671 show_core = 1;
2433 2672
2434 topo.num_packages = max_package_id + 1; 2673 topo.num_packages = max_package_id + 1;
2435 if (debug > 1) 2674 if (debug > 1)
2436 fprintf(stderr, "max_package_id %d, sizing for %d packages\n", 2675 fprintf(stderr, "max_package_id %d, sizing for %d packages\n",
2437 max_package_id, topo.num_packages); 2676 max_package_id, topo.num_packages);
2438 if (!summary_only && topo.num_packages > 1) 2677 if (debug && !summary_only && topo.num_packages > 1)
2439 show_pkg = 1; 2678 show_pkg = 1;
2440 2679
2441 topo.num_threads_per_core = max_siblings; 2680 topo.num_threads_per_core = max_siblings;
@@ -2550,14 +2789,11 @@ void turbostat_init()
2550{ 2789{
2551 check_dev_msr(); 2790 check_dev_msr();
2552 check_permissions(); 2791 check_permissions();
2553 check_cpuid(); 2792 process_cpuid();
2554 2793
2555 setup_all_buffers(); 2794 setup_all_buffers();
2556 2795
2557 if (debug) 2796 if (debug)
2558 print_verbose_header();
2559
2560 if (debug)
2561 for_all_cpus(print_epb, ODD_COUNTERS); 2797 for_all_cpus(print_epb, ODD_COUNTERS);
2562 2798
2563 if (debug) 2799 if (debug)
@@ -2634,7 +2870,7 @@ int get_and_dump_counters(void)
2634} 2870}
2635 2871
2636void print_version() { 2872void print_version() {
2637 fprintf(stderr, "turbostat version 4.1 10-Feb, 2015" 2873 fprintf(stderr, "turbostat version 4.5 2 Apr, 2015"
2638 " - Len Brown <lenb@kernel.org>\n"); 2874 " - Len Brown <lenb@kernel.org>\n");
2639} 2875}
2640 2876
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 4e511221a0c1..95abddcd7839 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -17,11 +17,20 @@ TARGETS += sysctl
17TARGETS += timers 17TARGETS += timers
18TARGETS += user 18TARGETS += user
19TARGETS += vm 19TARGETS += vm
20TARGETS += x86
20#Please keep the TARGETS list alphabetically sorted 21#Please keep the TARGETS list alphabetically sorted
21 22
22TARGETS_HOTPLUG = cpu-hotplug 23TARGETS_HOTPLUG = cpu-hotplug
23TARGETS_HOTPLUG += memory-hotplug 24TARGETS_HOTPLUG += memory-hotplug
24 25
26# Clear LDFLAGS and MAKEFLAGS if called from main
27# Makefile to avoid test build failures when test
28# Makefile doesn't have explicit build rules.
29ifeq (1,$(MAKELEVEL))
30undefine LDFLAGS
31override MAKEFLAGS =
32endif
33
25all: 34all:
26 for TARGET in $(TARGETS); do \ 35 for TARGET in $(TARGETS); do \
27 make -C $$TARGET; \ 36 make -C $$TARGET; \
@@ -47,7 +56,40 @@ clean_hotplug:
47 make -C $$TARGET clean; \ 56 make -C $$TARGET clean; \
48 done; 57 done;
49 58
59INSTALL_PATH ?= install
60INSTALL_PATH := $(abspath $(INSTALL_PATH))
61ALL_SCRIPT := $(INSTALL_PATH)/run_kselftest.sh
62
63install:
64ifdef INSTALL_PATH
65 @# Ask all targets to install their files
66 mkdir -p $(INSTALL_PATH)
67 for TARGET in $(TARGETS); do \
68 mkdir -p $(INSTALL_PATH)/$$TARGET ; \
69 make -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
70 done;
71
72 @# Ask all targets to emit their test scripts
73 echo "#!/bin/bash" > $(ALL_SCRIPT)
74 echo "cd \$$(dirname \$$0)" >> $(ALL_SCRIPT)
75 echo "ROOT=\$$PWD" >> $(ALL_SCRIPT)
76
77 for TARGET in $(TARGETS); do \
78 echo "echo ; echo Running tests in $$TARGET" >> $(ALL_SCRIPT); \
79 echo "echo ========================================" >> $(ALL_SCRIPT); \
80 echo "cd $$TARGET" >> $(ALL_SCRIPT); \
81 make -s --no-print-directory -C $$TARGET emit_tests >> $(ALL_SCRIPT); \
82 echo "cd \$$ROOT" >> $(ALL_SCRIPT); \
83 done;
84
85 chmod u+x $(ALL_SCRIPT)
86else
87 $(error Error: set INSTALL_PATH to use install)
88endif
89
50clean: 90clean:
51 for TARGET in $(TARGETS); do \ 91 for TARGET in $(TARGETS); do \
52 make -C $$TARGET clean; \ 92 make -C $$TARGET clean; \
53 done; 93 done;
94
95.PHONY: install
diff --git a/tools/testing/selftests/breakpoints/Makefile b/tools/testing/selftests/breakpoints/Makefile
index e18b42b254af..182235640209 100644
--- a/tools/testing/selftests/breakpoints/Makefile
+++ b/tools/testing/selftests/breakpoints/Makefile
@@ -16,8 +16,9 @@ else
16 echo "Not an x86 target, can't build breakpoints selftests" 16 echo "Not an x86 target, can't build breakpoints selftests"
17endif 17endif
18 18
19run_tests: 19TEST_PROGS := breakpoint_test
20 @./breakpoint_test || echo "breakpoints selftests: [FAIL]" 20
21include ../lib.mk
21 22
22clean: 23clean:
23 rm -fr breakpoint_test 24 rm -fr breakpoint_test
diff --git a/tools/testing/selftests/cpu-hotplug/Makefile b/tools/testing/selftests/cpu-hotplug/Makefile
index e9c28d8dc84b..fe1f99101c5d 100644
--- a/tools/testing/selftests/cpu-hotplug/Makefile
+++ b/tools/testing/selftests/cpu-hotplug/Makefile
@@ -1,9 +1,10 @@
1all: 1all:
2 2
3run_tests: 3TEST_PROGS := cpu-on-off-test.sh
4 @/bin/bash ./on-off-test.sh || echo "cpu-hotplug selftests: [FAIL]" 4
5include ../lib.mk
5 6
6run_full_test: 7run_full_test:
7 @/bin/bash ./on-off-test.sh -a || echo "cpu-hotplug selftests: [FAIL]" 8 @/bin/bash ./cpu-on-off-test.sh -a || echo "cpu-hotplug selftests: [FAIL]"
8 9
9clean: 10clean:
diff --git a/tools/testing/selftests/cpu-hotplug/on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
index 98b1d6565f2c..98b1d6565f2c 100644..100755
--- a/tools/testing/selftests/cpu-hotplug/on-off-test.sh
+++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
diff --git a/tools/testing/selftests/efivarfs/Makefile b/tools/testing/selftests/efivarfs/Makefile
index 29e8c6bc81b0..736c3ddfc787 100644
--- a/tools/testing/selftests/efivarfs/Makefile
+++ b/tools/testing/selftests/efivarfs/Makefile
@@ -1,12 +1,13 @@
1CC = $(CROSS_COMPILE)gcc
2CFLAGS = -Wall 1CFLAGS = -Wall
3 2
4test_objs = open-unlink create-read 3test_objs = open-unlink create-read
5 4
6all: $(test_objs) 5all: $(test_objs)
7 6
8run_tests: all 7TEST_PROGS := efivarfs.sh
9 @/bin/bash ./efivarfs.sh || echo "efivarfs selftests: [FAIL]" 8TEST_FILES := $(test_objs)
9
10include ../lib.mk
10 11
11clean: 12clean:
12 rm -f $(test_objs) 13 rm -f $(test_objs)
diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh b/tools/testing/selftests/efivarfs/efivarfs.sh
index 77edcdcc016b..77edcdcc016b 100644..100755
--- a/tools/testing/selftests/efivarfs/efivarfs.sh
+++ b/tools/testing/selftests/efivarfs/efivarfs.sh
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile
index 66dfc2ce1788..4edb7d0da29b 100644
--- a/tools/testing/selftests/exec/Makefile
+++ b/tools/testing/selftests/exec/Makefile
@@ -1,4 +1,3 @@
1CC = $(CROSS_COMPILE)gcc
2CFLAGS = -Wall 1CFLAGS = -Wall
3BINARIES = execveat 2BINARIES = execveat
4DEPS = execveat.symlink execveat.denatured script subdir 3DEPS = execveat.symlink execveat.denatured script subdir
@@ -18,8 +17,12 @@ execveat.denatured: execveat
18%: %.c 17%: %.c
19 $(CC) $(CFLAGS) -o $@ $^ 18 $(CC) $(CFLAGS) -o $@ $^
20 19
21run_tests: all 20TEST_PROGS := execveat
22 ./execveat 21TEST_FILES := $(DEPS)
22
23include ../lib.mk
24
25override EMIT_TESTS := echo "mkdir -p subdir; (./execveat && echo \"selftests: execveat [PASS]\") || echo \"selftests: execveat [FAIL]\""
23 26
24clean: 27clean:
25 rm -rf $(BINARIES) $(DEPS) subdir.moved execveat.moved xxxxx* 28 rm -rf $(BINARIES) $(DEPS) subdir.moved execveat.moved xxxxx*
diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c
index e238c9559caf..8d5d1d2ee7c1 100644
--- a/tools/testing/selftests/exec/execveat.c
+++ b/tools/testing/selftests/exec/execveat.c
@@ -30,7 +30,7 @@ static int execveat_(int fd, const char *path, char **argv, char **envp,
30#ifdef __NR_execveat 30#ifdef __NR_execveat
31 return syscall(__NR_execveat, fd, path, argv, envp, flags); 31 return syscall(__NR_execveat, fd, path, argv, envp, flags);
32#else 32#else
33 errno = -ENOSYS; 33 errno = ENOSYS;
34 return -1; 34 return -1;
35#endif 35#endif
36} 36}
@@ -234,6 +234,14 @@ static int run_tests(void)
234 int fd_cloexec = open_or_die("execveat", O_RDONLY|O_CLOEXEC); 234 int fd_cloexec = open_or_die("execveat", O_RDONLY|O_CLOEXEC);
235 int fd_script_cloexec = open_or_die("script", O_RDONLY|O_CLOEXEC); 235 int fd_script_cloexec = open_or_die("script", O_RDONLY|O_CLOEXEC);
236 236
237 /* Check if we have execveat at all, and bail early if not */
238 errno = 0;
239 execveat_(-1, NULL, NULL, NULL, 0);
240 if (errno == ENOSYS) {
241 printf("[FAIL] ENOSYS calling execveat - no kernel support?\n");
242 return 1;
243 }
244
237 /* Change file position to confirm it doesn't affect anything */ 245 /* Change file position to confirm it doesn't affect anything */
238 lseek(fd, 10, SEEK_SET); 246 lseek(fd, 10, SEEK_SET);
239 247
diff --git a/tools/testing/selftests/firmware/Makefile b/tools/testing/selftests/firmware/Makefile
index e23cce0bbc3a..9bf82234855b 100644
--- a/tools/testing/selftests/firmware/Makefile
+++ b/tools/testing/selftests/firmware/Makefile
@@ -3,25 +3,9 @@
3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" 3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
4all: 4all:
5 5
6fw_filesystem: 6TEST_PROGS := fw_filesystem.sh fw_userhelper.sh
7 @if /bin/sh ./fw_filesystem.sh ; then \
8 echo "fw_filesystem: ok"; \
9 else \
10 echo "fw_filesystem: [FAIL]"; \
11 exit 1; \
12 fi
13 7
14fw_userhelper: 8include ../lib.mk
15 @if /bin/sh ./fw_userhelper.sh ; then \
16 echo "fw_userhelper: ok"; \
17 else \
18 echo "fw_userhelper: [FAIL]"; \
19 exit 1; \
20 fi
21
22run_tests: all fw_filesystem fw_userhelper
23 9
24# Nothing to clean up. 10# Nothing to clean up.
25clean: 11clean:
26
27.PHONY: all clean run_tests fw_filesystem fw_userhelper
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
index 3fc6c10c2479..3fc6c10c2479 100644..100755
--- a/tools/testing/selftests/firmware/fw_filesystem.sh
+++ b/tools/testing/selftests/firmware/fw_filesystem.sh
diff --git a/tools/testing/selftests/firmware/fw_userhelper.sh b/tools/testing/selftests/firmware/fw_userhelper.sh
index 6efbade12139..6efbade12139 100644..100755
--- a/tools/testing/selftests/firmware/fw_userhelper.sh
+++ b/tools/testing/selftests/firmware/fw_userhelper.sh
diff --git a/tools/testing/selftests/ftrace/Makefile b/tools/testing/selftests/ftrace/Makefile
index 76cc9f156267..346720639d1d 100644
--- a/tools/testing/selftests/ftrace/Makefile
+++ b/tools/testing/selftests/ftrace/Makefile
@@ -1,7 +1,8 @@
1all: 1all:
2 2
3run_tests: 3TEST_PROGS := ftracetest
4 @/bin/sh ./ftracetest || echo "ftrace selftests: [FAIL]" 4
5include ../lib.mk
5 6
6clean: 7clean:
7 rm -rf logs/* 8 rm -rf logs/*
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
index fd9c49a13612..aa51f6c17359 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
@@ -2,4 +2,4 @@
2# description: Basic event tracing check 2# description: Basic event tracing check
3test -f available_events -a -f set_event -a -d events 3test -f available_events -a -f set_event -a -d events
4# check scheduler events are available 4# check scheduler events are available
5grep -q sched available_events && exit 0 || exit -1 \ No newline at end of file 5grep -q sched available_events && exit 0 || exit $FAIL
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-enable.tc b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc
index 668616d9bb03..87eb9d6dd4ca 100644
--- a/tools/testing/selftests/ftrace/test.d/event/event-enable.tc
+++ b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc
@@ -9,7 +9,11 @@ do_reset() {
9fail() { #msg 9fail() { #msg
10 do_reset 10 do_reset
11 echo $1 11 echo $1
12 exit -1 12 exit $FAIL
13}
14
15yield() {
16 ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
13} 17}
14 18
15if [ ! -f set_event -o ! -d events/sched ]; then 19if [ ! -f set_event -o ! -d events/sched ]; then
@@ -21,7 +25,8 @@ reset_tracer
21do_reset 25do_reset
22 26
23echo 'sched:sched_switch' > set_event 27echo 'sched:sched_switch' > set_event
24usleep 1 28
29yield
25 30
26count=`cat trace | grep sched_switch | wc -l` 31count=`cat trace | grep sched_switch | wc -l`
27if [ $count -eq 0 ]; then 32if [ $count -eq 0 ]; then
@@ -31,7 +36,8 @@ fi
31do_reset 36do_reset
32 37
33echo 1 > events/sched/sched_switch/enable 38echo 1 > events/sched/sched_switch/enable
34usleep 1 39
40yield
35 41
36count=`cat trace | grep sched_switch | wc -l` 42count=`cat trace | grep sched_switch | wc -l`
37if [ $count -eq 0 ]; then 43if [ $count -eq 0 ]; then
@@ -41,7 +47,8 @@ fi
41do_reset 47do_reset
42 48
43echo 0 > events/sched/sched_switch/enable 49echo 0 > events/sched/sched_switch/enable
44usleep 1 50
51yield
45 52
46count=`cat trace | grep sched_switch | wc -l` 53count=`cat trace | grep sched_switch | wc -l`
47if [ $count -ne 0 ]; then 54if [ $count -ne 0 ]; then
diff --git a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
index 655c415b6e7f..ced27ef0638f 100644
--- a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
+++ b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
@@ -9,7 +9,11 @@ do_reset() {
9fail() { #msg 9fail() { #msg
10 do_reset 10 do_reset
11 echo $1 11 echo $1
12 exit -1 12 exit $FAIL
13}
14
15yield() {
16 ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
13} 17}
14 18
15if [ ! -f set_event -o ! -d events/sched ]; then 19if [ ! -f set_event -o ! -d events/sched ]; then
@@ -21,7 +25,8 @@ reset_tracer
21do_reset 25do_reset
22 26
23echo 'sched:*' > set_event 27echo 'sched:*' > set_event
24usleep 1 28
29yield
25 30
26count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` 31count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
27if [ $count -lt 3 ]; then 32if [ $count -lt 3 ]; then
@@ -31,7 +36,8 @@ fi
31do_reset 36do_reset
32 37
33echo 1 > events/sched/enable 38echo 1 > events/sched/enable
34usleep 1 39
40yield
35 41
36count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` 42count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
37if [ $count -lt 3 ]; then 43if [ $count -lt 3 ]; then
@@ -41,7 +47,8 @@ fi
41do_reset 47do_reset
42 48
43echo 0 > events/sched/enable 49echo 0 > events/sched/enable
44usleep 1 50
51yield
45 52
46count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` 53count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
47if [ $count -ne 0 ]; then 54if [ $count -ne 0 ]; then
diff --git a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
index 480845774007..0bb5df3c00d4 100644
--- a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
+++ b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
@@ -9,7 +9,11 @@ do_reset() {
9fail() { #msg 9fail() { #msg
10 do_reset 10 do_reset
11 echo $1 11 echo $1
12 exit -1 12 exit $FAIL
13}
14
15yield() {
16 ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
13} 17}
14 18
15if [ ! -f available_events -o ! -f set_event -o ! -d events ]; then 19if [ ! -f available_events -o ! -f set_event -o ! -d events ]; then
@@ -21,6 +25,9 @@ reset_tracer
21do_reset 25do_reset
22 26
23echo '*:*' > set_event 27echo '*:*' > set_event
28
29yield
30
24count=`cat trace | grep -v ^# | wc -l` 31count=`cat trace | grep -v ^# | wc -l`
25if [ $count -eq 0 ]; then 32if [ $count -eq 0 ]; then
26 fail "none of events are recorded" 33 fail "none of events are recorded"
@@ -29,6 +36,9 @@ fi
29do_reset 36do_reset
30 37
31echo 1 > events/enable 38echo 1 > events/enable
39
40yield
41
32count=`cat trace | grep -v ^# | wc -l` 42count=`cat trace | grep -v ^# | wc -l`
33if [ $count -eq 0 ]; then 43if [ $count -eq 0 ]; then
34 fail "none of events are recorded" 44 fail "none of events are recorded"
@@ -37,6 +47,9 @@ fi
37do_reset 47do_reset
38 48
39echo 0 > events/enable 49echo 0 > events/enable
50
51yield
52
40count=`cat trace | grep -v ^# | wc -l` 53count=`cat trace | grep -v ^# | wc -l`
41if [ $count -ne 0 ]; then 54if [ $count -ne 0 ]; then
42 fail "any of events should not be recorded" 55 fail "any of events should not be recorded"
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
index c15e018e0220..15c2dba06ea2 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
@@ -16,7 +16,9 @@ fi
16 16
17do_reset() { 17do_reset() {
18 reset_tracer 18 reset_tracer
19 echo 0 > /proc/sys/kernel/stack_tracer_enabled 19 if [ -e /proc/sys/kernel/stack_tracer_enabled ]; then
20 echo 0 > /proc/sys/kernel/stack_tracer_enabled
21 fi
20 enable_tracing 22 enable_tracing
21 clear_trace 23 clear_trace
22 echo > set_ftrace_filter 24 echo > set_ftrace_filter
@@ -25,7 +27,7 @@ do_reset() {
25fail() { # msg 27fail() { # msg
26 do_reset 28 do_reset
27 echo $1 29 echo $1
28 exit -1 30 exit $FAIL
29} 31}
30 32
31disable_tracing 33disable_tracing
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
index 6af5f6360b18..0ab2189613ef 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
@@ -17,7 +17,7 @@ do_reset() {
17fail() { # msg 17fail() { # msg
18 do_reset 18 do_reset
19 echo $1 19 echo $1
20 exit -1 20 exit $FAIL
21} 21}
22 22
23disable_tracing 23disable_tracing
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
index 2e719cb1fc4d..7808336d6f50 100644
--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
@@ -31,7 +31,7 @@ fail() { # mesg
31 reset_tracer 31 reset_tracer
32 echo > set_ftrace_filter 32 echo > set_ftrace_filter
33 echo $1 33 echo $1
34 exit -1 34 exit $FAIL
35} 35}
36 36
37echo "Testing function tracer with profiler:" 37echo "Testing function tracer with profiler:"
diff --git a/tools/testing/selftests/gen_kselftest_tar.sh b/tools/testing/selftests/gen_kselftest_tar.sh
new file mode 100755
index 000000000000..17d5bd0c0936
--- /dev/null
+++ b/tools/testing/selftests/gen_kselftest_tar.sh
@@ -0,0 +1,55 @@
1#!/bin/bash
2#
3# gen_kselftest_tar
4# Generate kselftest tarball
5# Author: Shuah Khan <shuahkh@osg.samsung.com>
6# Copyright (C) 2015 Samsung Electronics Co., Ltd.
7
8# This software may be freely redistributed under the terms of the GNU
9# General Public License (GPLv2).
10
11# main
12main()
13{
14 if [ "$#" -eq 0 ]; then
15 echo "$0: Generating default compression gzip"
16 copts="cvzf"
17 ext=".tar.gz"
18 else
19 case "$1" in
20 tar)
21 copts="cvf"
22 ext=".tar"
23 ;;
24 targz)
25 copts="cvzf"
26 ext=".tar.gz"
27 ;;
28 tarbz2)
29 copts="cvjf"
30 ext=".tar.bz2"
31 ;;
32 tarxz)
33 copts="cvJf"
34 ext=".tar.xz"
35 ;;
36 *)
37 echo "Unknown tarball format $1"
38 exit 1
39 ;;
40 esac
41 fi
42
43 install_dir=./kselftest
44
45# Run install using INSTALL_KSFT_PATH override to generate install
46# directory
47./kselftest_install.sh
48tar $copts kselftest${ext} $install_dir
49echo "Kselftest archive kselftest${ext} created!"
50
51# clean up install directory
52rm -rf kselftest
53}
54
55main "$@"
diff --git a/tools/testing/selftests/ipc/Makefile b/tools/testing/selftests/ipc/Makefile
index 74bbefdeaf4c..25d2e702c68a 100644
--- a/tools/testing/selftests/ipc/Makefile
+++ b/tools/testing/selftests/ipc/Makefile
@@ -12,14 +12,11 @@ endif
12CFLAGS += -I../../../../usr/include/ 12CFLAGS += -I../../../../usr/include/
13 13
14all: 14all:
15ifeq ($(ARCH),x86) 15 $(CC) $(CFLAGS) msgque.c -o msgque_test
16 gcc $(CFLAGS) msgque.c -o msgque_test 16
17else 17TEST_PROGS := msgque_test
18 echo "Not an x86 target, can't build msgque selftest"
19endif
20 18
21run_tests: all 19include ../lib.mk
22 ./msgque_test
23 20
24clean: 21clean:
25 rm -fr ./msgque_test 22 rm -fr ./msgque_test
diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile
index ff0eefdc6ceb..2ae7450a9a89 100644
--- a/tools/testing/selftests/kcmp/Makefile
+++ b/tools/testing/selftests/kcmp/Makefile
@@ -1,10 +1,10 @@
1CC := $(CROSS_COMPILE)$(CC)
2CFLAGS += -I../../../../usr/include/ 1CFLAGS += -I../../../../usr/include/
3 2
4all: kcmp_test 3all: kcmp_test
5 4
6run_tests: all 5TEST_PROGS := kcmp_test
7 @./kcmp_test || echo "kcmp_test: [FAIL]" 6
7include ../lib.mk
8 8
9clean: 9clean:
10 $(RM) kcmp_test kcmp-test-file 10 $(RM) kcmp_test kcmp-test-file
diff --git a/tools/testing/selftests/kselftest_install.sh b/tools/testing/selftests/kselftest_install.sh
new file mode 100755
index 000000000000..1555fbdb08da
--- /dev/null
+++ b/tools/testing/selftests/kselftest_install.sh
@@ -0,0 +1,37 @@
1#!/bin/bash
2#
3# Kselftest Install
4# Install kselftest tests
5# Author: Shuah Khan <shuahkh@osg.samsung.com>
6# Copyright (C) 2015 Samsung Electronics Co., Ltd.
7
8# This software may be freely redistributed under the terms of the GNU
9# General Public License (GPLv2).
10
11install_loc=`pwd`
12
13main()
14{
15 if [ $(basename $install_loc) != "selftests" ]; then
16 echo "$0: Please run it in selftests directory ..."
17 exit 1;
18 fi
19 if [ "$#" -eq 0 ]; then
20 echo "$0: Installing in default location - $install_loc ..."
21 elif [ ! -d "$1" ]; then
22 echo "$0: $1 doesn't exist!!"
23 exit 1;
24 else
25 install_loc=$1
26 echo "$0: Installing in specified location - $install_loc ..."
27 fi
28
29 install_dir=$install_loc/kselftest
30
31# Create install directory
32 mkdir -p $install_dir
33# Build tests
34 INSTALL_PATH=$install_dir make install
35}
36
37main "$@"
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
new file mode 100644
index 000000000000..2194155ae62a
--- /dev/null
+++ b/tools/testing/selftests/lib.mk
@@ -0,0 +1,35 @@
1# This mimics the top-level Makefile. We do it explicitly here so that this
2# Makefile can operate with or without the kbuild infrastructure.
3CC := $(CROSS_COMPILE)gcc
4
5define RUN_TESTS
6 @for TEST in $(TEST_PROGS); do \
7 (./$$TEST && echo "selftests: $$TEST [PASS]") || echo "selftests: $$TEST [FAIL]"; \
8 done;
9endef
10
11run_tests: all
12 $(RUN_TESTS)
13
14define INSTALL_RULE
15 mkdir -p $(INSTALL_PATH)
16 install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)
17endef
18
19install: all
20ifdef INSTALL_PATH
21 $(INSTALL_RULE)
22else
23 $(error Error: set INSTALL_PATH to use install)
24endif
25
26define EMIT_TESTS
27 @for TEST in $(TEST_PROGS); do \
28 echo "(./$$TEST && echo \"selftests: $$TEST [PASS]\") || echo \"selftests: $$TEST [FAIL]\""; \
29 done;
30endef
31
32emit_tests:
33 $(EMIT_TESTS)
34
35.PHONY: run_tests all clean install emit_tests
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile
index b80cd10d53ba..3e7eb7972511 100644
--- a/tools/testing/selftests/memfd/Makefile
+++ b/tools/testing/selftests/memfd/Makefile
@@ -1,17 +1,19 @@
1CC = $(CROSS_COMPILE)gcc
1CFLAGS += -D_FILE_OFFSET_BITS=64 2CFLAGS += -D_FILE_OFFSET_BITS=64
2CFLAGS += -I../../../../include/uapi/ 3CFLAGS += -I../../../../include/uapi/
3CFLAGS += -I../../../../include/ 4CFLAGS += -I../../../../include/
5CFLAGS += -I../../../../usr/include/
4 6
5all: 7all:
6 gcc $(CFLAGS) memfd_test.c -o memfd_test 8 $(CC) $(CFLAGS) memfd_test.c -o memfd_test
7 9
8run_tests: all 10TEST_PROGS := memfd_test
9 gcc $(CFLAGS) memfd_test.c -o memfd_test 11
10 @./memfd_test || echo "memfd_test: [FAIL]" 12include ../lib.mk
11 13
12build_fuse: 14build_fuse:
13 gcc $(CFLAGS) fuse_mnt.c `pkg-config fuse --cflags --libs` -o fuse_mnt 15 $(CC) $(CFLAGS) fuse_mnt.c `pkg-config fuse --cflags --libs` -o fuse_mnt
14 gcc $(CFLAGS) fuse_test.c -o fuse_test 16 $(CC) $(CFLAGS) fuse_test.c -o fuse_test
15 17
16run_fuse: build_fuse 18run_fuse: build_fuse
17 @./run_fuse_test.sh || echo "fuse_test: [FAIL]" 19 @./run_fuse_test.sh || echo "fuse_test: [FAIL]"
diff --git a/tools/testing/selftests/memory-hotplug/Makefile b/tools/testing/selftests/memory-hotplug/Makefile
index d46b8d489cd2..afb2624c7048 100644
--- a/tools/testing/selftests/memory-hotplug/Makefile
+++ b/tools/testing/selftests/memory-hotplug/Makefile
@@ -1,9 +1,12 @@
1all: 1all:
2 2
3run_tests: 3include ../lib.mk
4 @/bin/bash ./on-off-test.sh -r 2 || echo "memory-hotplug selftests: [FAIL]" 4
5TEST_PROGS := mem-on-off-test.sh
6override RUN_TESTS := ./mem-on-off-test.sh -r 2 || echo "selftests: memory-hotplug [FAIL]"
7override EMIT_TESTS := echo "$(RUN_TESTS)"
5 8
6run_full_test: 9run_full_test:
7 @/bin/bash ./on-off-test.sh || echo "memory-hotplug selftests: [FAIL]" 10 @/bin/bash ./mem-on-off-test.sh || echo "memory-hotplug selftests: [FAIL]"
8 11
9clean: 12clean:
diff --git a/tools/testing/selftests/memory-hotplug/on-off-test.sh b/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh
index 6cddde0b96f8..6cddde0b96f8 100644..100755
--- a/tools/testing/selftests/memory-hotplug/on-off-test.sh
+++ b/tools/testing/selftests/memory-hotplug/mem-on-off-test.sh
diff --git a/tools/testing/selftests/mount/.gitignore b/tools/testing/selftests/mount/.gitignore
new file mode 100644
index 000000000000..856ad4107eb3
--- /dev/null
+++ b/tools/testing/selftests/mount/.gitignore
@@ -0,0 +1 @@
unprivileged-remount-test
diff --git a/tools/testing/selftests/mount/Makefile b/tools/testing/selftests/mount/Makefile
index 337d853c2b72..95580a97326e 100644
--- a/tools/testing/selftests/mount/Makefile
+++ b/tools/testing/selftests/mount/Makefile
@@ -1,17 +1,16 @@
1# Makefile for mount selftests. 1# Makefile for mount selftests.
2 2CFLAGS = -Wall \
3 -O2
3all: unprivileged-remount-test 4all: unprivileged-remount-test
4 5
5unprivileged-remount-test: unprivileged-remount-test.c 6unprivileged-remount-test: unprivileged-remount-test.c
6 gcc -Wall -O2 unprivileged-remount-test.c -o unprivileged-remount-test 7 $(CC) $(CFLAGS) unprivileged-remount-test.c -o unprivileged-remount-test
7 8
8# Allow specific tests to be selected. 9include ../lib.mk
9test_unprivileged_remount: unprivileged-remount-test
10 @if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi
11 10
12run_tests: all test_unprivileged_remount 11TEST_PROGS := unprivileged-remount-test
12override RUN_TESTS := if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi
13override EMIT_TESTS := echo "$(RUN_TESTS)"
13 14
14clean: 15clean:
15 rm -f unprivileged-remount-test 16 rm -f unprivileged-remount-test
16
17.PHONY: all test_unprivileged_remount
diff --git a/tools/testing/selftests/mqueue/Makefile b/tools/testing/selftests/mqueue/Makefile
index 8056e2e68fa4..0e3b41eb85cd 100644
--- a/tools/testing/selftests/mqueue/Makefile
+++ b/tools/testing/selftests/mqueue/Makefile
@@ -1,10 +1,22 @@
1CFLAGS = -O2
2
1all: 3all:
2 gcc -O2 mq_open_tests.c -o mq_open_tests -lrt 4 $(CC) $(CFLAGS) mq_open_tests.c -o mq_open_tests -lrt
3 gcc -O2 -o mq_perf_tests mq_perf_tests.c -lrt -lpthread -lpopt 5 $(CC) $(CFLAGS) -o mq_perf_tests mq_perf_tests.c -lrt -lpthread -lpopt
6
7include ../lib.mk
8
9override define RUN_TESTS
10 @./mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]"
11 @./mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
12endef
13
14TEST_PROGS := mq_open_tests mq_perf_tests
4 15
5run_tests: 16override define EMIT_TESTS
6 @./mq_open_tests /test1 || echo "mq_open_tests: [FAIL]" 17 echo "./mq_open_tests /test1 || echo \"selftests: mq_open_tests [FAIL]\""
7 @./mq_perf_tests || echo "mq_perf_tests: [FAIL]" 18 echo "./mq_perf_tests || echo \"selftests: mq_perf_tests [FAIL]\""
19endef
8 20
9clean: 21clean:
10 rm -f mq_open_tests mq_perf_tests 22 rm -f mq_open_tests mq_perf_tests
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 62f22cc9941c..fac4782c51d8 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -1,6 +1,5 @@
1# Makefile for net selftests 1# Makefile for net selftests
2 2
3CC = $(CROSS_COMPILE)gcc
4CFLAGS = -Wall -O2 -g 3CFLAGS = -Wall -O2 -g
5 4
6CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
@@ -11,9 +10,10 @@ all: $(NET_PROGS)
11%: %.c 10%: %.c
12 $(CC) $(CFLAGS) -o $@ $^ 11 $(CC) $(CFLAGS) -o $@ $^
13 12
14run_tests: all 13TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh
15 @/bin/sh ./run_netsocktests || echo "sockettests: [FAIL]" 14TEST_FILES := $(NET_PROGS)
16 @/bin/sh ./run_afpackettests || echo "afpackettests: [FAIL]" 15
17 ./test_bpf.sh 16include ../lib.mk
17
18clean: 18clean:
19 $(RM) $(NET_PROGS) 19 $(RM) $(NET_PROGS)
diff --git a/tools/testing/selftests/net/run_afpackettests b/tools/testing/selftests/net/run_afpackettests
index 5246e782d6e8..5246e782d6e8 100644..100755
--- a/tools/testing/selftests/net/run_afpackettests
+++ b/tools/testing/selftests/net/run_afpackettests
diff --git a/tools/testing/selftests/net/run_netsocktests b/tools/testing/selftests/net/run_netsocktests
index c09a682df56a..c09a682df56a 100644..100755
--- a/tools/testing/selftests/net/run_netsocktests
+++ b/tools/testing/selftests/net/run_netsocktests
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 1d5e7ad2c460..5ad042345ab9 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -8,27 +8,41 @@ ifeq ($(ARCH),powerpc)
8 8
9GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown") 9GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
10 10
11CC := $(CROSS_COMPILE)$(CC)
12CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS) 11CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
13 12
14export CC CFLAGS 13export CFLAGS
15 14
16TARGETS = pmu copyloops mm tm primitives stringloops 15SUB_DIRS = pmu copyloops mm tm primitives stringloops vphn switch_endian
17 16
18endif 17endif
19 18
20all: $(TARGETS) 19all: $(SUB_DIRS)
21 20
22$(TARGETS): 21$(SUB_DIRS):
23 $(MAKE) -k -C $@ all 22 $(MAKE) -k -C $@ all
24 23
25run_tests: all 24include ../lib.mk
26 @for TARGET in $(TARGETS); do \ 25
26override define RUN_TESTS
27 @for TARGET in $(SUB_DIRS); do \
27 $(MAKE) -C $$TARGET run_tests; \ 28 $(MAKE) -C $$TARGET run_tests; \
28 done; 29 done;
30endef
31
32override define INSTALL_RULE
33 @for TARGET in $(SUB_DIRS); do \
34 $(MAKE) -C $$TARGET install; \
35 done;
36endef
37
38override define EMIT_TESTS
39 @for TARGET in $(SUB_DIRS); do \
40 $(MAKE) -s -C $$TARGET emit_tests; \
41 done;
42endef
29 43
30clean: 44clean:
31 @for TARGET in $(TARGETS); do \ 45 @for TARGET in $(SUB_DIRS); do \
32 $(MAKE) -C $$TARGET clean; \ 46 $(MAKE) -C $$TARGET clean; \
33 done; 47 done;
34 rm -f tags 48 rm -f tags
@@ -36,4 +50,4 @@ clean:
36tags: 50tags:
37 find . -name '*.c' -o -name '*.h' | xargs ctags 51 find . -name '*.c' -o -name '*.h' | xargs ctags
38 52
39.PHONY: all run_tests clean tags $(TARGETS) 53.PHONY: tags $(SUB_DIRS)
diff --git a/tools/testing/selftests/powerpc/copyloops/Makefile b/tools/testing/selftests/powerpc/copyloops/Makefile
index 6f2d3be227f9..384843ea0d40 100644
--- a/tools/testing/selftests/powerpc/copyloops/Makefile
+++ b/tools/testing/selftests/powerpc/copyloops/Makefile
@@ -2,28 +2,24 @@
2CFLAGS += -m64 2CFLAGS += -m64
3CFLAGS += -I$(CURDIR) 3CFLAGS += -I$(CURDIR)
4CFLAGS += -D SELFTEST 4CFLAGS += -D SELFTEST
5CFLAGS += -maltivec
5 6
6# Use our CFLAGS for the implicit .S rule 7# Use our CFLAGS for the implicit .S rule
7ASFLAGS = $(CFLAGS) 8ASFLAGS = $(CFLAGS)
8 9
9PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7 10TEST_PROGS := copyuser_64 copyuser_power7 memcpy_64 memcpy_power7
10EXTRA_SOURCES := validate.c ../harness.c 11EXTRA_SOURCES := validate.c ../harness.c
11 12
12all: $(PROGS) 13all: $(TEST_PROGS)
13 14
14copyuser_64: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base 15copyuser_64: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_base
15copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7 16copyuser_power7: CPPFLAGS += -D COPY_LOOP=test___copy_tofrom_user_power7
16memcpy_64: CPPFLAGS += -D COPY_LOOP=test_memcpy 17memcpy_64: CPPFLAGS += -D COPY_LOOP=test_memcpy
17memcpy_power7: CPPFLAGS += -D COPY_LOOP=test_memcpy_power7 18memcpy_power7: CPPFLAGS += -D COPY_LOOP=test_memcpy_power7
18 19
19$(PROGS): $(EXTRA_SOURCES) 20$(TEST_PROGS): $(EXTRA_SOURCES)
20 21
21run_tests: all 22include ../../lib.mk
22 @-for PROG in $(PROGS); do \
23 ./$$PROG; \
24 done;
25 23
26clean: 24clean:
27 rm -f $(PROGS) *.o 25 rm -f $(TEST_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
index d1dc37425510..50ae7d2091ce 100644
--- a/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
+++ b/tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
@@ -4,39 +4,6 @@
4 4
5#define r1 1 5#define r1 1
6 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 7#define R14 r14
41#define R15 r15 8#define R15 r15
42#define R16 r16 9#define R16 r16
diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
index 8ebc58a09311..f7997affd143 100644
--- a/tools/testing/selftests/powerpc/harness.c
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -11,6 +11,10 @@
11#include <sys/types.h> 11#include <sys/types.h>
12#include <sys/wait.h> 12#include <sys/wait.h>
13#include <unistd.h> 13#include <unistd.h>
14#include <elf.h>
15#include <fcntl.h>
16#include <link.h>
17#include <sys/stat.h>
14 18
15#include "subunit.h" 19#include "subunit.h"
16#include "utils.h" 20#include "utils.h"
@@ -112,3 +116,46 @@ int test_harness(int (test_function)(void), char *name)
112 116
113 return rc; 117 return rc;
114} 118}
119
120static char auxv[4096];
121
122void *get_auxv_entry(int type)
123{
124 ElfW(auxv_t) *p;
125 void *result;
126 ssize_t num;
127 int fd;
128
129 fd = open("/proc/self/auxv", O_RDONLY);
130 if (fd == -1) {
131 perror("open");
132 return NULL;
133 }
134
135 result = NULL;
136
137 num = read(fd, auxv, sizeof(auxv));
138 if (num < 0) {
139 perror("read");
140 goto out;
141 }
142
143 if (num > sizeof(auxv)) {
144 printf("Overflowed auxv buffer\n");
145 goto out;
146 }
147
148 p = (ElfW(auxv_t) *)auxv;
149
150 while (p->a_type != AT_NULL) {
151 if (p->a_type == type) {
152 result = (void *)p->a_un.a_val;
153 break;
154 }
155
156 p++;
157 }
158out:
159 close(fd);
160 return result;
161}
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile
index a14c538dd7f8..41cc3ed66818 100644
--- a/tools/testing/selftests/powerpc/mm/Makefile
+++ b/tools/testing/selftests/powerpc/mm/Makefile
@@ -1,21 +1,16 @@
1noarg: 1noarg:
2 $(MAKE) -C ../ 2 $(MAKE) -C ../
3 3
4PROGS := hugetlb_vs_thp_test subpage_prot 4TEST_PROGS := hugetlb_vs_thp_test subpage_prot
5 5
6all: $(PROGS) tempfile 6all: $(TEST_PROGS) tempfile
7 7
8$(PROGS): ../harness.c 8$(TEST_PROGS): ../harness.c
9 9
10run_tests: all 10include ../../lib.mk
11 @-for PROG in $(PROGS); do \
12 ./$$PROG; \
13 done;
14 11
15tempfile: 12tempfile:
16 dd if=/dev/zero of=tempfile bs=64k count=1 13 dd if=/dev/zero of=tempfile bs=64k count=1
17 14
18clean: 15clean:
19 rm -f $(PROGS) tempfile 16 rm -f $(TEST_PROGS) tempfile
20
21.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c b/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c
index 3d8e5b033e1d..49003674de4f 100644
--- a/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c
+++ b/tools/testing/selftests/powerpc/mm/hugetlb_vs_thp_test.c
@@ -21,9 +21,13 @@ static int test_body(void)
21 * Typically the mmap will fail because no huge pages are 21 * Typically the mmap will fail because no huge pages are
22 * allocated on the system. But if there are huge pages 22 * allocated on the system. But if there are huge pages
23 * allocated the mmap will succeed. That's fine too, we just 23 * allocated the mmap will succeed. That's fine too, we just
24 * munmap here before continuing. 24 * munmap here before continuing. munmap() length of
25 * MAP_HUGETLB memory must be hugepage aligned.
25 */ 26 */
26 munmap(addr, SIZE); 27 if (munmap(addr, SIZE)) {
28 perror("munmap");
29 return 1;
30 }
27 } 31 }
28 32
29 p = mmap(addr, SIZE, PROT_READ | PROT_WRITE, 33 p = mmap(addr, SIZE, PROT_READ | PROT_WRITE,
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
index c9f4263906a5..5a161175bbd4 100644
--- a/tools/testing/selftests/powerpc/pmu/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -1,38 +1,42 @@
1noarg: 1noarg:
2 $(MAKE) -C ../ 2 $(MAKE) -C ../
3 3
4PROGS := count_instructions l3_bank_test per_event_excludes 4TEST_PROGS := count_instructions l3_bank_test per_event_excludes
5EXTRA_SOURCES := ../harness.c event.c lib.c 5EXTRA_SOURCES := ../harness.c event.c lib.c
6 6
7SUB_TARGETS = ebb 7all: $(TEST_PROGS) ebb
8 8
9all: $(PROGS) $(SUB_TARGETS) 9$(TEST_PROGS): $(EXTRA_SOURCES)
10
11$(PROGS): $(EXTRA_SOURCES)
12 10
13# loop.S can only be built 64-bit 11# loop.S can only be built 64-bit
14count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES) 12count_instructions: loop.S count_instructions.c $(EXTRA_SOURCES)
15 $(CC) $(CFLAGS) -m64 -o $@ $^ 13 $(CC) $(CFLAGS) -m64 -o $@ $^
16 14
17run_tests: all sub_run_tests 15include ../../lib.mk
18 @-for PROG in $(PROGS); do \
19 ./$$PROG; \
20 done;
21 16
22clean: sub_clean 17DEFAULT_RUN_TESTS := $(RUN_TESTS)
23 rm -f $(PROGS) loop.o 18override define RUN_TESTS
19 $(DEFAULT_RUN_TESTS)
20 $(MAKE) -C ebb run_tests
21endef
24 22
25$(SUB_TARGETS): 23DEFAULT_EMIT_TESTS := $(EMIT_TESTS)
26 $(MAKE) -k -C $@ all 24override define EMIT_TESTS
25 $(DEFAULT_EMIT_TESTS)
26 $(MAKE) -s -C ebb emit_tests
27endef
27 28
28sub_run_tests: all 29DEFAULT_INSTALL := $(INSTALL_RULE)
29 @for TARGET in $(SUB_TARGETS); do \ 30override define INSTALL_RULE
30 $(MAKE) -C $$TARGET run_tests; \ 31 $(DEFAULT_INSTALL_RULE)
31 done; 32 $(MAKE) -C ebb install
33endef
32 34
33sub_clean: 35clean:
34 @for TARGET in $(SUB_TARGETS); do \ 36 rm -f $(TEST_PROGS) loop.o
35 $(MAKE) -C $$TARGET clean; \ 37 $(MAKE) -C ebb clean
36 done; 38
39ebb:
40 $(MAKE) -k -C $@ all
37 41
38.PHONY: all run_tests clean sub_run_tests sub_clean $(SUB_TARGETS) 42.PHONY: all run_tests clean ebb
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
index 3dc4332698cb..5cdc9dbf2b27 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
@@ -4,7 +4,7 @@ noarg:
4# The EBB handler is 64-bit code and everything links against it 4# The EBB handler is 64-bit code and everything links against it
5CFLAGS += -m64 5CFLAGS += -m64
6 6
7PROGS := reg_access_test event_attributes_test cycles_test \ 7TEST_PROGS := reg_access_test event_attributes_test cycles_test \
8 cycles_with_freeze_test pmc56_overflow_test \ 8 cycles_with_freeze_test pmc56_overflow_test \
9 ebb_vs_cpu_event_test cpu_event_vs_ebb_test \ 9 ebb_vs_cpu_event_test cpu_event_vs_ebb_test \
10 cpu_event_pinned_vs_ebb_test task_event_vs_ebb_test \ 10 cpu_event_pinned_vs_ebb_test task_event_vs_ebb_test \
@@ -16,18 +16,15 @@ PROGS := reg_access_test event_attributes_test cycles_test \
16 lost_exception_test no_handler_test \ 16 lost_exception_test no_handler_test \
17 cycles_with_mmcr2_test 17 cycles_with_mmcr2_test
18 18
19all: $(PROGS) 19all: $(TEST_PROGS)
20 20
21$(PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c busy_loop.S 21$(TEST_PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c busy_loop.S
22 22
23instruction_count_test: ../loop.S 23instruction_count_test: ../loop.S
24 24
25lost_exception_test: ../lib.c 25lost_exception_test: ../lib.c
26 26
27run_tests: all 27include ../../../lib.mk
28 @-for PROG in $(PROGS); do \
29 ./$$PROG; \
30 done;
31 28
32clean: 29clean:
33 rm -f $(PROGS) 30 rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c
index 9768dea37bf3..a07104c2afe6 100644
--- a/tools/testing/selftests/powerpc/pmu/lib.c
+++ b/tools/testing/selftests/powerpc/pmu/lib.c
@@ -5,15 +5,10 @@
5 5
6#define _GNU_SOURCE /* For CPU_ZERO etc. */ 6#define _GNU_SOURCE /* For CPU_ZERO etc. */
7 7
8#include <elf.h>
9#include <errno.h> 8#include <errno.h>
10#include <fcntl.h>
11#include <link.h>
12#include <sched.h> 9#include <sched.h>
13#include <setjmp.h> 10#include <setjmp.h>
14#include <stdlib.h> 11#include <stdlib.h>
15#include <sys/stat.h>
16#include <sys/types.h>
17#include <sys/wait.h> 12#include <sys/wait.h>
18 13
19#include "utils.h" 14#include "utils.h"
@@ -256,45 +251,3 @@ out:
256 return rc; 251 return rc;
257} 252}
258 253
259static char auxv[4096];
260
261void *get_auxv_entry(int type)
262{
263 ElfW(auxv_t) *p;
264 void *result;
265 ssize_t num;
266 int fd;
267
268 fd = open("/proc/self/auxv", O_RDONLY);
269 if (fd == -1) {
270 perror("open");
271 return NULL;
272 }
273
274 result = NULL;
275
276 num = read(fd, auxv, sizeof(auxv));
277 if (num < 0) {
278 perror("read");
279 goto out;
280 }
281
282 if (num > sizeof(auxv)) {
283 printf("Overflowed auxv buffer\n");
284 goto out;
285 }
286
287 p = (ElfW(auxv_t) *)auxv;
288
289 while (p->a_type != AT_NULL) {
290 if (p->a_type == type) {
291 result = (void *)p->a_un.a_val;
292 break;
293 }
294
295 p++;
296 }
297out:
298 close(fd);
299 return result;
300}
diff --git a/tools/testing/selftests/powerpc/pmu/lib.h b/tools/testing/selftests/powerpc/pmu/lib.h
index 0f0339c8a6f6..ca5d72ae3be6 100644
--- a/tools/testing/selftests/powerpc/pmu/lib.h
+++ b/tools/testing/selftests/powerpc/pmu/lib.h
@@ -29,7 +29,6 @@ extern int notify_parent(union pipe write_pipe);
29extern int notify_parent_of_error(union pipe write_pipe); 29extern int notify_parent_of_error(union pipe write_pipe);
30extern pid_t eat_cpu(int (test_function)(void)); 30extern pid_t eat_cpu(int (test_function)(void));
31extern bool require_paranoia_below(int level); 31extern bool require_paranoia_below(int level);
32extern void *get_auxv_entry(int type);
33 32
34struct addr_range { 33struct addr_range {
35 uint64_t first, last; 34 uint64_t first, last;
diff --git a/tools/testing/selftests/powerpc/primitives/Makefile b/tools/testing/selftests/powerpc/primitives/Makefile
index ea737ca01732..b68c6221d3d1 100644
--- a/tools/testing/selftests/powerpc/primitives/Makefile
+++ b/tools/testing/selftests/powerpc/primitives/Makefile
@@ -1,17 +1,12 @@
1CFLAGS += -I$(CURDIR) 1CFLAGS += -I$(CURDIR)
2 2
3PROGS := load_unaligned_zeropad 3TEST_PROGS := load_unaligned_zeropad
4 4
5all: $(PROGS) 5all: $(TEST_PROGS)
6 6
7$(PROGS): ../harness.c 7$(TEST_PROGS): ../harness.c
8 8
9run_tests: all 9include ../../lib.mk
10 @-for PROG in $(PROGS); do \
11 ./$$PROG; \
12 done;
13 10
14clean: 11clean:
15 rm -f $(PROGS) *.o 12 rm -f $(TEST_PROGS) *.o
16
17.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/stringloops/Makefile b/tools/testing/selftests/powerpc/stringloops/Makefile
index 506d77346477..2a728f4d2873 100644
--- a/tools/testing/selftests/powerpc/stringloops/Makefile
+++ b/tools/testing/selftests/powerpc/stringloops/Makefile
@@ -2,19 +2,14 @@
2CFLAGS += -m64 2CFLAGS += -m64
3CFLAGS += -I$(CURDIR) 3CFLAGS += -I$(CURDIR)
4 4
5PROGS := memcmp 5TEST_PROGS := memcmp
6EXTRA_SOURCES := memcmp_64.S ../harness.c 6EXTRA_SOURCES := memcmp_64.S ../harness.c
7 7
8all: $(PROGS) 8all: $(TEST_PROGS)
9 9
10$(PROGS): $(EXTRA_SOURCES) 10$(TEST_PROGS): $(EXTRA_SOURCES)
11 11
12run_tests: all 12include ../../lib.mk
13 @-for PROG in $(PROGS); do \
14 ./$$PROG; \
15 done;
16 13
17clean: 14clean:
18 rm -f $(PROGS) *.o 15 rm -f $(TEST_PROGS) *.o
19
20.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/switch_endian/.gitignore b/tools/testing/selftests/powerpc/switch_endian/.gitignore
new file mode 100644
index 000000000000..89e762eab676
--- /dev/null
+++ b/tools/testing/selftests/powerpc/switch_endian/.gitignore
@@ -0,0 +1,2 @@
1switch_endian_test
2check-reversed.S
diff --git a/tools/testing/selftests/powerpc/switch_endian/Makefile b/tools/testing/selftests/powerpc/switch_endian/Makefile
new file mode 100644
index 000000000000..081473db22b7
--- /dev/null
+++ b/tools/testing/selftests/powerpc/switch_endian/Makefile
@@ -0,0 +1,24 @@
1CC := $(CROSS_COMPILE)gcc
2PROGS := switch_endian_test
3
4ASFLAGS += -O2 -Wall -g -nostdlib -m64
5
6all: $(PROGS)
7
8switch_endian_test: check-reversed.S
9
10check-reversed.o: check.o
11 $(CROSS_COMPILE)objcopy -j .text --reverse-bytes=4 -O binary $< $@
12
13check-reversed.S: check-reversed.o
14 hexdump -v -e '/1 ".byte 0x%02X\n"' $< > $@
15
16run_tests: all
17 @-for PROG in $(PROGS); do \
18 ./$$PROG; \
19 done;
20
21clean:
22 rm -f $(PROGS) *.o check-reversed.S
23
24.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/switch_endian/check.S b/tools/testing/selftests/powerpc/switch_endian/check.S
new file mode 100644
index 000000000000..e2484d2c24f4
--- /dev/null
+++ b/tools/testing/selftests/powerpc/switch_endian/check.S
@@ -0,0 +1,100 @@
1#include "common.h"
2
3/*
4 * Checks that registers contain what we expect, ie. they were not clobbered by
5 * the syscall.
6 *
7 * r15: pattern to check registers against.
8 *
9 * At the end r3 == 0 if everything's OK.
10 */
11 nop # guaranteed to be illegal in reverse-endian
12 mr r9,r15
13 cmpd r9,r3 # check r3
14 bne 1f
15 addi r9,r15,4 # check r4
16 cmpd r9,r4
17 bne 1f
18 lis r9,0x00FF # check CR
19 ori r9,r9,0xF000
20 mfcr r10
21 and r10,r10,r9
22 cmpw r9,r10
23 addi r9,r15,34
24 bne 1f
25 addi r9,r15,32 # check LR
26 mflr r10
27 cmpd r9,r10
28 bne 1f
29 addi r9,r15,5 # check r5
30 cmpd r9,r5
31 bne 1f
32 addi r9,r15,6 # check r6
33 cmpd r9,r6
34 bne 1f
35 addi r9,r15,7 # check r7
36 cmpd r9,r7
37 bne 1f
38 addi r9,r15,8 # check r8
39 cmpd r9,r8
40 bne 1f
41 addi r9,r15,13 # check r13
42 cmpd r9,r13
43 bne 1f
44 addi r9,r15,14 # check r14
45 cmpd r9,r14
46 bne 1f
47 addi r9,r15,16 # check r16
48 cmpd r9,r16
49 bne 1f
50 addi r9,r15,17 # check r17
51 cmpd r9,r17
52 bne 1f
53 addi r9,r15,18 # check r18
54 cmpd r9,r18
55 bne 1f
56 addi r9,r15,19 # check r19
57 cmpd r9,r19
58 bne 1f
59 addi r9,r15,20 # check r20
60 cmpd r9,r20
61 bne 1f
62 addi r9,r15,21 # check r21
63 cmpd r9,r21
64 bne 1f
65 addi r9,r15,22 # check r22
66 cmpd r9,r22
67 bne 1f
68 addi r9,r15,23 # check r23
69 cmpd r9,r23
70 bne 1f
71 addi r9,r15,24 # check r24
72 cmpd r9,r24
73 bne 1f
74 addi r9,r15,25 # check r25
75 cmpd r9,r25
76 bne 1f
77 addi r9,r15,26 # check r26
78 cmpd r9,r26
79 bne 1f
80 addi r9,r15,27 # check r27
81 cmpd r9,r27
82 bne 1f
83 addi r9,r15,28 # check r28
84 cmpd r9,r28
85 bne 1f
86 addi r9,r15,29 # check r29
87 cmpd r9,r29
88 bne 1f
89 addi r9,r15,30 # check r30
90 cmpd r9,r30
91 bne 1f
92 addi r9,r15,31 # check r31
93 cmpd r9,r31
94 bne 1f
95 b 2f
961: mr r3, r9
97 li r0, __NR_exit
98 sc
992: li r0, __NR_switch_endian
100 nop
diff --git a/tools/testing/selftests/powerpc/switch_endian/common.h b/tools/testing/selftests/powerpc/switch_endian/common.h
new file mode 100644
index 000000000000..69e399698c64
--- /dev/null
+++ b/tools/testing/selftests/powerpc/switch_endian/common.h
@@ -0,0 +1,6 @@
1#include <ppc-asm.h>
2#include <asm/unistd.h>
3
4#ifndef __NR_switch_endian
5#define __NR_switch_endian 363
6#endif
diff --git a/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
new file mode 100644
index 000000000000..ef7c971abb67
--- /dev/null
+++ b/tools/testing/selftests/powerpc/switch_endian/switch_endian_test.S
@@ -0,0 +1,81 @@
1#include "common.h"
2
3 .data
4 .balign 8
5message:
6 .ascii "success: switch_endian_test\n\0"
7
8 .section ".toc"
9 .balign 8
10pattern:
11 .llong 0x5555AAAA5555AAAA
12
13 .text
14FUNC_START(_start)
15 /* Load the pattern */
16 ld r15, pattern@TOC(%r2)
17
18 /* Setup CR, only CR2-CR4 are maintained */
19 lis r3, 0x00FF
20 ori r3, r3, 0xF000
21 mtcr r3
22
23 /* Load the pattern slightly modified into the registers */
24 mr r3, r15
25 addi r4, r15, 4
26
27 addi r5, r15, 32
28 mtlr r5
29
30 addi r5, r15, 5
31 addi r6, r15, 6
32 addi r7, r15, 7
33 addi r8, r15, 8
34
35 /* r9 - r12 are clobbered */
36
37 addi r13, r15, 13
38 addi r14, r15, 14
39
40 /* Skip r15 we're using it */
41
42 addi r16, r15, 16
43 addi r17, r15, 17
44 addi r18, r15, 18
45 addi r19, r15, 19
46 addi r20, r15, 20
47 addi r21, r15, 21
48 addi r22, r15, 22
49 addi r23, r15, 23
50 addi r24, r15, 24
51 addi r25, r15, 25
52 addi r26, r15, 26
53 addi r27, r15, 27
54 addi r28, r15, 28
55 addi r29, r15, 29
56 addi r30, r15, 30
57 addi r31, r15, 31
58
59 /*
60 * Call the syscall to switch endian.
61 * It clobbers r9-r12, XER, CTR and CR0-1,5-7.
62 */
63 li r0, __NR_switch_endian
64 sc
65
66#include "check-reversed.S"
67
68 /* Flip back, r0 already has the switch syscall number */
69 .long 0x02000044 /* sc */
70
71#include "check.S"
72
73 li r0, __NR_write
74 li r3, 1 /* stdout */
75 ld r4, message@got(%r2)
76 li r5, 28 /* strlen(message3) */
77 sc
78 li r0, __NR_exit
79 li r3, 0
80 sc
81 b .
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 33d02cc54a3e..2699635d2cd9 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -1 +1,2 @@
1tm-resched-dscr 1tm-resched-dscr
2tm-syscall
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 2cede239a074..1b616fa79e93 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,15 +1,13 @@
1PROGS := tm-resched-dscr 1TEST_PROGS := tm-resched-dscr tm-syscall
2 2
3all: $(PROGS) 3all: $(TEST_PROGS)
4 4
5$(PROGS): ../harness.c 5$(TEST_PROGS): ../harness.c
6 6
7run_tests: all 7tm-syscall: tm-syscall-asm.S
8 @-for PROG in $(PROGS); do \ 8tm-syscall: CFLAGS += -mhtm
9 ./$$PROG; \
10 done;
11 9
12clean: 10include ../../lib.mk
13 rm -f $(PROGS) *.o
14 11
15.PHONY: all run_tests clean 12clean:
13 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/tm/tm-syscall-asm.S b/tools/testing/selftests/powerpc/tm/tm-syscall-asm.S
new file mode 100644
index 000000000000..431f61ae2368
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-syscall-asm.S
@@ -0,0 +1,27 @@
1#include <ppc-asm.h>
2#include <asm/unistd.h>
3
4 .text
5FUNC_START(getppid_tm_active)
6 tbegin.
7 beq 1f
8 li r0, __NR_getppid
9 sc
10 tend.
11 blr
121:
13 li r3, -1
14 blr
15
16FUNC_START(getppid_tm_suspended)
17 tbegin.
18 beq 1f
19 li r0, __NR_getppid
20 tsuspend.
21 sc
22 tresume.
23 tend.
24 blr
251:
26 li r3, -1
27 blr
diff --git a/tools/testing/selftests/powerpc/tm/tm-syscall.c b/tools/testing/selftests/powerpc/tm/tm-syscall.c
new file mode 100644
index 000000000000..3ed8d4b252fa
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-syscall.c
@@ -0,0 +1,121 @@
1/*
2 * Copyright 2015, Sam Bobroff, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Test the kernel's system call code to ensure that a system call
6 * made from within an active HTM transaction is aborted with the
7 * correct failure code.
8 * Conversely, ensure that a system call made from within a
9 * suspended transaction can succeed.
10 */
11
12#include <stdio.h>
13#include <unistd.h>
14#include <sys/syscall.h>
15#include <asm/tm.h>
16#include <asm/cputable.h>
17#include <linux/auxvec.h>
18#include <sys/time.h>
19#include <stdlib.h>
20
21#include "utils.h"
22
23extern int getppid_tm_active(void);
24extern int getppid_tm_suspended(void);
25
26unsigned retries = 0;
27
28#define TEST_DURATION 10 /* seconds */
29#define TM_RETRIES 100
30
31long failure_code(void)
32{
33 return __builtin_get_texasru() >> 24;
34}
35
36bool failure_is_persistent(void)
37{
38 return (failure_code() & TM_CAUSE_PERSISTENT) == TM_CAUSE_PERSISTENT;
39}
40
41bool failure_is_syscall(void)
42{
43 return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL;
44}
45
46pid_t getppid_tm(bool suspend)
47{
48 int i;
49 pid_t pid;
50
51 for (i = 0; i < TM_RETRIES; i++) {
52 if (suspend)
53 pid = getppid_tm_suspended();
54 else
55 pid = getppid_tm_active();
56
57 if (pid >= 0)
58 return pid;
59
60 if (failure_is_persistent()) {
61 if (failure_is_syscall())
62 return -1;
63
64 printf("Unexpected persistent transaction failure.\n");
65 printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
66 __builtin_get_texasr(), __builtin_get_tfiar());
67 exit(-1);
68 }
69
70 retries++;
71 }
72
73 printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES);
74 printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
75 __builtin_get_texasr(), __builtin_get_tfiar());
76
77 exit(-1);
78}
79
80int tm_syscall(void)
81{
82 unsigned count = 0;
83 struct timeval end, now;
84
85 SKIP_IF(!((long)get_auxv_entry(AT_HWCAP2) & PPC_FEATURE2_HTM));
86 setbuf(stdout, NULL);
87
88 printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION);
89
90 gettimeofday(&end, NULL);
91 now.tv_sec = TEST_DURATION;
92 now.tv_usec = 0;
93 timeradd(&end, &now, &end);
94
95 for (count = 0; timercmp(&now, &end, <); count++) {
96 /*
97 * Test a syscall within a suspended transaction and verify
98 * that it succeeds.
99 */
100 FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */
101
102 /*
103 * Test a syscall within an active transaction and verify that
104 * it fails with the correct failure code.
105 */
106 FAIL_IF(getppid_tm(false) != -1); /* Should fail... */
107 FAIL_IF(!failure_is_persistent()); /* ...persistently... */
108 FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */
109 gettimeofday(&now, 0);
110 }
111
112 printf("%d active and suspended transactions behaved correctly.\n", count);
113 printf("(There were %d transaction retries.)\n", retries);
114
115 return 0;
116}
117
118int main(void)
119{
120 return test_harness(tm_syscall, "tm_syscall");
121}
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index a93777ae0684..b7d41086bb0a 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -15,11 +15,12 @@ typedef signed long long s64;
15 15
16/* Just for familiarity */ 16/* Just for familiarity */
17typedef uint32_t u32; 17typedef uint32_t u32;
18typedef uint16_t u16;
18typedef uint8_t u8; 19typedef uint8_t u8;
19 20
20 21
21int test_harness(int (test_function)(void), char *name); 22int test_harness(int (test_function)(void), char *name);
22 23extern void *get_auxv_entry(int type);
23 24
24/* Yes, this is evil */ 25/* Yes, this is evil */
25#define FAIL_IF(x) \ 26#define FAIL_IF(x) \
diff --git a/tools/testing/selftests/powerpc/vphn/.gitignore b/tools/testing/selftests/powerpc/vphn/.gitignore
new file mode 100644
index 000000000000..7c04395010cb
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vphn/.gitignore
@@ -0,0 +1 @@
test-vphn
diff --git a/tools/testing/selftests/powerpc/vphn/Makefile b/tools/testing/selftests/powerpc/vphn/Makefile
new file mode 100644
index 000000000000..e539f775fd8f
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vphn/Makefile
@@ -0,0 +1,15 @@
1PROG := test-vphn
2
3CFLAGS += -m64
4
5all: $(PROG)
6
7$(PROG): ../harness.c
8
9run_tests: all
10 ./$(PROG)
11
12clean:
13 rm -f $(PROG)
14
15.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/vphn/test-vphn.c b/tools/testing/selftests/powerpc/vphn/test-vphn.c
new file mode 100644
index 000000000000..5742f6876b25
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vphn/test-vphn.c
@@ -0,0 +1,410 @@
1#include <stdio.h>
2#include <byteswap.h>
3#include "utils.h"
4#include "subunit.h"
5
6#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
7#define cpu_to_be32(x) bswap_32(x)
8#define be32_to_cpu(x) bswap_32(x)
9#define be16_to_cpup(x) bswap_16(*x)
10#define cpu_to_be64(x) bswap_64(x)
11#else
12#define cpu_to_be32(x) (x)
13#define be32_to_cpu(x) (x)
14#define be16_to_cpup(x) (*x)
15#define cpu_to_be64(x) (x)
16#endif
17
18#include "vphn.c"
19
20static struct test {
21 char *descr;
22 long input[VPHN_REGISTER_COUNT];
23 u32 expected[VPHN_ASSOC_BUFSIZE];
24} all_tests[] = {
25 {
26 "vphn: no data",
27 {
28 0xffffffffffffffff,
29 0xffffffffffffffff,
30 0xffffffffffffffff,
31 0xffffffffffffffff,
32 0xffffffffffffffff,
33 0xffffffffffffffff,
34 },
35 {
36 0x00000000
37 }
38 },
39 {
40 "vphn: 1 x 16-bit value",
41 {
42 0x8001ffffffffffff,
43 0xffffffffffffffff,
44 0xffffffffffffffff,
45 0xffffffffffffffff,
46 0xffffffffffffffff,
47 0xffffffffffffffff,
48 },
49 {
50 0x00000001,
51 0x00000001
52 }
53 },
54 {
55 "vphn: 2 x 16-bit values",
56 {
57 0x80018002ffffffff,
58 0xffffffffffffffff,
59 0xffffffffffffffff,
60 0xffffffffffffffff,
61 0xffffffffffffffff,
62 0xffffffffffffffff,
63 },
64 {
65 0x00000002,
66 0x00000001,
67 0x00000002
68 }
69 },
70 {
71 "vphn: 3 x 16-bit values",
72 {
73 0x800180028003ffff,
74 0xffffffffffffffff,
75 0xffffffffffffffff,
76 0xffffffffffffffff,
77 0xffffffffffffffff,
78 0xffffffffffffffff,
79 },
80 {
81 0x00000003,
82 0x00000001,
83 0x00000002,
84 0x00000003
85 }
86 },
87 {
88 "vphn: 4 x 16-bit values",
89 {
90 0x8001800280038004,
91 0xffffffffffffffff,
92 0xffffffffffffffff,
93 0xffffffffffffffff,
94 0xffffffffffffffff,
95 0xffffffffffffffff,
96 },
97 {
98 0x00000004,
99 0x00000001,
100 0x00000002,
101 0x00000003,
102 0x00000004
103 }
104 },
105 {
106 /* Parsing the next 16-bit value out of the next 64-bit input
107 * value.
108 */
109 "vphn: 5 x 16-bit values",
110 {
111 0x8001800280038004,
112 0x8005ffffffffffff,
113 0xffffffffffffffff,
114 0xffffffffffffffff,
115 0xffffffffffffffff,
116 0xffffffffffffffff,
117 },
118 {
119 0x00000005,
120 0x00000001,
121 0x00000002,
122 0x00000003,
123 0x00000004,
124 0x00000005
125 }
126 },
127 {
128 /* Parse at most 6 x 64-bit input values */
129 "vphn: 24 x 16-bit values",
130 {
131 0x8001800280038004,
132 0x8005800680078008,
133 0x8009800a800b800c,
134 0x800d800e800f8010,
135 0x8011801280138014,
136 0x8015801680178018
137 },
138 {
139 0x00000018,
140 0x00000001,
141 0x00000002,
142 0x00000003,
143 0x00000004,
144 0x00000005,
145 0x00000006,
146 0x00000007,
147 0x00000008,
148 0x00000009,
149 0x0000000a,
150 0x0000000b,
151 0x0000000c,
152 0x0000000d,
153 0x0000000e,
154 0x0000000f,
155 0x00000010,
156 0x00000011,
157 0x00000012,
158 0x00000013,
159 0x00000014,
160 0x00000015,
161 0x00000016,
162 0x00000017,
163 0x00000018
164 }
165 },
166 {
167 "vphn: 1 x 32-bit value",
168 {
169 0x00000001ffffffff,
170 0xffffffffffffffff,
171 0xffffffffffffffff,
172 0xffffffffffffffff,
173 0xffffffffffffffff,
174 0xffffffffffffffff
175 },
176 {
177 0x00000001,
178 0x00000001
179 }
180 },
181 {
182 "vphn: 2 x 32-bit values",
183 {
184 0x0000000100000002,
185 0xffffffffffffffff,
186 0xffffffffffffffff,
187 0xffffffffffffffff,
188 0xffffffffffffffff,
189 0xffffffffffffffff
190 },
191 {
192 0x00000002,
193 0x00000001,
194 0x00000002
195 }
196 },
197 {
198 /* Parsing the next 32-bit value out of the next 64-bit input
199 * value.
200 */
201 "vphn: 3 x 32-bit values",
202 {
203 0x0000000100000002,
204 0x00000003ffffffff,
205 0xffffffffffffffff,
206 0xffffffffffffffff,
207 0xffffffffffffffff,
208 0xffffffffffffffff
209 },
210 {
211 0x00000003,
212 0x00000001,
213 0x00000002,
214 0x00000003
215 }
216 },
217 {
218 /* Parse at most 6 x 64-bit input values */
219 "vphn: 12 x 32-bit values",
220 {
221 0x0000000100000002,
222 0x0000000300000004,
223 0x0000000500000006,
224 0x0000000700000008,
225 0x000000090000000a,
226 0x0000000b0000000c
227 },
228 {
229 0x0000000c,
230 0x00000001,
231 0x00000002,
232 0x00000003,
233 0x00000004,
234 0x00000005,
235 0x00000006,
236 0x00000007,
237 0x00000008,
238 0x00000009,
239 0x0000000a,
240 0x0000000b,
241 0x0000000c
242 }
243 },
244 {
245 "vphn: 16-bit value followed by 32-bit value",
246 {
247 0x800100000002ffff,
248 0xffffffffffffffff,
249 0xffffffffffffffff,
250 0xffffffffffffffff,
251 0xffffffffffffffff,
252 0xffffffffffffffff
253 },
254 {
255 0x00000002,
256 0x00000001,
257 0x00000002
258 }
259 },
260 {
261 "vphn: 32-bit value followed by 16-bit value",
262 {
263 0x000000018002ffff,
264 0xffffffffffffffff,
265 0xffffffffffffffff,
266 0xffffffffffffffff,
267 0xffffffffffffffff,
268 0xffffffffffffffff
269 },
270 {
271 0x00000002,
272 0x00000001,
273 0x00000002
274 }
275 },
276 {
277 /* Parse a 32-bit value split accross two consecutives 64-bit
278 * input values.
279 */
280 "vphn: 16-bit value followed by 2 x 32-bit values",
281 {
282 0x8001000000020000,
283 0x0003ffffffffffff,
284 0xffffffffffffffff,
285 0xffffffffffffffff,
286 0xffffffffffffffff,
287 0xffffffffffffffff
288 },
289 {
290 0x00000003,
291 0x00000001,
292 0x00000002,
293 0x00000003,
294 0x00000004,
295 0x00000005
296 }
297 },
298 {
299 /* The lower bits in 0x0001ffff don't get mixed up with the
300 * 0xffff terminator.
301 */
302 "vphn: 32-bit value has all ones in 16 lower bits",
303 {
304 0x0001ffff80028003,
305 0xffffffffffffffff,
306 0xffffffffffffffff,
307 0xffffffffffffffff,
308 0xffffffffffffffff,
309 0xffffffffffffffff
310 },
311 {
312 0x00000003,
313 0x0001ffff,
314 0x00000002,
315 0x00000003
316 }
317 },
318 {
319 /* The following input doesn't follow the specification.
320 */
321 "vphn: last 32-bit value is truncated",
322 {
323 0x0000000100000002,
324 0x0000000300000004,
325 0x0000000500000006,
326 0x0000000700000008,
327 0x000000090000000a,
328 0x0000000b800c2bad
329 },
330 {
331 0x0000000c,
332 0x00000001,
333 0x00000002,
334 0x00000003,
335 0x00000004,
336 0x00000005,
337 0x00000006,
338 0x00000007,
339 0x00000008,
340 0x00000009,
341 0x0000000a,
342 0x0000000b,
343 0x0000000c
344 }
345 },
346 {
347 "vphn: garbage after terminator",
348 {
349 0xffff2bad2bad2bad,
350 0x2bad2bad2bad2bad,
351 0x2bad2bad2bad2bad,
352 0x2bad2bad2bad2bad,
353 0x2bad2bad2bad2bad,
354 0x2bad2bad2bad2bad
355 },
356 {
357 0x00000000
358 }
359 },
360 {
361 NULL
362 }
363};
364
365static int test_one(struct test *test)
366{
367 __be32 output[VPHN_ASSOC_BUFSIZE] = { 0 };
368 int i, len;
369
370 vphn_unpack_associativity(test->input, output);
371
372 len = be32_to_cpu(output[0]);
373 if (len != test->expected[0]) {
374 printf("expected %d elements, got %d\n", test->expected[0],
375 len);
376 return 1;
377 }
378
379 for (i = 1; i < len; i++) {
380 u32 val = be32_to_cpu(output[i]);
381 if (val != test->expected[i]) {
382 printf("element #%d is 0x%x, should be 0x%x\n", i, val,
383 test->expected[i]);
384 return 1;
385 }
386 }
387
388 return 0;
389}
390
391static int test_vphn(void)
392{
393 static struct test *test;
394
395 for (test = all_tests; test->descr; test++) {
396 int ret;
397
398 ret = test_one(test);
399 test_finish(test->descr, ret);
400 if (ret)
401 return ret;
402 }
403
404 return 0;
405}
406
407int main(int argc, char **argv)
408{
409 return test_harness(test_vphn, "test-vphn");
410}
diff --git a/tools/testing/selftests/powerpc/vphn/vphn.c b/tools/testing/selftests/powerpc/vphn/vphn.c
new file mode 120000
index 000000000000..186b906e66d5
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vphn/vphn.c
@@ -0,0 +1 @@
../../../../../arch/powerpc/mm/vphn.c \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/vphn/vphn.h b/tools/testing/selftests/powerpc/vphn/vphn.h
new file mode 120000
index 000000000000..7131efe38c65
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vphn/vphn.h
@@ -0,0 +1 @@
../../../../../arch/powerpc/mm/vphn.h \ No newline at end of file
diff --git a/tools/testing/selftests/ptrace/Makefile b/tools/testing/selftests/ptrace/Makefile
index 47ae2d385ce8..453927fea90c 100644
--- a/tools/testing/selftests/ptrace/Makefile
+++ b/tools/testing/selftests/ptrace/Makefile
@@ -6,5 +6,6 @@ all: peeksiginfo
6clean: 6clean:
7 rm -f peeksiginfo 7 rm -f peeksiginfo
8 8
9run_tests: all 9TEST_PROGS := peeksiginfo
10 @./peeksiginfo || echo "peeksiginfo selftests: [FAIL]" 10
11include ../lib.mk
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 368d64ac779e..dd2812ceb0ba 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -310,7 +310,7 @@ function dump(first, pastlast)
310 cfr[jn] = cf[j] "." cfrep[cf[j]]; 310 cfr[jn] = cf[j] "." cfrep[cf[j]];
311 } 311 }
312 if (cpusr[jn] > ncpus && ncpus != 0) 312 if (cpusr[jn] > ncpus && ncpus != 0)
313 ovf = "(!)"; 313 ovf = "-ovf";
314 else 314 else
315 ovf = ""; 315 ovf = "";
316 print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date`"; 316 print "echo ", cfr[jn], cpusr[jn] ovf ": Starting build. `date`";
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
index d2d2a86139db..49701218dc62 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
@@ -1,2 +1,3 @@
1CONFIG_RCU_TORTURE_TEST=y 1CONFIG_RCU_TORTURE_TEST=y
2CONFIG_PRINTK_TIME=y 2CONFIG_PRINTK_TIME=y
3CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
diff --git a/tools/testing/selftests/size/Makefile b/tools/testing/selftests/size/Makefile
index 04dc25e4fa92..bbd0b5398b61 100644
--- a/tools/testing/selftests/size/Makefile
+++ b/tools/testing/selftests/size/Makefile
@@ -1,12 +1,11 @@
1CC = $(CROSS_COMPILE)gcc
2
3all: get_size 1all: get_size
4 2
5get_size: get_size.c 3get_size: get_size.c
6 $(CC) -static -ffreestanding -nostartfiles -s $< -o $@ 4 $(CC) -static -ffreestanding -nostartfiles -s $< -o $@
7 5
8run_tests: all 6TEST_PROGS := get_size
9 ./get_size 7
8include ../lib.mk
10 9
11clean: 10clean:
12 $(RM) get_size 11 $(RM) get_size
diff --git a/tools/testing/selftests/sysctl/Makefile b/tools/testing/selftests/sysctl/Makefile
index 0a92adaf0865..b3c33e071f10 100644
--- a/tools/testing/selftests/sysctl/Makefile
+++ b/tools/testing/selftests/sysctl/Makefile
@@ -4,16 +4,10 @@
4# No binaries, but make sure arg-less "make" doesn't trigger "run_tests". 4# No binaries, but make sure arg-less "make" doesn't trigger "run_tests".
5all: 5all:
6 6
7# Allow specific tests to be selected. 7TEST_PROGS := run_numerictests run_stringtests
8test_num: 8TEST_FILES := common_tests
9 @/bin/sh ./run_numerictests
10 9
11test_string: 10include ../lib.mk
12 @/bin/sh ./run_stringtests
13
14run_tests: all test_num test_string
15 11
16# Nothing to clean up. 12# Nothing to clean up.
17clean: 13clean:
18
19.PHONY: all run_tests clean test_num test_string
diff --git a/tools/testing/selftests/sysctl/run_numerictests b/tools/testing/selftests/sysctl/run_numerictests
index 8510f93f2d14..8510f93f2d14 100644..100755
--- a/tools/testing/selftests/sysctl/run_numerictests
+++ b/tools/testing/selftests/sysctl/run_numerictests
diff --git a/tools/testing/selftests/sysctl/run_stringtests b/tools/testing/selftests/sysctl/run_stringtests
index 90a9293d520c..90a9293d520c 100644..100755
--- a/tools/testing/selftests/sysctl/run_stringtests
+++ b/tools/testing/selftests/sysctl/run_stringtests
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index eb2859f4ad21..89a3f44bf355 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -1,8 +1,36 @@
1all: 1CC = $(CROSS_COMPILE)gcc
2 gcc posix_timers.c -o posix_timers -lrt 2BUILD_FLAGS = -DKTEST
3CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
4LDFLAGS += -lrt -lpthread
3 5
4run_tests: all 6# these are all "safe" tests that don't modify
5 ./posix_timers 7# system time or require escalated privledges
8TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
9 inconsistency-check raw_skew threadtest rtctest
10
11TEST_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex change_skew \
12 skew_consistency clocksource-switch leap-a-day \
13 leapcrash set-tai set-2038
14
15bins = $(TEST_PROGS) $(TEST_PROGS_EXTENDED)
16
17all: ${bins}
18
19include ../lib.mk
20
21# these tests require escalated privledges
22# and may modify the system time or trigger
23# other behavior like suspend
24run_destructive_tests: run_tests
25 ./alarmtimer-suspend
26 ./valid-adjtimex
27 ./change_skew
28 ./skew_consistency
29 ./clocksource-switch
30 ./leap-a-day -s -i 10
31 ./leapcrash
32 ./set-tai
33 ./set-2038
6 34
7clean: 35clean:
8 rm -f ./posix_timers 36 rm -f ${bins}
diff --git a/tools/testing/selftests/timers/alarmtimer-suspend.c b/tools/testing/selftests/timers/alarmtimer-suspend.c
new file mode 100644
index 000000000000..aaffbde1d5ee
--- /dev/null
+++ b/tools/testing/selftests/timers/alarmtimer-suspend.c
@@ -0,0 +1,185 @@
1/* alarmtimer suspend test
2 * John Stultz (john.stultz@linaro.org)
3 * (C) Copyright Linaro 2013
4 * Licensed under the GPLv2
5 *
6 * This test makes sure the alarmtimer & RTC wakeup code is
7 * functioning.
8 *
9 * To build:
10 * $ gcc alarmtimer-suspend.c -o alarmtimer-suspend -lrt
11 *
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 */
22
23
24#include <stdio.h>
25#include <unistd.h>
26#include <time.h>
27#include <string.h>
28#include <signal.h>
29#include <stdlib.h>
30#include <pthread.h>
31#ifdef KTEST
32#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43
44#define CLOCK_REALTIME 0
45#define CLOCK_MONOTONIC 1
46#define CLOCK_PROCESS_CPUTIME_ID 2
47#define CLOCK_THREAD_CPUTIME_ID 3
48#define CLOCK_MONOTONIC_RAW 4
49#define CLOCK_REALTIME_COARSE 5
50#define CLOCK_MONOTONIC_COARSE 6
51#define CLOCK_BOOTTIME 7
52#define CLOCK_REALTIME_ALARM 8
53#define CLOCK_BOOTTIME_ALARM 9
54#define CLOCK_HWSPECIFIC 10
55#define CLOCK_TAI 11
56#define NR_CLOCKIDS 12
57
58
59#define NSEC_PER_SEC 1000000000ULL
60#define UNREASONABLE_LAT (NSEC_PER_SEC * 4) /* hopefully we resume in 4secs */
61
62#define SUSPEND_SECS 15
63int alarmcount;
64int alarm_clock_id;
65struct timespec start_time;
66
67
68char *clockstring(int clockid)
69{
70 switch (clockid) {
71 case CLOCK_REALTIME:
72 return "CLOCK_REALTIME";
73 case CLOCK_MONOTONIC:
74 return "CLOCK_MONOTONIC";
75 case CLOCK_PROCESS_CPUTIME_ID:
76 return "CLOCK_PROCESS_CPUTIME_ID";
77 case CLOCK_THREAD_CPUTIME_ID:
78 return "CLOCK_THREAD_CPUTIME_ID";
79 case CLOCK_MONOTONIC_RAW:
80 return "CLOCK_MONOTONIC_RAW";
81 case CLOCK_REALTIME_COARSE:
82 return "CLOCK_REALTIME_COARSE";
83 case CLOCK_MONOTONIC_COARSE:
84 return "CLOCK_MONOTONIC_COARSE";
85 case CLOCK_BOOTTIME:
86 return "CLOCK_BOOTTIME";
87 case CLOCK_REALTIME_ALARM:
88 return "CLOCK_REALTIME_ALARM";
89 case CLOCK_BOOTTIME_ALARM:
90 return "CLOCK_BOOTTIME_ALARM";
91 case CLOCK_TAI:
92 return "CLOCK_TAI";
93 };
94 return "UNKNOWN_CLOCKID";
95}
96
97
98long long timespec_sub(struct timespec a, struct timespec b)
99{
100 long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
101
102 ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
103 return ret;
104}
105
106int final_ret = 0;
107
108void sigalarm(int signo)
109{
110 long long delta_ns;
111 struct timespec ts;
112
113 clock_gettime(alarm_clock_id, &ts);
114 alarmcount++;
115
116 delta_ns = timespec_sub(start_time, ts);
117 delta_ns -= NSEC_PER_SEC * SUSPEND_SECS * alarmcount;
118
119 printf("ALARM(%i): %ld:%ld latency: %lld ns ", alarmcount, ts.tv_sec,
120 ts.tv_nsec, delta_ns);
121
122 if (delta_ns > UNREASONABLE_LAT) {
123 printf("[FAIL]\n");
124 final_ret = -1;
125 } else
126 printf("[OK]\n");
127
128}
129
130int main(void)
131{
132 timer_t tm1;
133 struct itimerspec its1, its2;
134 struct sigevent se;
135 struct sigaction act;
136 int signum = SIGRTMAX;
137
138 /* Set up signal handler: */
139 sigfillset(&act.sa_mask);
140 act.sa_flags = 0;
141 act.sa_handler = sigalarm;
142 sigaction(signum, &act, NULL);
143
144 /* Set up timer: */
145 memset(&se, 0, sizeof(se));
146 se.sigev_notify = SIGEV_SIGNAL;
147 se.sigev_signo = signum;
148 se.sigev_value.sival_int = 0;
149
150 for (alarm_clock_id = CLOCK_REALTIME_ALARM;
151 alarm_clock_id <= CLOCK_BOOTTIME_ALARM;
152 alarm_clock_id++) {
153
154 alarmcount = 0;
155 timer_create(alarm_clock_id, &se, &tm1);
156
157 clock_gettime(alarm_clock_id, &start_time);
158 printf("Start time (%s): %ld:%ld\n", clockstring(alarm_clock_id),
159 start_time.tv_sec, start_time.tv_nsec);
160 printf("Setting alarm for every %i seconds\n", SUSPEND_SECS);
161 its1.it_value = start_time;
162 its1.it_value.tv_sec += SUSPEND_SECS;
163 its1.it_interval.tv_sec = SUSPEND_SECS;
164 its1.it_interval.tv_nsec = 0;
165
166 timer_settime(tm1, TIMER_ABSTIME, &its1, &its2);
167
168 while (alarmcount < 5)
169 sleep(1); /* First 5 alarms, do nothing */
170
171 printf("Starting suspend loops\n");
172 while (alarmcount < 10) {
173 int ret;
174
175 sleep(1);
176 ret = system("echo mem > /sys/power/state");
177 if (ret)
178 break;
179 }
180 timer_delete(tm1);
181 }
182 if (final_ret)
183 return ksft_exit_fail();
184 return ksft_exit_pass();
185}
diff --git a/tools/testing/selftests/timers/change_skew.c b/tools/testing/selftests/timers/change_skew.c
new file mode 100644
index 000000000000..cb1968977c04
--- /dev/null
+++ b/tools/testing/selftests/timers/change_skew.c
@@ -0,0 +1,107 @@
1/* ADJ_FREQ Skew change test
2 * by: john stultz (johnstul@us.ibm.com)
3 * (C) Copyright IBM 2012
4 * Licensed under the GPLv2
5 *
6 * NOTE: This is a meta-test which cranks the ADJ_FREQ knob and
7 * then uses other tests to detect problems. Thus this test requires
8 * that the raw_skew, inconsistency-check and nanosleep tests be
9 * present in the same directory it is run from.
10 *
11 * To build:
12 * $ gcc change_skew.c -o change_skew -lrt
13 *
14 * This program is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <sys/time.h>
29#include <sys/timex.h>
30#include <time.h>
31#ifdef KTEST
32#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43
44#define NSEC_PER_SEC 1000000000LL
45
46
47int change_skew_test(int ppm)
48{
49 struct timex tx;
50 int ret;
51
52 tx.modes = ADJ_FREQUENCY;
53 tx.freq = ppm << 16;
54
55 ret = adjtimex(&tx);
56 if (ret < 0) {
57 printf("Error adjusting freq\n");
58 return ret;
59 }
60
61 ret = system("./raw_skew");
62 ret |= system("./inconsistency-check");
63 ret |= system("./nanosleep");
64
65 return ret;
66}
67
68
69int main(int argv, char **argc)
70{
71 struct timex tx;
72 int i, ret;
73
74 int ppm[5] = {0, 250, 500, -250, -500};
75
76 /* Kill ntpd */
77 ret = system("killall -9 ntpd");
78
79 /* Make sure there's no offset adjustment going on */
80 tx.modes = ADJ_OFFSET;
81 tx.offset = 0;
82 ret = adjtimex(&tx);
83
84 if (ret < 0) {
85 printf("Maybe you're not running as root?\n");
86 return -1;
87 }
88
89 for (i = 0; i < 5; i++) {
90 printf("Using %i ppm adjustment\n", ppm[i]);
91 ret = change_skew_test(ppm[i]);
92 if (ret)
93 break;
94 }
95
96 /* Set things back */
97 tx.modes = ADJ_FREQUENCY;
98 tx.offset = 0;
99 adjtimex(&tx);
100
101 if (ret) {
102 printf("[FAIL]");
103 return ksft_exit_fail();
104 }
105 printf("[OK]");
106 return ksft_exit_pass();
107}
diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c
new file mode 100644
index 000000000000..627ec7425f78
--- /dev/null
+++ b/tools/testing/selftests/timers/clocksource-switch.c
@@ -0,0 +1,179 @@
1/* Clocksource change test
2 * by: john stultz (johnstul@us.ibm.com)
3 * (C) Copyright IBM 2012
4 * Licensed under the GPLv2
5 *
6 * NOTE: This is a meta-test which quickly changes the clocksourc and
7 * then uses other tests to detect problems. Thus this test requires
8 * that the inconsistency-check and nanosleep tests be present in the
9 * same directory it is run from.
10 *
11 * To build:
12 * $ gcc clocksource-switch.c -o clocksource-switch -lrt
13 *
14 * This program is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 */
24
25
26#include <stdio.h>
27#include <unistd.h>
28#include <stdlib.h>
29#include <sys/time.h>
30#include <sys/timex.h>
31#include <time.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <fcntl.h>
35#include <string.h>
36#include <sys/wait.h>
37#ifdef KTEST
38#include "../kselftest.h"
39#else
40static inline int ksft_exit_pass(void)
41{
42 exit(0);
43}
44static inline int ksft_exit_fail(void)
45{
46 exit(1);
47}
48#endif
49
50
51int get_clocksources(char list[][30])
52{
53 int fd, i;
54 size_t size;
55 char buf[512];
56 char *head, *tmp;
57
58 fd = open("/sys/devices/system/clocksource/clocksource0/available_clocksource", O_RDONLY);
59
60 size = read(fd, buf, 512);
61
62 close(fd);
63
64 for (i = 0; i < 30; i++)
65 list[i][0] = '\0';
66
67 head = buf;
68 i = 0;
69 while (head - buf < size) {
70 /* Find the next space */
71 for (tmp = head; *tmp != ' '; tmp++) {
72 if (*tmp == '\n')
73 break;
74 if (*tmp == '\0')
75 break;
76 }
77 *tmp = '\0';
78 strcpy(list[i], head);
79 head = tmp + 1;
80 i++;
81 }
82
83 return i-1;
84}
85
86int get_cur_clocksource(char *buf, size_t size)
87{
88 int fd;
89
90 fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_RDONLY);
91
92 size = read(fd, buf, size);
93
94 return 0;
95}
96
97int change_clocksource(char *clocksource)
98{
99 int fd;
100 size_t size;
101
102 fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY);
103
104 if (fd < 0)
105 return -1;
106
107 size = write(fd, clocksource, strlen(clocksource));
108
109 if (size < 0)
110 return -1;
111
112 close(fd);
113 return 0;
114}
115
116
117int run_tests(int secs)
118{
119 int ret;
120 char buf[255];
121
122 sprintf(buf, "./inconsistency-check -t %i", secs);
123 ret = system(buf);
124 if (ret)
125 return ret;
126 ret = system("./nanosleep");
127 return ret;
128}
129
130
131char clocksource_list[10][30];
132
133int main(int argv, char **argc)
134{
135 char orig_clk[512];
136 int count, i, status;
137 pid_t pid;
138
139 get_cur_clocksource(orig_clk, 512);
140
141 count = get_clocksources(clocksource_list);
142
143 if (change_clocksource(clocksource_list[0])) {
144 printf("Error: You probably need to run this as root\n");
145 return -1;
146 }
147
148 /* Check everything is sane before we start switching asyncrhonously */
149 for (i = 0; i < count; i++) {
150 printf("Validating clocksource %s\n", clocksource_list[i]);
151 if (change_clocksource(clocksource_list[i])) {
152 status = -1;
153 goto out;
154 }
155 if (run_tests(5)) {
156 status = -1;
157 goto out;
158 }
159 }
160
161
162 printf("Running Asyncrhonous Switching Tests...\n");
163 pid = fork();
164 if (!pid)
165 return run_tests(60);
166
167 while (pid != waitpid(pid, &status, WNOHANG))
168 for (i = 0; i < count; i++)
169 if (change_clocksource(clocksource_list[i])) {
170 status = -1;
171 goto out;
172 }
173out:
174 change_clocksource(orig_clk);
175
176 if (status)
177 return ksft_exit_fail();
178 return ksft_exit_pass();
179}
diff --git a/tools/testing/selftests/timers/inconsistency-check.c b/tools/testing/selftests/timers/inconsistency-check.c
new file mode 100644
index 000000000000..caf1bc9257c4
--- /dev/null
+++ b/tools/testing/selftests/timers/inconsistency-check.c
@@ -0,0 +1,204 @@
1/* Time inconsistency check test
2 * by: john stultz (johnstul@us.ibm.com)
3 * (C) Copyright IBM 2003, 2004, 2005, 2012
4 * (C) Copyright Linaro Limited 2015
5 * Licensed under the GPLv2
6 *
7 * To build:
8 * $ gcc inconsistency-check.c -o inconsistency-check -lrt
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21
22
23#include <stdio.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <time.h>
27#include <sys/time.h>
28#include <sys/timex.h>
29#include <string.h>
30#include <signal.h>
31#ifdef KTEST
32#include "../kselftest.h"
33#else
34static inline int ksft_exit_pass(void)
35{
36 exit(0);
37}
38static inline int ksft_exit_fail(void)
39{
40 exit(1);
41}
42#endif
43
44#define CALLS_PER_LOOP 64
45#define NSEC_PER_SEC 1000000000ULL
46
47#define CLOCK_REALTIME 0
48#define CLOCK_MONOTONIC 1
49#define CLOCK_PROCESS_CPUTIME_ID 2
50#define CLOCK_THREAD_CPUTIME_ID 3
51#define CLOCK_MONOTONIC_RAW 4
52#define CLOCK_REALTIME_COARSE 5
53#define CLOCK_MONOTONIC_COARSE 6
54#define CLOCK_BOOTTIME 7
55#define CLOCK_REALTIME_ALARM 8
56#define CLOCK_BOOTTIME_ALARM 9
57#define CLOCK_HWSPECIFIC 10
58#define CLOCK_TAI 11
59#define NR_CLOCKIDS 12
60
61char *clockstring(int clockid)
62{
63 switch (clockid) {
64 case CLOCK_REALTIME:
65 return "CLOCK_REALTIME";
66 case CLOCK_MONOTONIC:
67 return "CLOCK_MONOTONIC";
68 case CLOCK_PROCESS_CPUTIME_ID:
69 return "CLOCK_PROCESS_CPUTIME_ID";
70 case CLOCK_THREAD_CPUTIME_ID:
71 return "CLOCK_THREAD_CPUTIME_ID";
72 case CLOCK_MONOTONIC_RAW:
73 return "CLOCK_MONOTONIC_RAW";
74 case CLOCK_REALTIME_COARSE:
75 return "CLOCK_REALTIME_COARSE";
76 case CLOCK_MONOTONIC_COARSE:
77 return "CLOCK_MONOTONIC_COARSE";
78 case CLOCK_BOOTTIME:
79 return "CLOCK_BOOTTIME";
80 case CLOCK_REALTIME_ALARM:
81 return "CLOCK_REALTIME_ALARM";
82 case CLOCK_BOOTTIME_ALARM:
83 return "CLOCK_BOOTTIME_ALARM";
84 case CLOCK_TAI:
85 return "CLOCK_TAI";
86 };
87 return "UNKNOWN_CLOCKID";
88}
89
90/* returns 1 if a <= b, 0 otherwise */
91static inline int in_order(struct timespec a, struct timespec b)
92{
93 /* use unsigned to avoid false positives on 2038 rollover */
94 if ((unsigned long)a.tv_sec < (unsigned long)b.tv_sec)
95 return 1;
96 if ((unsigned long)a.tv_sec > (unsigned long)b.tv_sec)
97 return 0;
98 if (a.tv_nsec > b.tv_nsec)
99 return 0;
100 return 1;
101}
102
103
104
105int consistency_test(int clock_type, unsigned long seconds)
106{
107 struct timespec list[CALLS_PER_LOOP];
108 int i, inconsistent;
109 long now, then;
110 time_t t;
111 char *start_str;
112
113 clock_gettime(clock_type, &list[0]);
114 now = then = list[0].tv_sec;
115
116 /* timestamp start of test */
117 t = time(0);
118 start_str = ctime(&t);
119
120 while (seconds == -1 || now - then < seconds) {
121 inconsistent = 0;
122
123 /* Fill list */
124 for (i = 0; i < CALLS_PER_LOOP; i++)
125 clock_gettime(clock_type, &list[i]);
126
127 /* Check for inconsistencies */
128 for (i = 0; i < CALLS_PER_LOOP - 1; i++)
129 if (!in_order(list[i], list[i+1]))
130 inconsistent = i;
131
132 /* display inconsistency */
133 if (inconsistent) {
134 unsigned long long delta;
135
136 printf("\%s\n", start_str);
137 for (i = 0; i < CALLS_PER_LOOP; i++) {
138 if (i == inconsistent)
139 printf("--------------------\n");
140 printf("%lu:%lu\n", list[i].tv_sec,
141 list[i].tv_nsec);
142 if (i == inconsistent + 1)
143 printf("--------------------\n");
144 }
145 delta = list[inconsistent].tv_sec * NSEC_PER_SEC;
146 delta += list[inconsistent].tv_nsec;
147 delta -= list[inconsistent+1].tv_sec * NSEC_PER_SEC;
148 delta -= list[inconsistent+1].tv_nsec;
149 printf("Delta: %llu ns\n", delta);
150 fflush(0);
151 /* timestamp inconsistency*/
152 t = time(0);
153 printf("%s\n", ctime(&t));
154 printf("[FAILED]\n");
155 return -1;
156 }
157 now = list[0].tv_sec;
158 }
159 printf("[OK]\n");
160 return 0;
161}
162
163
164int main(int argc, char *argv[])
165{
166 int clockid, opt;
167 int userclock = CLOCK_REALTIME;
168 int maxclocks = NR_CLOCKIDS;
169 int runtime = 10;
170 struct timespec ts;
171
172 /* Process arguments */
173 while ((opt = getopt(argc, argv, "t:c:")) != -1) {
174 switch (opt) {
175 case 't':
176 runtime = atoi(optarg);
177 break;
178 case 'c':
179 userclock = atoi(optarg);
180 maxclocks = userclock + 1;
181 break;
182 default:
183 printf("Usage: %s [-t <secs>] [-c <clockid>]\n", argv[0]);
184 printf(" -t: Number of seconds to run\n");
185 printf(" -c: clockid to use (default, all clockids)\n");
186 exit(-1);
187 }
188 }
189
190 setbuf(stdout, NULL);
191
192 for (clockid = userclock; clockid < maxclocks; clockid++) {
193
194 if (clockid == CLOCK_HWSPECIFIC)
195 continue;
196
197 if (!clock_gettime(clockid, &ts)) {
198 printf("Consistent %-30s ", clockstring(clockid));
199 if (consistency_test(clockid, runtime))
200 return ksft_exit_fail();
201 }
202 }
203 return ksft_exit_pass();
204}
diff --git a/tools/testing/selftests/timers/leap-a-day.c b/tools/testing/selftests/timers/leap-a-day.c
new file mode 100644
index 000000000000..b8272e6c4b3b
--- /dev/null
+++ b/tools/testing/selftests/timers/leap-a-day.c
@@ -0,0 +1,319 @@
1/* Leap second stress test
2 * by: John Stultz (john.stultz@linaro.org)
3 * (C) Copyright IBM 2012
4 * (C) Copyright 2013, 2015 Linaro Limited
5 * Licensed under the GPLv2
6 *
7 * This test signals the kernel to insert a leap second
8 * every day at midnight GMT. This allows for stessing the
9 * kernel's leap-second behavior, as well as how well applications
10 * handle the leap-second discontinuity.
11 *
12 * Usage: leap-a-day [-s] [-i <num>]
13 *
14 * Options:
15 * -s: Each iteration, set the date to 10 seconds before midnight GMT.
16 * This speeds up the number of leapsecond transitions tested,
17 * but because it calls settimeofday frequently, advancing the
18 * time by 24 hours every ~16 seconds, it may cause application
19 * disruption.
20 *
21 * -i: Number of iterations to run (default: infinite)
22 *
23 * Other notes: Disabling NTP prior to running this is advised, as the two
24 * may conflict in their commands to the kernel.
25 *
26 * To build:
27 * $ gcc leap-a-day.c -o leap-a-day -lrt
28 *
29 * This program is free software: you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation, either version 2 of the License, or
32 * (at your option) any later version.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 */
39
40
41
42#include <stdio.h>
43#include <stdlib.h>
44#include <time.h>
45#include <sys/time.h>
46#include <sys/timex.h>
47#include <string.h>
48#include <signal.h>
49#include <unistd.h>
50#ifdef KTEST
51#include "../kselftest.h"
52#else
53static inline int ksft_exit_pass(void)
54{
55 exit(0);
56}
57static inline int ksft_exit_fail(void)
58{
59 exit(1);
60}
61#endif
62
63#define NSEC_PER_SEC 1000000000ULL
64#define CLOCK_TAI 11
65
66/* returns 1 if a <= b, 0 otherwise */
67static inline int in_order(struct timespec a, struct timespec b)
68{
69 if (a.tv_sec < b.tv_sec)
70 return 1;
71 if (a.tv_sec > b.tv_sec)
72 return 0;
73 if (a.tv_nsec > b.tv_nsec)
74 return 0;
75 return 1;
76}
77
78struct timespec timespec_add(struct timespec ts, unsigned long long ns)
79{
80 ts.tv_nsec += ns;
81 while (ts.tv_nsec >= NSEC_PER_SEC) {
82 ts.tv_nsec -= NSEC_PER_SEC;
83 ts.tv_sec++;
84 }
85 return ts;
86}
87
88char *time_state_str(int state)
89{
90 switch (state) {
91 case TIME_OK: return "TIME_OK";
92 case TIME_INS: return "TIME_INS";
93 case TIME_DEL: return "TIME_DEL";
94 case TIME_OOP: return "TIME_OOP";
95 case TIME_WAIT: return "TIME_WAIT";
96 case TIME_BAD: return "TIME_BAD";
97 }
98 return "ERROR";
99}
100
101/* clear NTP time_status & time_state */
102int clear_time_state(void)
103{
104 struct timex tx;
105 int ret;
106
107 /*
108 * We have to call adjtime twice here, as kernels
109 * prior to 6b1859dba01c7 (included in 3.5 and
110 * -stable), had an issue with the state machine
111 * and wouldn't clear the STA_INS/DEL flag directly.
112 */
113 tx.modes = ADJ_STATUS;
114 tx.status = STA_PLL;
115 ret = adjtimex(&tx);
116
117 /* Clear maxerror, as it can cause UNSYNC to be set */
118 tx.modes = ADJ_MAXERROR;
119 tx.maxerror = 0;
120 ret = adjtimex(&tx);
121
122 /* Clear the status */
123 tx.modes = ADJ_STATUS;
124 tx.status = 0;
125 ret = adjtimex(&tx);
126
127 return ret;
128}
129
130/* Make sure we cleanup on ctrl-c */
131void handler(int unused)
132{
133 clear_time_state();
134 exit(0);
135}
136
137/* Test for known hrtimer failure */
138void test_hrtimer_failure(void)
139{
140 struct timespec now, target;
141
142 clock_gettime(CLOCK_REALTIME, &now);
143 target = timespec_add(now, NSEC_PER_SEC/2);
144 clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &target, NULL);
145 clock_gettime(CLOCK_REALTIME, &now);
146
147 if (!in_order(target, now))
148 printf("ERROR: hrtimer early expiration failure observed.\n");
149}
150
151int main(int argc, char **argv)
152{
153 int settime = 0;
154 int tai_time = 0;
155 int insert = 1;
156 int iterations = -1;
157 int opt;
158
159 /* Process arguments */
160 while ((opt = getopt(argc, argv, "sti:")) != -1) {
161 switch (opt) {
162 case 's':
163 printf("Setting time to speed up testing\n");
164 settime = 1;
165 break;
166 case 'i':
167 iterations = atoi(optarg);
168 break;
169 case 't':
170 tai_time = 1;
171 break;
172 default:
173 printf("Usage: %s [-s] [-i <iterations>]\n", argv[0]);
174 printf(" -s: Set time to right before leap second each iteration\n");
175 printf(" -i: Number of iterations\n");
176 printf(" -t: Print TAI time\n");
177 exit(-1);
178 }
179 }
180
181 /* Make sure TAI support is present if -t was used */
182 if (tai_time) {
183 struct timespec ts;
184
185 if (clock_gettime(CLOCK_TAI, &ts)) {
186 printf("System doesn't support CLOCK_TAI\n");
187 ksft_exit_fail();
188 }
189 }
190
191 signal(SIGINT, handler);
192 signal(SIGKILL, handler);
193
194 if (iterations < 0)
195 printf("This runs continuously. Press ctrl-c to stop\n");
196 else
197 printf("Running for %i iterations. Press ctrl-c to stop\n", iterations);
198
199 printf("\n");
200 while (1) {
201 int ret;
202 struct timespec ts;
203 struct timex tx;
204 time_t now, next_leap;
205
206 /* Get the current time */
207 clock_gettime(CLOCK_REALTIME, &ts);
208
209 /* Calculate the next possible leap second 23:59:60 GMT */
210 next_leap = ts.tv_sec;
211 next_leap += 86400 - (next_leap % 86400);
212
213 if (settime) {
214 struct timeval tv;
215
216 tv.tv_sec = next_leap - 10;
217 tv.tv_usec = 0;
218 settimeofday(&tv, NULL);
219 printf("Setting time to %s", ctime(&tv.tv_sec));
220 }
221
222 /* Reset NTP time state */
223 clear_time_state();
224
225 /* Set the leap second insert flag */
226 tx.modes = ADJ_STATUS;
227 if (insert)
228 tx.status = STA_INS;
229 else
230 tx.status = STA_DEL;
231 ret = adjtimex(&tx);
232 if (ret < 0) {
233 printf("Error: Problem setting STA_INS/STA_DEL!: %s\n",
234 time_state_str(ret));
235 return ksft_exit_fail();
236 }
237
238 /* Validate STA_INS was set */
239 tx.modes = 0;
240 ret = adjtimex(&tx);
241 if (tx.status != STA_INS && tx.status != STA_DEL) {
242 printf("Error: STA_INS/STA_DEL not set!: %s\n",
243 time_state_str(ret));
244 return ksft_exit_fail();
245 }
246
247 if (tai_time) {
248 printf("Using TAI time,"
249 " no inconsistencies should be seen!\n");
250 }
251
252 printf("Scheduling leap second for %s", ctime(&next_leap));
253
254 /* Wake up 3 seconds before leap */
255 ts.tv_sec = next_leap - 3;
256 ts.tv_nsec = 0;
257
258 while (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL))
259 printf("Something woke us up, returning to sleep\n");
260
261 /* Validate STA_INS is still set */
262 tx.modes = 0;
263 ret = adjtimex(&tx);
264 if (tx.status != STA_INS && tx.status != STA_DEL) {
265 printf("Something cleared STA_INS/STA_DEL, setting it again.\n");
266 tx.modes = ADJ_STATUS;
267 if (insert)
268 tx.status = STA_INS;
269 else
270 tx.status = STA_DEL;
271 ret = adjtimex(&tx);
272 }
273
274 /* Check adjtimex output every half second */
275 now = tx.time.tv_sec;
276 while (now < next_leap + 2) {
277 char buf[26];
278 struct timespec tai;
279
280 tx.modes = 0;
281 ret = adjtimex(&tx);
282
283 if (tai_time) {
284 clock_gettime(CLOCK_TAI, &tai);
285 printf("%ld sec, %9ld ns\t%s\n",
286 tai.tv_sec,
287 tai.tv_nsec,
288 time_state_str(ret));
289 } else {
290 ctime_r(&tx.time.tv_sec, buf);
291 buf[strlen(buf)-1] = 0; /*remove trailing\n */
292
293 printf("%s + %6ld us (%i)\t%s\n",
294 buf,
295 tx.time.tv_usec,
296 tx.tai,
297 time_state_str(ret));
298 }
299 now = tx.time.tv_sec;
300 /* Sleep for another half second */
301 ts.tv_sec = 0;
302 ts.tv_nsec = NSEC_PER_SEC / 2;
303 clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
304 }
305 /* Switch to using other mode */
306 insert = !insert;
307
308 /* Note if kernel has known hrtimer failure */
309 test_hrtimer_failure();
310
311 printf("Leap complete\n\n");
312
313 if ((iterations != -1) && !(--iterations))
314 break;
315 }
316
317 clear_time_state();
318 return ksft_exit_pass();
319}
diff --git a/tools/testing/selftests/timers/leapcrash.c b/tools/testing/selftests/timers/leapcrash.c
new file mode 100644
index 000000000000..a1071bdbdeb7
--- /dev/null
+++ b/tools/testing/selftests/timers/leapcrash.c
@@ -0,0 +1,120 @@
1/* Demo leapsecond deadlock
2 * by: John Stultz (john.stultz@linaro.org)
3 * (C) Copyright IBM 2012
4 * (C) Copyright 2013, 2015 Linaro Limited
5 * Licensed under the GPL
6 *
7 * This test demonstrates leapsecond deadlock that is possibe
8 * on kernels from 2.6.26 to 3.3.
9 *
10 * WARNING: THIS WILL LIKELY HARDHANG SYSTEMS AND MAY LOSE DATA
11 * RUN AT YOUR OWN RISK!
12 * To build:
13 * $ gcc leapcrash.c -o leapcrash -lrt
14 */
15
16
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <time.h>
21#include <sys/time.h>
22#include <sys/timex.h>
23#include <string.h>
24#include <signal.h>
25#ifdef KTEST
26#include "../kselftest.h"
27#else
28static inline int ksft_exit_pass(void)
29{
30 exit(0);
31}
32static inline int ksft_exit_fail(void)
33{
34 exit(1);
35}
36#endif
37
38
39
40/* clear NTP time_status & time_state */
41int clear_time_state(void)
42{
43 struct timex tx;
44 int ret;
45
46 /*
47 * We have to call adjtime twice here, as kernels
48 * prior to 6b1859dba01c7 (included in 3.5 and
49 * -stable), had an issue with the state machine
50 * and wouldn't clear the STA_INS/DEL flag directly.
51 */
52 tx.modes = ADJ_STATUS;
53 tx.status = STA_PLL;
54 ret = adjtimex(&tx);
55
56 tx.modes = ADJ_STATUS;
57 tx.status = 0;
58 ret = adjtimex(&tx);
59
60 return ret;
61}
62
63/* Make sure we cleanup on ctrl-c */
64void handler(int unused)
65{
66 clear_time_state();
67 exit(0);
68}
69
70
71int main(void)
72{
73 struct timex tx;
74 struct timespec ts;
75 time_t next_leap;
76 int count = 0;
77
78 setbuf(stdout, NULL);
79
80 signal(SIGINT, handler);
81 signal(SIGKILL, handler);
82 printf("This runs for a few minutes. Press ctrl-c to stop\n");
83
84 clear_time_state();
85
86
87 /* Get the current time */
88 clock_gettime(CLOCK_REALTIME, &ts);
89
90 /* Calculate the next possible leap second 23:59:60 GMT */
91 next_leap = ts.tv_sec;
92 next_leap += 86400 - (next_leap % 86400);
93
94 for (count = 0; count < 20; count++) {
95 struct timeval tv;
96
97
98 /* set the time to 2 seconds before the leap */
99 tv.tv_sec = next_leap - 2;
100 tv.tv_usec = 0;
101 if (settimeofday(&tv, NULL)) {
102 printf("Error: You're likely not running with proper (ie: root) permissions\n");
103 return ksft_exit_fail();
104 }
105 tx.modes = 0;
106 adjtimex(&tx);
107
108 /* hammer on adjtime w/ STA_INS */
109 while (tx.time.tv_sec < next_leap + 1) {
110 /* Set the leap second insert flag */
111 tx.modes = ADJ_STATUS;
112 tx.status = STA_INS;
113 adjtimex(&tx);
114 }
115 clear_time_state();
116 printf(".");
117 }
118 printf("[OK]\n");
119 return ksft_exit_pass();
120}
diff --git a/tools/testing/selftests/timers/mqueue-lat.c b/tools/testing/selftests/timers/mqueue-lat.c
new file mode 100644
index 000000000000..a2a3924d0b41
--- /dev/null
+++ b/tools/testing/selftests/timers/mqueue-lat.c
@@ -0,0 +1,124 @@
1/* Measure mqueue timeout latency
2 * by: john stultz (john.stultz@linaro.org)
3 * (C) Copyright Linaro 2013
4 *
5 * Inspired with permission from example test by:
6 * Romain Francoise <romain@orebokech.com>
7 * Licensed under the GPLv2
8 *
9 * To build:
10 * $ gcc mqueue-lat.c -o mqueue-lat -lrt
11 *
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <time.h>
26#include <sys/time.h>
27#include <sys/timex.h>
28#include <string.h>
29#include <signal.h>
30#include <errno.h>
31#include <mqueue.h>
32#ifdef KTEST
33#include "../kselftest.h"
34#else
35static inline int ksft_exit_pass(void)
36{
37 exit(0);
38}
39static inline int ksft_exit_fail(void)
40{
41 exit(1);
42}
43#endif
44
45#define NSEC_PER_SEC 1000000000ULL
46
47#define TARGET_TIMEOUT 100000000 /* 100ms in nanoseconds */
48#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
49
50
51long long timespec_sub(struct timespec a, struct timespec b)
52{
53 long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
54
55 ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
56 return ret;
57}
58
59struct timespec timespec_add(struct timespec ts, unsigned long long ns)
60{
61 ts.tv_nsec += ns;
62 while (ts.tv_nsec >= NSEC_PER_SEC) {
63 ts.tv_nsec -= NSEC_PER_SEC;
64 ts.tv_sec++;
65 }
66 return ts;
67}
68
69int mqueue_lat_test(void)
70{
71
72 mqd_t q;
73 struct mq_attr attr;
74 struct timespec start, end, now, target;
75 int i, count, ret;
76
77 q = mq_open("/foo", O_CREAT | O_RDONLY, 0666, NULL);
78 if (q < 0) {
79 perror("mq_open");
80 return -1;
81 }
82 mq_getattr(q, &attr);
83
84
85 count = 100;
86 clock_gettime(CLOCK_MONOTONIC, &start);
87
88 for (i = 0; i < count; i++) {
89 char buf[attr.mq_msgsize];
90
91 clock_gettime(CLOCK_REALTIME, &now);
92 target = now;
93 target = timespec_add(now, TARGET_TIMEOUT); /* 100ms */
94
95 ret = mq_timedreceive(q, buf, sizeof(buf), NULL, &target);
96 if (ret < 0 && errno != ETIMEDOUT) {
97 perror("mq_timedreceive");
98 return -1;
99 }
100 }
101 clock_gettime(CLOCK_MONOTONIC, &end);
102
103 mq_close(q);
104
105 if ((timespec_sub(start, end)/count) > TARGET_TIMEOUT + UNRESONABLE_LATENCY)
106 return -1;
107
108 return 0;
109}
110
111int main(int argc, char **argv)
112{
113 int ret;
114
115 printf("Mqueue latency : ");
116
117 ret = mqueue_lat_test();
118 if (ret < 0) {
119 printf("[FAILED]\n");
120 return ksft_exit_fail();
121 }
122 printf("[OK]\n");
123 return ksft_exit_pass();
124}
diff --git a/tools/testing/selftests/timers/nanosleep.c b/tools/testing/selftests/timers/nanosleep.c
new file mode 100644
index 000000000000..8a3c29de7d49
--- /dev/null
+++ b/tools/testing/selftests/timers/nanosleep.c
@@ -0,0 +1,174 @@
1/* Make sure timers don't return early
2 * by: john stultz (johnstul@us.ibm.com)
3 * John Stultz (john.stultz@linaro.org)
4 * (C) Copyright IBM 2012
5 * (C) Copyright Linaro 2013 2015
6 * Licensed under the GPLv2
7 *
8 * To build:
9 * $ gcc nanosleep.c -o nanosleep -lrt
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <time.h>
25#include <sys/time.h>
26#include <sys/timex.h>
27#include <string.h>
28#include <signal.h>
29#ifdef KTEST
30#include "../kselftest.h"
31#else
32static inline int ksft_exit_pass(void)
33{
34 exit(0);
35}
36static inline int ksft_exit_fail(void)
37{
38 exit(1);
39}
40#endif
41
42#define NSEC_PER_SEC 1000000000ULL
43
44#define CLOCK_REALTIME 0
45#define CLOCK_MONOTONIC 1
46#define CLOCK_PROCESS_CPUTIME_ID 2
47#define CLOCK_THREAD_CPUTIME_ID 3
48#define CLOCK_MONOTONIC_RAW 4
49#define CLOCK_REALTIME_COARSE 5
50#define CLOCK_MONOTONIC_COARSE 6
51#define CLOCK_BOOTTIME 7
52#define CLOCK_REALTIME_ALARM 8
53#define CLOCK_BOOTTIME_ALARM 9
54#define CLOCK_HWSPECIFIC 10
55#define CLOCK_TAI 11
56#define NR_CLOCKIDS 12
57
58#define UNSUPPORTED 0xf00f
59
60char *clockstring(int clockid)
61{
62 switch (clockid) {
63 case CLOCK_REALTIME:
64 return "CLOCK_REALTIME";
65 case CLOCK_MONOTONIC:
66 return "CLOCK_MONOTONIC";
67 case CLOCK_PROCESS_CPUTIME_ID:
68 return "CLOCK_PROCESS_CPUTIME_ID";
69 case CLOCK_THREAD_CPUTIME_ID:
70 return "CLOCK_THREAD_CPUTIME_ID";
71 case CLOCK_MONOTONIC_RAW:
72 return "CLOCK_MONOTONIC_RAW";
73 case CLOCK_REALTIME_COARSE:
74 return "CLOCK_REALTIME_COARSE";
75 case CLOCK_MONOTONIC_COARSE:
76 return "CLOCK_MONOTONIC_COARSE";
77 case CLOCK_BOOTTIME:
78 return "CLOCK_BOOTTIME";
79 case CLOCK_REALTIME_ALARM:
80 return "CLOCK_REALTIME_ALARM";
81 case CLOCK_BOOTTIME_ALARM:
82 return "CLOCK_BOOTTIME_ALARM";
83 case CLOCK_TAI:
84 return "CLOCK_TAI";
85 };
86 return "UNKNOWN_CLOCKID";
87}
88
89/* returns 1 if a <= b, 0 otherwise */
90static inline int in_order(struct timespec a, struct timespec b)
91{
92 if (a.tv_sec < b.tv_sec)
93 return 1;
94 if (a.tv_sec > b.tv_sec)
95 return 0;
96 if (a.tv_nsec > b.tv_nsec)
97 return 0;
98 return 1;
99}
100
101struct timespec timespec_add(struct timespec ts, unsigned long long ns)
102{
103 ts.tv_nsec += ns;
104 while (ts.tv_nsec >= NSEC_PER_SEC) {
105 ts.tv_nsec -= NSEC_PER_SEC;
106 ts.tv_sec++;
107 }
108 return ts;
109}
110
111int nanosleep_test(int clockid, long long ns)
112{
113 struct timespec now, target, rel;
114
115 /* First check abs time */
116 if (clock_gettime(clockid, &now))
117 return UNSUPPORTED;
118 target = timespec_add(now, ns);
119
120 if (clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL))
121 return UNSUPPORTED;
122 clock_gettime(clockid, &now);
123
124 if (!in_order(target, now))
125 return -1;
126
127 /* Second check reltime */
128 clock_gettime(clockid, &now);
129 rel.tv_sec = 0;
130 rel.tv_nsec = 0;
131 rel = timespec_add(rel, ns);
132 target = timespec_add(now, ns);
133 clock_nanosleep(clockid, 0, &rel, NULL);
134 clock_gettime(clockid, &now);
135
136 if (!in_order(target, now))
137 return -1;
138 return 0;
139}
140
141int main(int argc, char **argv)
142{
143 long long length;
144 int clockid, ret;
145
146 for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
147
148 /* Skip cputime clockids since nanosleep won't increment cputime */
149 if (clockid == CLOCK_PROCESS_CPUTIME_ID ||
150 clockid == CLOCK_THREAD_CPUTIME_ID ||
151 clockid == CLOCK_HWSPECIFIC)
152 continue;
153
154 printf("Nanosleep %-31s ", clockstring(clockid));
155
156 length = 10;
157 while (length <= (NSEC_PER_SEC * 10)) {
158 ret = nanosleep_test(clockid, length);
159 if (ret == UNSUPPORTED) {
160 printf("[UNSUPPORTED]\n");
161 goto next;
162 }
163 if (ret < 0) {
164 printf("[FAILED]\n");
165 return ksft_exit_fail();
166 }
167 length *= 100;
168 }
169 printf("[OK]\n");
170next:
171 ret = 0;
172 }
173 return ksft_exit_pass();
174}
diff --git a/tools/testing/selftests/timers/nsleep-lat.c b/tools/testing/selftests/timers/nsleep-lat.c
new file mode 100644
index 000000000000..2d7898fda0f1
--- /dev/null
+++ b/tools/testing/selftests/timers/nsleep-lat.c
@@ -0,0 +1,190 @@
1/* Measure nanosleep timer latency
2 * by: john stultz (john.stultz@linaro.org)
3 * (C) Copyright Linaro 2013
4 * Licensed under the GPLv2
5 *
6 * To build:
7 * $ gcc nsleep-lat.c -o nsleep-lat -lrt
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <time.h>
23#include <sys/time.h>
24#include <sys/timex.h>
25#include <string.h>
26#include <signal.h>
27#ifdef KTEST
28#include "../kselftest.h"
29#else
30static inline int ksft_exit_pass(void)
31{
32 exit(0);
33}
34static inline int ksft_exit_fail(void)
35{
36 exit(1);
37}
38#endif
39
40#define NSEC_PER_SEC 1000000000ULL
41
42#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
43
44
45#define CLOCK_REALTIME 0
46#define CLOCK_MONOTONIC 1
47#define CLOCK_PROCESS_CPUTIME_ID 2
48#define CLOCK_THREAD_CPUTIME_ID 3
49#define CLOCK_MONOTONIC_RAW 4
50#define CLOCK_REALTIME_COARSE 5
51#define CLOCK_MONOTONIC_COARSE 6
52#define CLOCK_BOOTTIME 7
53#define CLOCK_REALTIME_ALARM 8
54#define CLOCK_BOOTTIME_ALARM 9
55#define CLOCK_HWSPECIFIC 10
56#define CLOCK_TAI 11
57#define NR_CLOCKIDS 12
58
59#define UNSUPPORTED 0xf00f
60
61char *clockstring(int clockid)
62{
63 switch (clockid) {
64 case CLOCK_REALTIME:
65 return "CLOCK_REALTIME";
66 case CLOCK_MONOTONIC:
67 return "CLOCK_MONOTONIC";
68 case CLOCK_PROCESS_CPUTIME_ID:
69 return "CLOCK_PROCESS_CPUTIME_ID";
70 case CLOCK_THREAD_CPUTIME_ID:
71 return "CLOCK_THREAD_CPUTIME_ID";
72 case CLOCK_MONOTONIC_RAW:
73 return "CLOCK_MONOTONIC_RAW";
74 case CLOCK_REALTIME_COARSE:
75 return "CLOCK_REALTIME_COARSE";
76 case CLOCK_MONOTONIC_COARSE:
77 return "CLOCK_MONOTONIC_COARSE";
78 case CLOCK_BOOTTIME:
79 return "CLOCK_BOOTTIME";
80 case CLOCK_REALTIME_ALARM:
81 return "CLOCK_REALTIME_ALARM";
82 case CLOCK_BOOTTIME_ALARM:
83 return "CLOCK_BOOTTIME_ALARM";
84 case CLOCK_TAI:
85 return "CLOCK_TAI";
86 };
87 return "UNKNOWN_CLOCKID";
88}
89
90struct timespec timespec_add(struct timespec ts, unsigned long long ns)
91{
92 ts.tv_nsec += ns;
93 while (ts.tv_nsec >= NSEC_PER_SEC) {
94 ts.tv_nsec -= NSEC_PER_SEC;
95 ts.tv_sec++;
96 }
97 return ts;
98}
99
100
101long long timespec_sub(struct timespec a, struct timespec b)
102{
103 long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
104
105 ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
106 return ret;
107}
108
109int nanosleep_lat_test(int clockid, long long ns)
110{
111 struct timespec start, end, target;
112 long long latency = 0;
113 int i, count;
114
115 target.tv_sec = ns/NSEC_PER_SEC;
116 target.tv_nsec = ns%NSEC_PER_SEC;
117
118 if (clock_gettime(clockid, &start))
119 return UNSUPPORTED;
120 if (clock_nanosleep(clockid, 0, &target, NULL))
121 return UNSUPPORTED;
122
123 count = 10;
124
125 /* First check relative latency */
126 clock_gettime(clockid, &start);
127 for (i = 0; i < count; i++)
128 clock_nanosleep(clockid, 0, &target, NULL);
129 clock_gettime(clockid, &end);
130
131 if (((timespec_sub(start, end)/count)-ns) > UNRESONABLE_LATENCY) {
132 printf("Large rel latency: %lld ns :", (timespec_sub(start, end)/count)-ns);
133 return -1;
134 }
135
136 /* Next check absolute latency */
137 for (i = 0; i < count; i++) {
138 clock_gettime(clockid, &start);
139 target = timespec_add(start, ns);
140 clock_nanosleep(clockid, TIMER_ABSTIME, &target, NULL);
141 clock_gettime(clockid, &end);
142 latency += timespec_sub(target, end);
143 }
144
145 if (latency/count > UNRESONABLE_LATENCY) {
146 printf("Large abs latency: %lld ns :", latency/count);
147 return -1;
148 }
149
150 return 0;
151}
152
153
154
155int main(int argc, char **argv)
156{
157 long long length;
158 int clockid, ret;
159
160 for (clockid = CLOCK_REALTIME; clockid < NR_CLOCKIDS; clockid++) {
161
162 /* Skip cputime clockids since nanosleep won't increment cputime */
163 if (clockid == CLOCK_PROCESS_CPUTIME_ID ||
164 clockid == CLOCK_THREAD_CPUTIME_ID ||
165 clockid == CLOCK_HWSPECIFIC)
166 continue;
167
168 printf("nsleep latency %-26s ", clockstring(clockid));
169
170 length = 10;
171 while (length <= (NSEC_PER_SEC * 10)) {
172 ret = nanosleep_lat_test(clockid, length);
173 if (ret)
174 break;
175 length *= 100;
176
177 }
178
179 if (ret == UNSUPPORTED) {
180 printf("[UNSUPPORTED]\n");
181 continue;
182 }
183 if (ret < 0) {
184 printf("[FAILED]\n");
185 return ksft_exit_fail();
186 }
187 printf("[OK]\n");
188 }
189 return ksft_exit_pass();
190}
diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c
index f87d970a485c..5a246a02dff3 100644
--- a/tools/testing/selftests/timers/posix_timers.c
+++ b/tools/testing/selftests/timers/posix_timers.c
@@ -35,10 +35,11 @@ static void user_loop(void)
35static void kernel_loop(void) 35static void kernel_loop(void)
36{ 36{
37 void *addr = sbrk(0); 37 void *addr = sbrk(0);
38 int err = 0;
38 39
39 while (!done) { 40 while (!done && !err) {
40 brk(addr + 4096); 41 err = brk(addr + 4096);
41 brk(addr); 42 err |= brk(addr);
42 } 43 }
43} 44}
44 45
@@ -190,8 +191,6 @@ static int check_timer_create(int which)
190 191
191int main(int argc, char **argv) 192int main(int argc, char **argv)
192{ 193{
193 int err;
194
195 printf("Testing posix timers. False negative may happen on CPU execution \n"); 194 printf("Testing posix timers. False negative may happen on CPU execution \n");
196 printf("based timers if other threads run on the CPU...\n"); 195 printf("based timers if other threads run on the CPU...\n");
197 196
diff --git a/tools/testing/selftests/timers/raw_skew.c b/tools/testing/selftests/timers/raw_skew.c
new file mode 100644
index 000000000000..30906bfd9c1b
--- /dev/null
+++ b/tools/testing/selftests/timers/raw_skew.c
@@ -0,0 +1,154 @@
1/* CLOCK_MONOTONIC vs CLOCK_MONOTONIC_RAW skew test
2 * by: john stultz (johnstul@us.ibm.com)
3 * John Stultz <john.stultz@linaro.org>
4 * (C) Copyright IBM 2012
5 * (C) Copyright Linaro Limited 2015
6 * Licensed under the GPLv2
7 *
8 * To build:
9 * $ gcc raw_skew.c -o raw_skew -lrt
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
22#include <stdio.h>
23#include <unistd.h>
24#include <stdlib.h>
25#include <sys/time.h>
26#include <sys/timex.h>
27#include <time.h>
28#ifdef KTEST
29#include "../kselftest.h"
30#else
31static inline int ksft_exit_pass(void)
32{
33 exit(0);
34}
35static inline int ksft_exit_fail(void)
36{
37 exit(1);
38}
39#endif
40
41
42#define CLOCK_MONOTONIC_RAW 4
43#define NSEC_PER_SEC 1000000000LL
44
45#define shift_right(x, s) ({ \
46 __typeof__(x) __x = (x); \
47 __typeof__(s) __s = (s); \
48 __x < 0 ? -(-__x >> __s) : __x >> __s; \
49})
50
51long long llabs(long long val)
52{
53 if (val < 0)
54 val = -val;
55 return val;
56}
57
58unsigned long long ts_to_nsec(struct timespec ts)
59{
60 return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
61}
62
63struct timespec nsec_to_ts(long long ns)
64{
65 struct timespec ts;
66
67 ts.tv_sec = ns/NSEC_PER_SEC;
68 ts.tv_nsec = ns%NSEC_PER_SEC;
69 return ts;
70}
71
72long long diff_timespec(struct timespec start, struct timespec end)
73{
74 long long start_ns, end_ns;
75
76 start_ns = ts_to_nsec(start);
77 end_ns = ts_to_nsec(end);
78 return end_ns - start_ns;
79}
80
81void get_monotonic_and_raw(struct timespec *mon, struct timespec *raw)
82{
83 struct timespec start, mid, end;
84 long long diff = 0, tmp;
85 int i;
86
87 for (i = 0; i < 3; i++) {
88 long long newdiff;
89
90 clock_gettime(CLOCK_MONOTONIC, &start);
91 clock_gettime(CLOCK_MONOTONIC_RAW, &mid);
92 clock_gettime(CLOCK_MONOTONIC, &end);
93
94 newdiff = diff_timespec(start, end);
95 if (diff == 0 || newdiff < diff) {
96 diff = newdiff;
97 *raw = mid;
98 tmp = (ts_to_nsec(start) + ts_to_nsec(end))/2;
99 *mon = nsec_to_ts(tmp);
100 }
101 }
102}
103
104int main(int argv, char **argc)
105{
106 struct timespec mon, raw, start, end;
107 long long delta1, delta2, interval, eppm, ppm;
108 struct timex tx1, tx2;
109
110 setbuf(stdout, NULL);
111
112 if (clock_gettime(CLOCK_MONOTONIC_RAW, &raw)) {
113 printf("ERR: NO CLOCK_MONOTONIC_RAW\n");
114 return -1;
115 }
116
117 tx1.modes = 0;
118 adjtimex(&tx1);
119 get_monotonic_and_raw(&mon, &raw);
120 start = mon;
121 delta1 = diff_timespec(mon, raw);
122
123 if (tx1.offset)
124 printf("WARNING: ADJ_OFFSET in progress, this will cause inaccurate results\n");
125
126 printf("Estimating clock drift: ");
127 sleep(120);
128
129 get_monotonic_and_raw(&mon, &raw);
130 end = mon;
131 tx2.modes = 0;
132 adjtimex(&tx2);
133 delta2 = diff_timespec(mon, raw);
134
135 interval = diff_timespec(start, end);
136
137 /* calculate measured ppm between MONOTONIC and MONOTONIC_RAW */
138 eppm = ((delta2-delta1)*NSEC_PER_SEC)/interval;
139 eppm = -eppm;
140 printf("%lld.%i(est)", eppm/1000, abs((int)(eppm%1000)));
141
142 /* Avg the two actual freq samples adjtimex gave us */
143 ppm = (tx1.freq + tx2.freq) * 1000 / 2;
144 ppm = (long long)tx1.freq * 1000;
145 ppm = shift_right(ppm, 16);
146 printf(" %lld.%i(act)", ppm/1000, abs((int)(ppm%1000)));
147
148 if (llabs(eppm - ppm) > 1000) {
149 printf(" [FAILED]\n");
150 return ksft_exit_fail();
151 }
152 printf(" [OK]\n");
153 return ksft_exit_pass();
154}
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
new file mode 100644
index 000000000000..d80ae852334d
--- /dev/null
+++ b/tools/testing/selftests/timers/rtctest.c
@@ -0,0 +1,271 @@
1/*
2 * Real Time Clock Driver Test/Example Program
3 *
4 * Compile with:
5 * gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
6 *
7 * Copyright (C) 1996, Paul Gortmaker.
8 *
9 * Released under the GNU General Public License, version 2,
10 * included herein by reference.
11 *
12 */
13
14#include <stdio.h>
15#include <linux/rtc.h>
16#include <sys/ioctl.h>
17#include <sys/time.h>
18#include <sys/types.h>
19#include <fcntl.h>
20#include <unistd.h>
21#include <stdlib.h>
22#include <errno.h>
23
24
25/*
26 * This expects the new RTC class driver framework, working with
27 * clocks that will often not be clones of what the PC-AT had.
28 * Use the command line to specify another RTC if you need one.
29 */
30static const char default_rtc[] = "/dev/rtc0";
31
32
33int main(int argc, char **argv)
34{
35 int i, fd, retval, irqcount = 0;
36 unsigned long tmp, data;
37 struct rtc_time rtc_tm;
38 const char *rtc = default_rtc;
39 struct timeval start, end, diff;
40
41 switch (argc) {
42 case 2:
43 rtc = argv[1];
44 /* FALLTHROUGH */
45 case 1:
46 break;
47 default:
48 fprintf(stderr, "usage: rtctest [rtcdev]\n");
49 return 1;
50 }
51
52 fd = open(rtc, O_RDONLY);
53
54 if (fd == -1) {
55 perror(rtc);
56 exit(errno);
57 }
58
59 fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");
60
61 /* Turn on update interrupts (one per second) */
62 retval = ioctl(fd, RTC_UIE_ON, 0);
63 if (retval == -1) {
64 if (errno == ENOTTY) {
65 fprintf(stderr,
66 "\n...Update IRQs not supported.\n");
67 goto test_READ;
68 }
69 perror("RTC_UIE_ON ioctl");
70 exit(errno);
71 }
72
73 fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:",
74 rtc);
75 fflush(stderr);
76 for (i=1; i<6; i++) {
77 /* This read will block */
78 retval = read(fd, &data, sizeof(unsigned long));
79 if (retval == -1) {
80 perror("read");
81 exit(errno);
82 }
83 fprintf(stderr, " %d",i);
84 fflush(stderr);
85 irqcount++;
86 }
87
88 fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
89 fflush(stderr);
90 for (i=1; i<6; i++) {
91 struct timeval tv = {5, 0}; /* 5 second timeout on select */
92 fd_set readfds;
93
94 FD_ZERO(&readfds);
95 FD_SET(fd, &readfds);
96 /* The select will wait until an RTC interrupt happens. */
97 retval = select(fd+1, &readfds, NULL, NULL, &tv);
98 if (retval == -1) {
99 perror("select");
100 exit(errno);
101 }
102 /* This read won't block unlike the select-less case above. */
103 retval = read(fd, &data, sizeof(unsigned long));
104 if (retval == -1) {
105 perror("read");
106 exit(errno);
107 }
108 fprintf(stderr, " %d",i);
109 fflush(stderr);
110 irqcount++;
111 }
112
113 /* Turn off update interrupts */
114 retval = ioctl(fd, RTC_UIE_OFF, 0);
115 if (retval == -1) {
116 perror("RTC_UIE_OFF ioctl");
117 exit(errno);
118 }
119
120test_READ:
121 /* Read the RTC time/date */
122 retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
123 if (retval == -1) {
124 perror("RTC_RD_TIME ioctl");
125 exit(errno);
126 }
127
128 fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
129 rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
130 rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
131
132 /* Set the alarm to 5 sec in the future, and check for rollover */
133 rtc_tm.tm_sec += 5;
134 if (rtc_tm.tm_sec >= 60) {
135 rtc_tm.tm_sec %= 60;
136 rtc_tm.tm_min++;
137 }
138 if (rtc_tm.tm_min == 60) {
139 rtc_tm.tm_min = 0;
140 rtc_tm.tm_hour++;
141 }
142 if (rtc_tm.tm_hour == 24)
143 rtc_tm.tm_hour = 0;
144
145 retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
146 if (retval == -1) {
147 if (errno == ENOTTY) {
148 fprintf(stderr,
149 "\n...Alarm IRQs not supported.\n");
150 goto test_PIE;
151 }
152 perror("RTC_ALM_SET ioctl");
153 exit(errno);
154 }
155
156 /* Read the current alarm settings */
157 retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
158 if (retval == -1) {
159 perror("RTC_ALM_READ ioctl");
160 exit(errno);
161 }
162
163 fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
164 rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
165
166 /* Enable alarm interrupts */
167 retval = ioctl(fd, RTC_AIE_ON, 0);
168 if (retval == -1) {
169 perror("RTC_AIE_ON ioctl");
170 exit(errno);
171 }
172
173 fprintf(stderr, "Waiting 5 seconds for alarm...");
174 fflush(stderr);
175 /* This blocks until the alarm ring causes an interrupt */
176 retval = read(fd, &data, sizeof(unsigned long));
177 if (retval == -1) {
178 perror("read");
179 exit(errno);
180 }
181 irqcount++;
182 fprintf(stderr, " okay. Alarm rang.\n");
183
184 /* Disable alarm interrupts */
185 retval = ioctl(fd, RTC_AIE_OFF, 0);
186 if (retval == -1) {
187 perror("RTC_AIE_OFF ioctl");
188 exit(errno);
189 }
190
191test_PIE:
192 /* Read periodic IRQ rate */
193 retval = ioctl(fd, RTC_IRQP_READ, &tmp);
194 if (retval == -1) {
195 /* not all RTCs support periodic IRQs */
196 if (errno == ENOTTY) {
197 fprintf(stderr, "\nNo periodic IRQ support\n");
198 goto done;
199 }
200 perror("RTC_IRQP_READ ioctl");
201 exit(errno);
202 }
203 fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp);
204
205 fprintf(stderr, "Counting 20 interrupts at:");
206 fflush(stderr);
207
208 /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
209 for (tmp=2; tmp<=64; tmp*=2) {
210
211 retval = ioctl(fd, RTC_IRQP_SET, tmp);
212 if (retval == -1) {
213 /* not all RTCs can change their periodic IRQ rate */
214 if (errno == ENOTTY) {
215 fprintf(stderr,
216 "\n...Periodic IRQ rate is fixed\n");
217 goto done;
218 }
219 perror("RTC_IRQP_SET ioctl");
220 exit(errno);
221 }
222
223 fprintf(stderr, "\n%ldHz:\t", tmp);
224 fflush(stderr);
225
226 /* Enable periodic interrupts */
227 retval = ioctl(fd, RTC_PIE_ON, 0);
228 if (retval == -1) {
229 perror("RTC_PIE_ON ioctl");
230 exit(errno);
231 }
232
233 for (i=1; i<21; i++) {
234 gettimeofday(&start, NULL);
235 /* This blocks */
236 retval = read(fd, &data, sizeof(unsigned long));
237 if (retval == -1) {
238 perror("read");
239 exit(errno);
240 }
241 gettimeofday(&end, NULL);
242 timersub(&end, &start, &diff);
243 if (diff.tv_sec > 0 ||
244 diff.tv_usec > ((1000000L / tmp) * 1.10)) {
245 fprintf(stderr, "\nPIE delta error: %ld.%06ld should be close to 0.%06ld\n",
246 diff.tv_sec, diff.tv_usec,
247 (1000000L / tmp));
248 fflush(stdout);
249 exit(-1);
250 }
251
252 fprintf(stderr, " %d",i);
253 fflush(stderr);
254 irqcount++;
255 }
256
257 /* Disable periodic interrupts */
258 retval = ioctl(fd, RTC_PIE_OFF, 0);
259 if (retval == -1) {
260 perror("RTC_PIE_OFF ioctl");
261 exit(errno);
262 }
263 }
264
265done:
266 fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
267
268 close(fd);
269
270 return 0;
271}
diff --git a/tools/testing/selftests/timers/set-2038.c b/tools/testing/selftests/timers/set-2038.c
new file mode 100644
index 000000000000..c8a7e14446b1
--- /dev/null
+++ b/tools/testing/selftests/timers/set-2038.c
@@ -0,0 +1,144 @@
1/* Time bounds setting test
2 * by: john stultz (johnstul@us.ibm.com)
3 * (C) Copyright IBM 2012
4 * Licensed under the GPLv2
5 *
6 * NOTE: This is a meta-test which sets the time to edge cases then
7 * uses other tests to detect problems. Thus this test requires that
8 * the inconsistency-check and nanosleep tests be present in the same
9 * directory it is run from.
10 *
11 * To build:
12 * $ gcc set-2038.c -o set-2038 -lrt
13 *
14 * This program is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <time.h>
29#include <sys/time.h>
30#ifdef KTEST
31#include "../kselftest.h"
32#else
33static inline int ksft_exit_pass(void)
34{
35 exit(0);
36}
37static inline int ksft_exit_fail(void)
38{
39 exit(1);
40}
41#endif
42
43#define NSEC_PER_SEC 1000000000LL
44
45#define KTIME_MAX ((long long)~((unsigned long long)1 << 63))
46#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)
47
48#define YEAR_1901 (-0x7fffffffL)
49#define YEAR_1970 1
50#define YEAR_2038 0x7fffffffL /*overflows 32bit time_t */
51#define YEAR_2262 KTIME_SEC_MAX /*overflows 64bit ktime_t */
52#define YEAR_MAX ((long long)((1ULL<<63)-1)) /*overflows 64bit time_t */
53
54int is32bits(void)
55{
56 return (sizeof(long) == 4);
57}
58
59int settime(long long time)
60{
61 struct timeval now;
62 int ret;
63
64 now.tv_sec = (time_t)time;
65 now.tv_usec = 0;
66
67 ret = settimeofday(&now, NULL);
68
69 printf("Setting time to 0x%lx: %d\n", (long)time, ret);
70 return ret;
71}
72
73int do_tests(void)
74{
75 int ret;
76
77 ret = system("date");
78 ret = system("./inconsistency-check -c 0 -t 20");
79 ret |= system("./nanosleep");
80 ret |= system("./nsleep-lat");
81 return ret;
82
83}
84
85int main(int argc, char *argv[])
86{
87 int ret = 0;
88 int opt, dangerous = 0;
89 time_t start;
90
91 /* Process arguments */
92 while ((opt = getopt(argc, argv, "d")) != -1) {
93 switch (opt) {
94 case 'd':
95 dangerous = 1;
96 }
97 }
98
99 start = time(0);
100
101 /* First test that crazy values don't work */
102 if (!settime(YEAR_1901)) {
103 ret = -1;
104 goto out;
105 }
106 if (!settime(YEAR_MAX)) {
107 ret = -1;
108 goto out;
109 }
110 if (!is32bits() && !settime(YEAR_2262)) {
111 ret = -1;
112 goto out;
113 }
114
115 /* Now test behavior near edges */
116 settime(YEAR_1970);
117 ret = do_tests();
118 if (ret)
119 goto out;
120
121 settime(YEAR_2038 - 600);
122 ret = do_tests();
123 if (ret)
124 goto out;
125
126 /* The rest of the tests can blowup on 32bit systems */
127 if (is32bits() && !dangerous)
128 goto out;
129 /* Test rollover behavior 32bit edge */
130 settime(YEAR_2038 - 10);
131 ret = do_tests();
132 if (ret)
133 goto out;
134
135 settime(YEAR_2262 - 600);
136 ret = do_tests();
137
138out:
139 /* restore clock */
140 settime(start);
141 if (ret)
142 return ksft_exit_fail();
143 return ksft_exit_pass();
144}
diff --git a/tools/testing/selftests/timers/set-tai.c b/tools/testing/selftests/timers/set-tai.c
new file mode 100644
index 000000000000..dc88dbc8831f
--- /dev/null
+++ b/tools/testing/selftests/timers/set-tai.c
@@ -0,0 +1,79 @@
1/* Set tai offset
2 * by: John Stultz <john.stultz@linaro.org>
3 * (C) Copyright Linaro 2013
4 * Licensed under the GPLv2
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <time.h>
21#include <sys/time.h>
22#include <sys/timex.h>
23#include <string.h>
24#include <signal.h>
25#include <unistd.h>
26#ifdef KTEST
27#include "../kselftest.h"
28#else
29static inline int ksft_exit_pass(void)
30{
31 exit(0);
32}
33static inline int ksft_exit_fail(void)
34{
35 exit(1);
36}
37#endif
38
39int set_tai(int offset)
40{
41 struct timex tx;
42
43 memset(&tx, 0, sizeof(tx));
44
45 tx.modes = ADJ_TAI;
46 tx.constant = offset;
47
48 return adjtimex(&tx);
49}
50
51int get_tai(void)
52{
53 struct timex tx;
54
55 memset(&tx, 0, sizeof(tx));
56
57 adjtimex(&tx);
58 return tx.tai;
59}
60
61int main(int argc, char **argv)
62{
63 int i, ret;
64
65 ret = get_tai();
66 printf("tai offset started at %i\n", ret);
67
68 printf("Checking tai offsets can be properly set: ");
69 for (i = 1; i <= 60; i++) {
70 ret = set_tai(i);
71 ret = get_tai();
72 if (ret != i) {
73 printf("[FAILED] expected: %i got %i\n", i, ret);
74 return ksft_exit_fail();
75 }
76 }
77 printf("[OK]\n");
78 return ksft_exit_pass();
79}
diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c
new file mode 100644
index 000000000000..4fc98c5b0899
--- /dev/null
+++ b/tools/testing/selftests/timers/set-timer-lat.c
@@ -0,0 +1,216 @@
1/* set_timer latency test
2 * John Stultz (john.stultz@linaro.org)
3 * (C) Copyright Linaro 2014
4 * Licensed under the GPLv2
5 *
6 * This test makes sure the set_timer api is correct
7 *
8 * To build:
9 * $ gcc set-timer-lat.c -o set-timer-lat -lrt
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
22
23#include <stdio.h>
24#include <unistd.h>
25#include <time.h>
26#include <string.h>
27#include <signal.h>
28#include <stdlib.h>
29#include <pthread.h>
30#ifdef KTEST
31#include "../kselftest.h"
32#else
33static inline int ksft_exit_pass(void)
34{
35 exit(0);
36}
37static inline int ksft_exit_fail(void)
38{
39 exit(1);
40}
41#endif
42
43#define CLOCK_REALTIME 0
44#define CLOCK_MONOTONIC 1
45#define CLOCK_PROCESS_CPUTIME_ID 2
46#define CLOCK_THREAD_CPUTIME_ID 3
47#define CLOCK_MONOTONIC_RAW 4
48#define CLOCK_REALTIME_COARSE 5
49#define CLOCK_MONOTONIC_COARSE 6
50#define CLOCK_BOOTTIME 7
51#define CLOCK_REALTIME_ALARM 8
52#define CLOCK_BOOTTIME_ALARM 9
53#define CLOCK_HWSPECIFIC 10
54#define CLOCK_TAI 11
55#define NR_CLOCKIDS 12
56
57
58#define NSEC_PER_SEC 1000000000ULL
59#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
60
61#define TIMER_SECS 1
62int alarmcount;
63int clock_id;
64struct timespec start_time;
65long long max_latency_ns;
66
67char *clockstring(int clockid)
68{
69 switch (clockid) {
70 case CLOCK_REALTIME:
71 return "CLOCK_REALTIME";
72 case CLOCK_MONOTONIC:
73 return "CLOCK_MONOTONIC";
74 case CLOCK_PROCESS_CPUTIME_ID:
75 return "CLOCK_PROCESS_CPUTIME_ID";
76 case CLOCK_THREAD_CPUTIME_ID:
77 return "CLOCK_THREAD_CPUTIME_ID";
78 case CLOCK_MONOTONIC_RAW:
79 return "CLOCK_MONOTONIC_RAW";
80 case CLOCK_REALTIME_COARSE:
81 return "CLOCK_REALTIME_COARSE";
82 case CLOCK_MONOTONIC_COARSE:
83 return "CLOCK_MONOTONIC_COARSE";
84 case CLOCK_BOOTTIME:
85 return "CLOCK_BOOTTIME";
86 case CLOCK_REALTIME_ALARM:
87 return "CLOCK_REALTIME_ALARM";
88 case CLOCK_BOOTTIME_ALARM:
89 return "CLOCK_BOOTTIME_ALARM";
90 case CLOCK_TAI:
91 return "CLOCK_TAI";
92 };
93 return "UNKNOWN_CLOCKID";
94}
95
96
97long long timespec_sub(struct timespec a, struct timespec b)
98{
99 long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
100
101 ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
102 return ret;
103}
104
105
106void sigalarm(int signo)
107{
108 long long delta_ns;
109 struct timespec ts;
110
111 clock_gettime(clock_id, &ts);
112 alarmcount++;
113
114 delta_ns = timespec_sub(start_time, ts);
115 delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount;
116
117 if (delta_ns < 0)
118 printf("%s timer fired early: FAIL\n", clockstring(clock_id));
119
120 if (delta_ns > max_latency_ns)
121 max_latency_ns = delta_ns;
122}
123
124int do_timer(int clock_id, int flags)
125{
126 struct sigevent se;
127 timer_t tm1;
128 struct itimerspec its1, its2;
129 int err;
130
131 /* Set up timer: */
132 memset(&se, 0, sizeof(se));
133 se.sigev_notify = SIGEV_SIGNAL;
134 se.sigev_signo = SIGRTMAX;
135 se.sigev_value.sival_int = 0;
136
137 max_latency_ns = 0;
138 alarmcount = 0;
139
140 err = timer_create(clock_id, &se, &tm1);
141 if (err) {
142 if ((clock_id == CLOCK_REALTIME_ALARM) ||
143 (clock_id == CLOCK_BOOTTIME_ALARM)) {
144 printf("%-22s %s missing CAP_WAKE_ALARM? : [UNSUPPORTED]\n",
145 clockstring(clock_id),
146 flags ? "ABSTIME":"RELTIME");
147 return 0;
148 }
149 printf("%s - timer_create() failed\n", clockstring(clock_id));
150 return -1;
151 }
152
153 clock_gettime(clock_id, &start_time);
154 if (flags) {
155 its1.it_value = start_time;
156 its1.it_value.tv_sec += TIMER_SECS;
157 } else {
158 its1.it_value.tv_sec = TIMER_SECS;
159 its1.it_value.tv_nsec = 0;
160 }
161 its1.it_interval.tv_sec = TIMER_SECS;
162 its1.it_interval.tv_nsec = 0;
163
164 err = timer_settime(tm1, flags, &its1, &its2);
165 if (err) {
166 printf("%s - timer_settime() failed\n", clockstring(clock_id));
167 return -1;
168 }
169
170 while (alarmcount < 5)
171 sleep(1);
172
173 printf("%-22s %s max latency: %10lld ns : ",
174 clockstring(clock_id),
175 flags ? "ABSTIME":"RELTIME",
176 max_latency_ns);
177
178 timer_delete(tm1);
179 if (max_latency_ns < UNRESONABLE_LATENCY) {
180 printf("[OK]\n");
181 return 0;
182 }
183 printf("[FAILED]\n");
184 return -1;
185}
186
187int main(void)
188{
189 struct sigaction act;
190 int signum = SIGRTMAX;
191 int ret = 0;
192
193 /* Set up signal handler: */
194 sigfillset(&act.sa_mask);
195 act.sa_flags = 0;
196 act.sa_handler = sigalarm;
197 sigaction(signum, &act, NULL);
198
199 printf("Setting timers for every %i seconds\n", TIMER_SECS);
200 for (clock_id = 0; clock_id < NR_CLOCKIDS; clock_id++) {
201
202 if ((clock_id == CLOCK_PROCESS_CPUTIME_ID) ||
203 (clock_id == CLOCK_THREAD_CPUTIME_ID) ||
204 (clock_id == CLOCK_MONOTONIC_RAW) ||
205 (clock_id == CLOCK_REALTIME_COARSE) ||
206 (clock_id == CLOCK_MONOTONIC_COARSE) ||
207 (clock_id == CLOCK_HWSPECIFIC))
208 continue;
209
210 ret |= do_timer(clock_id, TIMER_ABSTIME);
211 ret |= do_timer(clock_id, 0);
212 }
213 if (ret)
214 return ksft_exit_fail();
215 return ksft_exit_pass();
216}
diff --git a/tools/testing/selftests/timers/skew_consistency.c b/tools/testing/selftests/timers/skew_consistency.c
new file mode 100644
index 000000000000..5562f84ee07c
--- /dev/null
+++ b/tools/testing/selftests/timers/skew_consistency.c
@@ -0,0 +1,89 @@
1/* ADJ_FREQ Skew consistency test
2 * by: john stultz (johnstul@us.ibm.com)
3 * (C) Copyright IBM 2012
4 * Licensed under the GPLv2
5 *
6 * NOTE: This is a meta-test which cranks the ADJ_FREQ knob back
7 * and forth and watches for consistency problems. Thus this test requires
8 * that the inconsistency-check tests be present in the same directory it
9 * is run from.
10 *
11 * To build:
12 * $ gcc skew_consistency.c -o skew_consistency -lrt
13 *
14 * This program is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 */
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <unistd.h>
29#include <sys/time.h>
30#include <sys/timex.h>
31#include <time.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <fcntl.h>
35#include <stdlib.h>
36#include <string.h>
37#include <sys/wait.h>
38#ifdef KTEST
39#include "../kselftest.h"
40#else
41static inline int ksft_exit_pass(void)
42{
43 exit(0);
44}
45static inline int ksft_exit_fail(void)
46{
47 exit(1);
48}
49#endif
50
51#define NSEC_PER_SEC 1000000000LL
52
53int main(int argv, char **argc)
54{
55 struct timex tx;
56 int ret, ppm;
57 pid_t pid;
58
59
60 printf("Running Asyncrhonous Frequency Changing Tests...\n");
61
62 pid = fork();
63 if (!pid)
64 return system("./inconsistency-check -c 1 -t 600");
65
66 ppm = 500;
67 ret = 0;
68
69 while (pid != waitpid(pid, &ret, WNOHANG)) {
70 ppm = -ppm;
71 tx.modes = ADJ_FREQUENCY;
72 tx.freq = ppm << 16;
73 adjtimex(&tx);
74 usleep(500000);
75 }
76
77 /* Set things back */
78 tx.modes = ADJ_FREQUENCY;
79 tx.offset = 0;
80 adjtimex(&tx);
81
82
83 if (ret) {
84 printf("[FAILED]\n");
85 return ksft_exit_fail();
86 }
87 printf("[OK]\n");
88 return ksft_exit_pass();
89}
diff --git a/tools/testing/selftests/timers/threadtest.c b/tools/testing/selftests/timers/threadtest.c
new file mode 100644
index 000000000000..e632e116f05e
--- /dev/null
+++ b/tools/testing/selftests/timers/threadtest.c
@@ -0,0 +1,204 @@
1/* threadtest.c
2 * by: john stultz (johnstul@us.ibm.com)
3 * (C) Copyright IBM 2004, 2005, 2006, 2012
4 * Licensed under the GPLv2
5 *
6 * To build:
7 * $ gcc threadtest.c -o threadtest -lrt
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19#include <stdio.h>
20#include <unistd.h>
21#include <stdlib.h>
22#include <sys/time.h>
23#include <pthread.h>
24#ifdef KTEST
25#include "../kselftest.h"
26#else
27static inline int ksft_exit_pass(void)
28{
29 exit(0);
30}
31static inline int ksft_exit_fail(void)
32{
33 exit(1);
34}
35#endif
36
37
38/* serializes shared list access */
39pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
40/* serializes console output */
41pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
42
43
44#define MAX_THREADS 128
45#define LISTSIZE 128
46
47int done = 0;
48
49struct timespec global_list[LISTSIZE];
50int listcount = 0;
51
52
53void checklist(struct timespec *list, int size)
54{
55 int i, j;
56 struct timespec *a, *b;
57
58 /* scan the list */
59 for (i = 0; i < size-1; i++) {
60 a = &list[i];
61 b = &list[i+1];
62
63 /* look for any time inconsistencies */
64 if ((b->tv_sec <= a->tv_sec) &&
65 (b->tv_nsec < a->tv_nsec)) {
66
67 /* flag other threads */
68 done = 1;
69
70 /*serialize printing to avoid junky output*/
71 pthread_mutex_lock(&print_lock);
72
73 /* dump the list */
74 printf("\n");
75 for (j = 0; j < size; j++) {
76 if (j == i)
77 printf("---------------\n");
78 printf("%lu:%lu\n", list[j].tv_sec, list[j].tv_nsec);
79 if (j == i+1)
80 printf("---------------\n");
81 }
82 printf("[FAILED]\n");
83
84 pthread_mutex_unlock(&print_lock);
85 }
86 }
87}
88
89/* The shared thread shares a global list
90 * that each thread fills while holding the lock.
91 * This stresses clock syncronization across cpus.
92 */
93void *shared_thread(void *arg)
94{
95 while (!done) {
96 /* protect the list */
97 pthread_mutex_lock(&list_lock);
98
99 /* see if we're ready to check the list */
100 if (listcount >= LISTSIZE) {
101 checklist(global_list, LISTSIZE);
102 listcount = 0;
103 }
104 clock_gettime(CLOCK_MONOTONIC, &global_list[listcount++]);
105
106 pthread_mutex_unlock(&list_lock);
107 }
108 return NULL;
109}
110
111
112/* Each independent thread fills in its own
113 * list. This stresses clock_gettime() lock contention.
114 */
115void *independent_thread(void *arg)
116{
117 struct timespec my_list[LISTSIZE];
118 int count;
119
120 while (!done) {
121 /* fill the list */
122 for (count = 0; count < LISTSIZE; count++)
123 clock_gettime(CLOCK_MONOTONIC, &my_list[count]);
124 checklist(my_list, LISTSIZE);
125 }
126 return NULL;
127}
128
129#define DEFAULT_THREAD_COUNT 8
130#define DEFAULT_RUNTIME 30
131
132int main(int argc, char **argv)
133{
134 int thread_count, i;
135 time_t start, now, runtime;
136 char buf[255];
137 pthread_t pth[MAX_THREADS];
138 int opt;
139 void *tret;
140 int ret = 0;
141 void *(*thread)(void *) = shared_thread;
142
143 thread_count = DEFAULT_THREAD_COUNT;
144 runtime = DEFAULT_RUNTIME;
145
146 /* Process arguments */
147 while ((opt = getopt(argc, argv, "t:n:i")) != -1) {
148 switch (opt) {
149 case 't':
150 runtime = atoi(optarg);
151 break;
152 case 'n':
153 thread_count = atoi(optarg);
154 break;
155 case 'i':
156 thread = independent_thread;
157 printf("using independent threads\n");
158 break;
159 default:
160 printf("Usage: %s [-t <secs>] [-n <numthreads>] [-i]\n", argv[0]);
161 printf(" -t: time to run\n");
162 printf(" -n: number of threads\n");
163 printf(" -i: use independent threads\n");
164 return -1;
165 }
166 }
167
168 if (thread_count > MAX_THREADS)
169 thread_count = MAX_THREADS;
170
171
172 setbuf(stdout, NULL);
173
174 start = time(0);
175 strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&start));
176 printf("%s\n", buf);
177 printf("Testing consistency with %i threads for %ld seconds: ", thread_count, runtime);
178
179 /* spawn */
180 for (i = 0; i < thread_count; i++)
181 pthread_create(&pth[i], 0, thread, 0);
182
183 while (time(&now) < start + runtime) {
184 sleep(1);
185 if (done) {
186 ret = 1;
187 strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&now));
188 printf("%s\n", buf);
189 goto out;
190 }
191 }
192 printf("[OK]\n");
193 done = 1;
194
195out:
196 /* wait */
197 for (i = 0; i < thread_count; i++)
198 pthread_join(pth[i], &tret);
199
200 /* die */
201 if (ret)
202 ksft_exit_fail();
203 return ksft_exit_pass();
204}
diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c
new file mode 100644
index 000000000000..e86d937cc22c
--- /dev/null
+++ b/tools/testing/selftests/timers/valid-adjtimex.c
@@ -0,0 +1,202 @@
1/* valid adjtimex test
2 * by: John Stultz <john.stultz@linaro.org>
3 * (C) Copyright Linaro 2015
4 * Licensed under the GPLv2
5 *
6 * This test validates adjtimex interface with valid
7 * and invalid test data.
8 *
9 * Usage: valid-adjtimex
10 *
11 * To build:
12 * $ gcc valid-adjtimex.c -o valid-adjtimex -lrt
13 *
14 * This program is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 */
24
25
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <time.h>
30#include <sys/time.h>
31#include <sys/timex.h>
32#include <string.h>
33#include <signal.h>
34#include <unistd.h>
35#ifdef KTEST
36#include "../kselftest.h"
37#else
38static inline int ksft_exit_pass(void)
39{
40 exit(0);
41}
42static inline int ksft_exit_fail(void)
43{
44 exit(1);
45}
46#endif
47
48#define NSEC_PER_SEC 1000000000L
49
50/* clear NTP time_status & time_state */
51int clear_time_state(void)
52{
53 struct timex tx;
54 int ret;
55
56 tx.modes = ADJ_STATUS;
57 tx.status = 0;
58 ret = adjtimex(&tx);
59 return ret;
60}
61
62#define NUM_FREQ_VALID 32
63#define NUM_FREQ_OUTOFRANGE 4
64#define NUM_FREQ_INVALID 2
65
66long valid_freq[NUM_FREQ_VALID] = {
67 -499<<16,
68 -450<<16,
69 -400<<16,
70 -350<<16,
71 -300<<16,
72 -250<<16,
73 -200<<16,
74 -150<<16,
75 -100<<16,
76 -75<<16,
77 -50<<16,
78 -25<<16,
79 -10<<16,
80 -5<<16,
81 -1<<16,
82 -1000,
83 1<<16,
84 5<<16,
85 10<<16,
86 25<<16,
87 50<<16,
88 75<<16,
89 100<<16,
90 150<<16,
91 200<<16,
92 250<<16,
93 300<<16,
94 350<<16,
95 400<<16,
96 450<<16,
97 499<<16,
98};
99
100long outofrange_freq[NUM_FREQ_OUTOFRANGE] = {
101 -1000<<16,
102 -550<<16,
103 550<<16,
104 1000<<16,
105};
106
107#define LONG_MAX (~0UL>>1)
108#define LONG_MIN (-LONG_MAX - 1)
109
110long invalid_freq[NUM_FREQ_INVALID] = {
111 LONG_MAX,
112 LONG_MIN,
113};
114
115int validate_freq(void)
116{
117 struct timex tx;
118 int ret, pass = 0;
119 int i;
120
121 clear_time_state();
122
123 memset(&tx, 0, sizeof(struct timex));
124 /* Set the leap second insert flag */
125
126 printf("Testing ADJ_FREQ... ");
127 for (i = 0; i < NUM_FREQ_VALID; i++) {
128 tx.modes = ADJ_FREQUENCY;
129 tx.freq = valid_freq[i];
130
131 ret = adjtimex(&tx);
132 if (ret < 0) {
133 printf("[FAIL]\n");
134 printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
135 valid_freq[i], valid_freq[i]>>16);
136 pass = -1;
137 goto out;
138 }
139 tx.modes = 0;
140 ret = adjtimex(&tx);
141 if (tx.freq != valid_freq[i]) {
142 printf("Warning: freq value %ld not what we set it (%ld)!\n",
143 tx.freq, valid_freq[i]);
144 }
145 }
146 for (i = 0; i < NUM_FREQ_OUTOFRANGE; i++) {
147 tx.modes = ADJ_FREQUENCY;
148 tx.freq = outofrange_freq[i];
149
150 ret = adjtimex(&tx);
151 if (ret < 0) {
152 printf("[FAIL]\n");
153 printf("Error: adjtimex(ADJ_FREQ, %ld - %ld ppm\n",
154 outofrange_freq[i], outofrange_freq[i]>>16);
155 pass = -1;
156 goto out;
157 }
158 tx.modes = 0;
159 ret = adjtimex(&tx);
160 if (tx.freq == outofrange_freq[i]) {
161 printf("[FAIL]\n");
162 printf("ERROR: out of range value %ld actually set!\n",
163 tx.freq);
164 pass = -1;
165 goto out;
166 }
167 }
168
169
170 if (sizeof(long) == 8) { /* this case only applies to 64bit systems */
171 for (i = 0; i < NUM_FREQ_INVALID; i++) {
172 tx.modes = ADJ_FREQUENCY;
173 tx.freq = invalid_freq[i];
174 ret = adjtimex(&tx);
175 if (ret >= 0) {
176 printf("[FAIL]\n");
177 printf("Error: No failure on invalid ADJ_FREQUENCY %ld\n",
178 invalid_freq[i]);
179 pass = -1;
180 goto out;
181 }
182 }
183 }
184
185 printf("[OK]\n");
186out:
187 /* reset freq to zero */
188 tx.modes = ADJ_FREQUENCY;
189 tx.freq = 0;
190 ret = adjtimex(&tx);
191
192 return pass;
193}
194
195
196int main(int argc, char **argv)
197{
198 if (validate_freq())
199 return ksft_exit_fail();
200
201 return ksft_exit_pass();
202}
diff --git a/tools/testing/selftests/user/Makefile b/tools/testing/selftests/user/Makefile
index 12c9d15bab07..d401b63c5b1a 100644
--- a/tools/testing/selftests/user/Makefile
+++ b/tools/testing/selftests/user/Makefile
@@ -3,5 +3,6 @@
3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" 3# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
4all: 4all:
5 5
6run_tests: all 6TEST_PROGS := test_user_copy.sh
7 ./test_user_copy.sh 7
8include ../lib.mk
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index 077828c889f1..a5ce9534eb15 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -1,6 +1,5 @@
1# Makefile for vm selftests 1# Makefile for vm selftests
2 2
3CC = $(CROSS_COMPILE)gcc
4CFLAGS = -Wall 3CFLAGS = -Wall
5BINARIES = hugepage-mmap hugepage-shm map_hugetlb thuge-gen hugetlbfstest 4BINARIES = hugepage-mmap hugepage-shm map_hugetlb thuge-gen hugetlbfstest
6BINARIES += transhuge-stress 5BINARIES += transhuge-stress
@@ -9,8 +8,10 @@ all: $(BINARIES)
9%: %.c 8%: %.c
10 $(CC) $(CFLAGS) -o $@ $^ -lrt 9 $(CC) $(CFLAGS) -o $@ $^ -lrt
11 10
12run_tests: all 11TEST_PROGS := run_vmtests
13 @/bin/sh ./run_vmtests || (echo "vmtests: [FAIL]"; exit 1) 12TEST_FILES := $(BINARIES)
13
14include ../lib.mk
14 15
15clean: 16clean:
16 $(RM) $(BINARIES) 17 $(RM) $(BINARIES)
diff --git a/tools/testing/selftests/vm/hugetlbfstest.c b/tools/testing/selftests/vm/hugetlbfstest.c
index ea40ff8c2391..02e1072ec187 100644
--- a/tools/testing/selftests/vm/hugetlbfstest.c
+++ b/tools/testing/selftests/vm/hugetlbfstest.c
@@ -34,6 +34,7 @@ static void do_mmap(int fd, int extra_flags, int unmap)
34 int *p; 34 int *p;
35 int flags = MAP_PRIVATE | MAP_POPULATE | extra_flags; 35 int flags = MAP_PRIVATE | MAP_POPULATE | extra_flags;
36 u64 before, after; 36 u64 before, after;
37 int ret;
37 38
38 before = read_rss(); 39 before = read_rss();
39 p = mmap(NULL, length, PROT_READ | PROT_WRITE, flags, fd, 0); 40 p = mmap(NULL, length, PROT_READ | PROT_WRITE, flags, fd, 0);
@@ -44,7 +45,8 @@ static void do_mmap(int fd, int extra_flags, int unmap)
44 !"rss didn't grow as expected"); 45 !"rss didn't grow as expected");
45 if (!unmap) 46 if (!unmap)
46 return; 47 return;
47 munmap(p, length); 48 ret = munmap(p, length);
49 assert(!ret || !"munmap returned an unexpected error");
48 after = read_rss(); 50 after = read_rss();
49 assert(llabs(after - before) < 0x40000 || 51 assert(llabs(after - before) < 0x40000 ||
50 !"rss didn't shrink as expected"); 52 !"rss didn't shrink as expected");
diff --git a/tools/testing/selftests/vm/map_hugetlb.c b/tools/testing/selftests/vm/map_hugetlb.c
index ac56639dd4a9..addcd6fc1ecc 100644
--- a/tools/testing/selftests/vm/map_hugetlb.c
+++ b/tools/testing/selftests/vm/map_hugetlb.c
@@ -73,7 +73,11 @@ int main(void)
73 write_bytes(addr); 73 write_bytes(addr);
74 ret = read_bytes(addr); 74 ret = read_bytes(addr);
75 75
76 munmap(addr, LENGTH); 76 /* munmap() length of MAP_HUGETLB memory must be hugepage aligned */
77 if (munmap(addr, LENGTH)) {
78 perror("munmap");
79 exit(1);
80 }
77 81
78 return ret; 82 return ret;
79} 83}
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index c87b6812300d..c87b6812300d 100644..100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
diff --git a/tools/testing/selftests/x86/.gitignore b/tools/testing/selftests/x86/.gitignore
new file mode 100644
index 000000000000..15034fef9698
--- /dev/null
+++ b/tools/testing/selftests/x86/.gitignore
@@ -0,0 +1,2 @@
1*_32
2*_64
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
new file mode 100644
index 000000000000..ddf63569df5a
--- /dev/null
+++ b/tools/testing/selftests/x86/Makefile
@@ -0,0 +1,48 @@
1.PHONY: all all_32 all_64 check_build32 clean run_tests
2
3TARGETS_C_BOTHBITS := sigreturn single_step_syscall
4
5BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32)
6BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64)
7
8CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
9
10UNAME_P := $(shell uname -p)
11
12# Always build 32-bit tests
13all: all_32
14
15# If we're on a 64-bit host, build 64-bit tests as well
16ifeq ($(shell uname -p),x86_64)
17all: all_64
18endif
19
20all_32: check_build32 $(BINARIES_32)
21
22all_64: $(BINARIES_64)
23
24clean:
25 $(RM) $(BINARIES_32) $(BINARIES_64)
26
27run_tests:
28 ./run_x86_tests.sh
29
30$(TARGETS_C_BOTHBITS:%=%_32): %_32: %.c
31 $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
32
33$(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c
34 $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
35
36check_build32:
37 @if ! $(CC) -m32 -o /dev/null trivial_32bit_program.c; then \
38 echo "Warning: you seem to have a broken 32-bit build" 2>&1; \
39 echo "environment. If you are using a Debian-like"; \
40 echo " distribution, try:"; \
41 echo ""; \
42 echo " apt-get install gcc-multilib libc6-i386 libc6-dev-i386"; \
43 echo ""; \
44 echo "If you are using a Fedora-like distribution, try:"; \
45 echo ""; \
46 echo " yum install glibc-devel.*i686"; \
47 exit 1; \
48 fi
diff --git a/tools/testing/selftests/x86/run_x86_tests.sh b/tools/testing/selftests/x86/run_x86_tests.sh
new file mode 100644
index 000000000000..3fc19b376812
--- /dev/null
+++ b/tools/testing/selftests/x86/run_x86_tests.sh
@@ -0,0 +1,13 @@
1#!/bin/bash
2
3# This is deliberately minimal. IMO kselftests should provide a standard
4# script here.
5./sigreturn_32 || exit 1
6./single_step_syscall_32 || exit 1
7
8if [[ "$uname -p" -eq "x86_64" ]]; then
9 ./sigreturn_64 || exit 1
10 ./single_step_syscall_64 || exit 1
11fi
12
13exit 0
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
new file mode 100644
index 000000000000..b5aa1bab7416
--- /dev/null
+++ b/tools/testing/selftests/x86/sigreturn.c
@@ -0,0 +1,684 @@
1/*
2 * sigreturn.c - tests for x86 sigreturn(2) and exit-to-userspace
3 * Copyright (c) 2014-2015 Andrew Lutomirski
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * This is a series of tests that exercises the sigreturn(2) syscall and
15 * the IRET / SYSRET paths in the kernel.
16 *
17 * For now, this focuses on the effects of unusual CS and SS values,
18 * and it has a bunch of tests to make sure that ESP/RSP is restored
19 * properly.
20 *
21 * The basic idea behind these tests is to raise(SIGUSR1) to create a
22 * sigcontext frame, plug in the values to be tested, and then return,
23 * which implicitly invokes sigreturn(2) and programs the user context
24 * as desired.
25 *
26 * For tests for which we expect sigreturn and the subsequent return to
27 * user mode to succeed, we return to a short trampoline that generates
28 * SIGTRAP so that the meat of the tests can be ordinary C code in a
29 * SIGTRAP handler.
30 *
31 * The inner workings of each test is documented below.
32 *
33 * Do not run on outdated, unpatched kernels at risk of nasty crashes.
34 */
35
36#define _GNU_SOURCE
37
38#include <sys/time.h>
39#include <time.h>
40#include <stdlib.h>
41#include <sys/syscall.h>
42#include <unistd.h>
43#include <stdio.h>
44#include <string.h>
45#include <inttypes.h>
46#include <sys/mman.h>
47#include <sys/signal.h>
48#include <sys/ucontext.h>
49#include <asm/ldt.h>
50#include <err.h>
51#include <setjmp.h>
52#include <stddef.h>
53#include <stdbool.h>
54#include <sys/ptrace.h>
55#include <sys/user.h>
56
57/*
58 * In principle, this test can run on Linux emulation layers (e.g.
59 * Illumos "LX branded zones"). Solaris-based kernels reserve LDT
60 * entries 0-5 for their own internal purposes, so start our LDT
61 * allocations above that reservation. (The tests don't pass on LX
62 * branded zones, but at least this lets them run.)
63 */
64#define LDT_OFFSET 6
65
66/* An aligned stack accessible through some of our segments. */
67static unsigned char stack16[65536] __attribute__((aligned(4096)));
68
69/*
70 * An aligned int3 instruction used as a trampoline. Some of the tests
71 * want to fish out their ss values, so this trampoline copies ss to eax
72 * before the int3.
73 */
74asm (".pushsection .text\n\t"
75 ".type int3, @function\n\t"
76 ".align 4096\n\t"
77 "int3:\n\t"
78 "mov %ss,%eax\n\t"
79 "int3\n\t"
80 ".size int3, . - int3\n\t"
81 ".align 4096, 0xcc\n\t"
82 ".popsection");
83extern char int3[4096];
84
85/*
86 * At startup, we prepapre:
87 *
88 * - ldt_nonexistent_sel: An LDT entry that doesn't exist (all-zero
89 * descriptor or out of bounds).
90 * - code16_sel: A 16-bit LDT code segment pointing to int3.
91 * - data16_sel: A 16-bit LDT data segment pointing to stack16.
92 * - npcode32_sel: A 32-bit not-present LDT code segment pointing to int3.
93 * - npdata32_sel: A 32-bit not-present LDT data segment pointing to stack16.
94 * - gdt_data16_idx: A 16-bit GDT data segment pointing to stack16.
95 * - gdt_npdata32_idx: A 32-bit not-present GDT data segment pointing to
96 * stack16.
97 *
98 * For no particularly good reason, xyz_sel is a selector value with the
99 * RPL and LDT bits filled in, whereas xyz_idx is just an index into the
100 * descriptor table. These variables will be zero if their respective
101 * segments could not be allocated.
102 */
103static unsigned short ldt_nonexistent_sel;
104static unsigned short code16_sel, data16_sel, npcode32_sel, npdata32_sel;
105
106static unsigned short gdt_data16_idx, gdt_npdata32_idx;
107
108static unsigned short GDT3(int idx)
109{
110 return (idx << 3) | 3;
111}
112
113static unsigned short LDT3(int idx)
114{
115 return (idx << 3) | 7;
116}
117
118/* Our sigaltstack scratch space. */
119static char altstack_data[SIGSTKSZ];
120
121static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
122 int flags)
123{
124 struct sigaction sa;
125 memset(&sa, 0, sizeof(sa));
126 sa.sa_sigaction = handler;
127 sa.sa_flags = SA_SIGINFO | flags;
128 sigemptyset(&sa.sa_mask);
129 if (sigaction(sig, &sa, 0))
130 err(1, "sigaction");
131}
132
133static void clearhandler(int sig)
134{
135 struct sigaction sa;
136 memset(&sa, 0, sizeof(sa));
137 sa.sa_handler = SIG_DFL;
138 sigemptyset(&sa.sa_mask);
139 if (sigaction(sig, &sa, 0))
140 err(1, "sigaction");
141}
142
143static void add_ldt(const struct user_desc *desc, unsigned short *var,
144 const char *name)
145{
146 if (syscall(SYS_modify_ldt, 1, desc, sizeof(*desc)) == 0) {
147 *var = LDT3(desc->entry_number);
148 } else {
149 printf("[NOTE]\tFailed to create %s segment\n", name);
150 *var = 0;
151 }
152}
153
154static void setup_ldt(void)
155{
156 if ((unsigned long)stack16 > (1ULL << 32) - sizeof(stack16))
157 errx(1, "stack16 is too high\n");
158 if ((unsigned long)int3 > (1ULL << 32) - sizeof(int3))
159 errx(1, "int3 is too high\n");
160
161 ldt_nonexistent_sel = LDT3(LDT_OFFSET + 2);
162
163 const struct user_desc code16_desc = {
164 .entry_number = LDT_OFFSET + 0,
165 .base_addr = (unsigned long)int3,
166 .limit = 4095,
167 .seg_32bit = 0,
168 .contents = 2, /* Code, not conforming */
169 .read_exec_only = 0,
170 .limit_in_pages = 0,
171 .seg_not_present = 0,
172 .useable = 0
173 };
174 add_ldt(&code16_desc, &code16_sel, "code16");
175
176 const struct user_desc data16_desc = {
177 .entry_number = LDT_OFFSET + 1,
178 .base_addr = (unsigned long)stack16,
179 .limit = 0xffff,
180 .seg_32bit = 0,
181 .contents = 0, /* Data, grow-up */
182 .read_exec_only = 0,
183 .limit_in_pages = 0,
184 .seg_not_present = 0,
185 .useable = 0
186 };
187 add_ldt(&data16_desc, &data16_sel, "data16");
188
189 const struct user_desc npcode32_desc = {
190 .entry_number = LDT_OFFSET + 3,
191 .base_addr = (unsigned long)int3,
192 .limit = 4095,
193 .seg_32bit = 1,
194 .contents = 2, /* Code, not conforming */
195 .read_exec_only = 0,
196 .limit_in_pages = 0,
197 .seg_not_present = 1,
198 .useable = 0
199 };
200 add_ldt(&npcode32_desc, &npcode32_sel, "npcode32");
201
202 const struct user_desc npdata32_desc = {
203 .entry_number = LDT_OFFSET + 4,
204 .base_addr = (unsigned long)stack16,
205 .limit = 0xffff,
206 .seg_32bit = 1,
207 .contents = 0, /* Data, grow-up */
208 .read_exec_only = 0,
209 .limit_in_pages = 0,
210 .seg_not_present = 1,
211 .useable = 0
212 };
213 add_ldt(&npdata32_desc, &npdata32_sel, "npdata32");
214
215 struct user_desc gdt_data16_desc = {
216 .entry_number = -1,
217 .base_addr = (unsigned long)stack16,
218 .limit = 0xffff,
219 .seg_32bit = 0,
220 .contents = 0, /* Data, grow-up */
221 .read_exec_only = 0,
222 .limit_in_pages = 0,
223 .seg_not_present = 0,
224 .useable = 0
225 };
226
227 if (syscall(SYS_set_thread_area, &gdt_data16_desc) == 0) {
228 /*
229 * This probably indicates vulnerability to CVE-2014-8133.
230 * Merely getting here isn't definitive, though, and we'll
231 * diagnose the problem for real later on.
232 */
233 printf("[WARN]\tset_thread_area allocated data16 at index %d\n",
234 gdt_data16_desc.entry_number);
235 gdt_data16_idx = gdt_data16_desc.entry_number;
236 } else {
237 printf("[OK]\tset_thread_area refused 16-bit data\n");
238 }
239
240 struct user_desc gdt_npdata32_desc = {
241 .entry_number = -1,
242 .base_addr = (unsigned long)stack16,
243 .limit = 0xffff,
244 .seg_32bit = 1,
245 .contents = 0, /* Data, grow-up */
246 .read_exec_only = 0,
247 .limit_in_pages = 0,
248 .seg_not_present = 1,
249 .useable = 0
250 };
251
252 if (syscall(SYS_set_thread_area, &gdt_npdata32_desc) == 0) {
253 /*
254 * As a hardening measure, newer kernels don't allow this.
255 */
256 printf("[WARN]\tset_thread_area allocated npdata32 at index %d\n",
257 gdt_npdata32_desc.entry_number);
258 gdt_npdata32_idx = gdt_npdata32_desc.entry_number;
259 } else {
260 printf("[OK]\tset_thread_area refused 16-bit data\n");
261 }
262}
263
264/* State used by our signal handlers. */
265static gregset_t initial_regs, requested_regs, resulting_regs;
266
267/* Instructions for the SIGUSR1 handler. */
268static volatile unsigned short sig_cs, sig_ss;
269static volatile sig_atomic_t sig_trapped, sig_err, sig_trapno;
270
271/* Abstractions for some 32-bit vs 64-bit differences. */
272#ifdef __x86_64__
273# define REG_IP REG_RIP
274# define REG_SP REG_RSP
275# define REG_AX REG_RAX
276
277struct selectors {
278 unsigned short cs, gs, fs, ss;
279};
280
281static unsigned short *ssptr(ucontext_t *ctx)
282{
283 struct selectors *sels = (void *)&ctx->uc_mcontext.gregs[REG_CSGSFS];
284 return &sels->ss;
285}
286
287static unsigned short *csptr(ucontext_t *ctx)
288{
289 struct selectors *sels = (void *)&ctx->uc_mcontext.gregs[REG_CSGSFS];
290 return &sels->cs;
291}
292#else
293# define REG_IP REG_EIP
294# define REG_SP REG_ESP
295# define REG_AX REG_EAX
296
297static greg_t *ssptr(ucontext_t *ctx)
298{
299 return &ctx->uc_mcontext.gregs[REG_SS];
300}
301
302static greg_t *csptr(ucontext_t *ctx)
303{
304 return &ctx->uc_mcontext.gregs[REG_CS];
305}
306#endif
307
308/* Number of errors in the current test case. */
309static volatile sig_atomic_t nerrs;
310
311/*
312 * SIGUSR1 handler. Sets CS and SS as requested and points IP to the
313 * int3 trampoline. Sets SP to a large known value so that we can see
314 * whether the value round-trips back to user mode correctly.
315 */
316static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
317{
318 ucontext_t *ctx = (ucontext_t*)ctx_void;
319
320 memcpy(&initial_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
321
322 *csptr(ctx) = sig_cs;
323 *ssptr(ctx) = sig_ss;
324
325 ctx->uc_mcontext.gregs[REG_IP] =
326 sig_cs == code16_sel ? 0 : (unsigned long)&int3;
327 ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL;
328 ctx->uc_mcontext.gregs[REG_AX] = 0;
329
330 memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
331 requested_regs[REG_AX] = *ssptr(ctx); /* The asm code does this. */
332
333 return;
334}
335
336/*
337 * Called after a successful sigreturn. Restores our state so that
338 * the original raise(SIGUSR1) returns.
339 */
340static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
341{
342 ucontext_t *ctx = (ucontext_t*)ctx_void;
343
344 sig_err = ctx->uc_mcontext.gregs[REG_ERR];
345 sig_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO];
346
347 unsigned short ss;
348 asm ("mov %%ss,%0" : "=r" (ss));
349
350 greg_t asm_ss = ctx->uc_mcontext.gregs[REG_AX];
351 if (asm_ss != sig_ss && sig == SIGTRAP) {
352 /* Sanity check failure. */
353 printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n",
354 ss, *ssptr(ctx), (unsigned long long)asm_ss);
355 nerrs++;
356 }
357
358 memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
359 memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t));
360
361 sig_trapped = sig;
362}
363
364/*
365 * Checks a given selector for its code bitness or returns -1 if it's not
366 * a usable code segment selector.
367 */
368int cs_bitness(unsigned short cs)
369{
370 uint32_t valid = 0, ar;
371 asm ("lar %[cs], %[ar]\n\t"
372 "jnz 1f\n\t"
373 "mov $1, %[valid]\n\t"
374 "1:"
375 : [ar] "=r" (ar), [valid] "+rm" (valid)
376 : [cs] "r" (cs));
377
378 if (!valid)
379 return -1;
380
381 bool db = (ar & (1 << 22));
382 bool l = (ar & (1 << 21));
383
384 if (!(ar & (1<<11)))
385 return -1; /* Not code. */
386
387 if (l && !db)
388 return 64;
389 else if (!l && db)
390 return 32;
391 else if (!l && !db)
392 return 16;
393 else
394 return -1; /* Unknown bitness. */
395}
396
397/* Finds a usable code segment of the requested bitness. */
398int find_cs(int bitness)
399{
400 unsigned short my_cs;
401
402 asm ("mov %%cs,%0" : "=r" (my_cs));
403
404 if (cs_bitness(my_cs) == bitness)
405 return my_cs;
406 if (cs_bitness(my_cs + (2 << 3)) == bitness)
407 return my_cs + (2 << 3);
408 if (my_cs > (2<<3) && cs_bitness(my_cs - (2 << 3)) == bitness)
409 return my_cs - (2 << 3);
410 if (cs_bitness(code16_sel) == bitness)
411 return code16_sel;
412
413 printf("[WARN]\tCould not find %d-bit CS\n", bitness);
414 return -1;
415}
416
417static int test_valid_sigreturn(int cs_bits, bool use_16bit_ss, int force_ss)
418{
419 int cs = find_cs(cs_bits);
420 if (cs == -1) {
421 printf("[SKIP]\tCode segment unavailable for %d-bit CS, %d-bit SS\n",
422 cs_bits, use_16bit_ss ? 16 : 32);
423 return 0;
424 }
425
426 if (force_ss != -1) {
427 sig_ss = force_ss;
428 } else {
429 if (use_16bit_ss) {
430 if (!data16_sel) {
431 printf("[SKIP]\tData segment unavailable for %d-bit CS, 16-bit SS\n",
432 cs_bits);
433 return 0;
434 }
435 sig_ss = data16_sel;
436 } else {
437 asm volatile ("mov %%ss,%0" : "=r" (sig_ss));
438 }
439 }
440
441 sig_cs = cs;
442
443 printf("[RUN]\tValid sigreturn: %d-bit CS (%hx), %d-bit SS (%hx%s)\n",
444 cs_bits, sig_cs, use_16bit_ss ? 16 : 32, sig_ss,
445 (sig_ss & 4) ? "" : ", GDT");
446
447 raise(SIGUSR1);
448
449 nerrs = 0;
450
451 /*
452 * Check that each register had an acceptable value when the
453 * int3 trampoline was invoked.
454 */
455 for (int i = 0; i < NGREG; i++) {
456 greg_t req = requested_regs[i], res = resulting_regs[i];
457 if (i == REG_TRAPNO || i == REG_IP)
458 continue; /* don't care */
459 if (i == REG_SP) {
460 printf("\tSP: %llx -> %llx\n", (unsigned long long)req,
461 (unsigned long long)res);
462
463 /*
464 * In many circumstances, the high 32 bits of rsp
465 * are zeroed. For example, we could be a real
466 * 32-bit program, or we could hit any of a number
467 * of poorly-documented IRET or segmented ESP
468 * oddities. If this happens, it's okay.
469 */
470 if (res == (req & 0xFFFFFFFF))
471 continue; /* OK; not expected to work */
472 }
473
474 bool ignore_reg = false;
475#if __i386__
476 if (i == REG_UESP)
477 ignore_reg = true;
478#else
479 if (i == REG_CSGSFS) {
480 struct selectors *req_sels =
481 (void *)&requested_regs[REG_CSGSFS];
482 struct selectors *res_sels =
483 (void *)&resulting_regs[REG_CSGSFS];
484 if (req_sels->cs != res_sels->cs) {
485 printf("[FAIL]\tCS mismatch: requested 0x%hx; got 0x%hx\n",
486 req_sels->cs, res_sels->cs);
487 nerrs++;
488 }
489
490 if (req_sels->ss != res_sels->ss) {
491 printf("[FAIL]\tSS mismatch: requested 0x%hx; got 0x%hx\n",
492 req_sels->ss, res_sels->ss);
493 nerrs++;
494 }
495
496 continue;
497 }
498#endif
499
500 /* Sanity check on the kernel */
501 if (i == REG_AX && requested_regs[i] != resulting_regs[i]) {
502 printf("[FAIL]\tAX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n",
503 (unsigned long long)requested_regs[i],
504 (unsigned long long)resulting_regs[i]);
505 nerrs++;
506 continue;
507 }
508
509 if (requested_regs[i] != resulting_regs[i] && !ignore_reg) {
510 /*
511 * SP is particularly interesting here. The
512 * usual cause of failures is that we hit the
513 * nasty IRET case of returning to a 16-bit SS,
514 * in which case bits 16:31 of the *kernel*
515 * stack pointer persist in ESP.
516 */
517 printf("[FAIL]\tReg %d mismatch: requested 0x%llx; got 0x%llx\n",
518 i, (unsigned long long)requested_regs[i],
519 (unsigned long long)resulting_regs[i]);
520 nerrs++;
521 }
522 }
523
524 if (nerrs == 0)
525 printf("[OK]\tall registers okay\n");
526
527 return nerrs;
528}
529
530static int test_bad_iret(int cs_bits, unsigned short ss, int force_cs)
531{
532 int cs = force_cs == -1 ? find_cs(cs_bits) : force_cs;
533 if (cs == -1)
534 return 0;
535
536 sig_cs = cs;
537 sig_ss = ss;
538
539 printf("[RUN]\t%d-bit CS (%hx), bogus SS (%hx)\n",
540 cs_bits, sig_cs, sig_ss);
541
542 sig_trapped = 0;
543 raise(SIGUSR1);
544 if (sig_trapped) {
545 char errdesc[32] = "";
546 if (sig_err) {
547 const char *src = (sig_err & 1) ? " EXT" : "";
548 const char *table;
549 if ((sig_err & 0x6) == 0x0)
550 table = "GDT";
551 else if ((sig_err & 0x6) == 0x4)
552 table = "LDT";
553 else if ((sig_err & 0x6) == 0x2)
554 table = "IDT";
555 else
556 table = "???";
557
558 sprintf(errdesc, "%s%s index %d, ",
559 table, src, sig_err >> 3);
560 }
561
562 char trapname[32];
563 if (sig_trapno == 13)
564 strcpy(trapname, "GP");
565 else if (sig_trapno == 11)
566 strcpy(trapname, "NP");
567 else if (sig_trapno == 12)
568 strcpy(trapname, "SS");
569 else if (sig_trapno == 32)
570 strcpy(trapname, "IRET"); /* X86_TRAP_IRET */
571 else
572 sprintf(trapname, "%d", sig_trapno);
573
574 printf("[OK]\tGot #%s(0x%lx) (i.e. %s%s)\n",
575 trapname, (unsigned long)sig_err,
576 errdesc, strsignal(sig_trapped));
577 return 0;
578 } else {
579 printf("[FAIL]\tDid not get SIGSEGV\n");
580 return 1;
581 }
582}
583
584int main()
585{
586 int total_nerrs = 0;
587 unsigned short my_cs, my_ss;
588
589 asm volatile ("mov %%cs,%0" : "=r" (my_cs));
590 asm volatile ("mov %%ss,%0" : "=r" (my_ss));
591 setup_ldt();
592
593 stack_t stack = {
594 .ss_sp = altstack_data,
595 .ss_size = SIGSTKSZ,
596 };
597 if (sigaltstack(&stack, NULL) != 0)
598 err(1, "sigaltstack");
599
600 sethandler(SIGUSR1, sigusr1, 0);
601 sethandler(SIGTRAP, sigtrap, SA_ONSTACK);
602
603 /* Easy cases: return to a 32-bit SS in each possible CS bitness. */
604 total_nerrs += test_valid_sigreturn(64, false, -1);
605 total_nerrs += test_valid_sigreturn(32, false, -1);
606 total_nerrs += test_valid_sigreturn(16, false, -1);
607
608 /*
609 * Test easy espfix cases: return to a 16-bit LDT SS in each possible
610 * CS bitness. NB: with a long mode CS, the SS bitness is irrelevant.
611 *
612 * This catches the original missing-espfix-on-64-bit-kernels issue
613 * as well as CVE-2014-8134.
614 */
615 total_nerrs += test_valid_sigreturn(64, true, -1);
616 total_nerrs += test_valid_sigreturn(32, true, -1);
617 total_nerrs += test_valid_sigreturn(16, true, -1);
618
619 if (gdt_data16_idx) {
620 /*
621 * For performance reasons, Linux skips espfix if SS points
622 * to the GDT. If we were able to allocate a 16-bit SS in
623 * the GDT, see if it leaks parts of the kernel stack pointer.
624 *
625 * This tests for CVE-2014-8133.
626 */
627 total_nerrs += test_valid_sigreturn(64, true,
628 GDT3(gdt_data16_idx));
629 total_nerrs += test_valid_sigreturn(32, true,
630 GDT3(gdt_data16_idx));
631 total_nerrs += test_valid_sigreturn(16, true,
632 GDT3(gdt_data16_idx));
633 }
634
635 /*
636 * We're done testing valid sigreturn cases. Now we test states
637 * for which sigreturn itself will succeed but the subsequent
638 * entry to user mode will fail.
639 *
640 * Depending on the failure mode and the kernel bitness, these
641 * entry failures can generate SIGSEGV, SIGBUS, or SIGILL.
642 */
643 clearhandler(SIGTRAP);
644 sethandler(SIGSEGV, sigtrap, SA_ONSTACK);
645 sethandler(SIGBUS, sigtrap, SA_ONSTACK);
646 sethandler(SIGILL, sigtrap, SA_ONSTACK); /* 32-bit kernels do this */
647
648 /* Easy failures: invalid SS, resulting in #GP(0) */
649 test_bad_iret(64, ldt_nonexistent_sel, -1);
650 test_bad_iret(32, ldt_nonexistent_sel, -1);
651 test_bad_iret(16, ldt_nonexistent_sel, -1);
652
653 /* These fail because SS isn't a data segment, resulting in #GP(SS) */
654 test_bad_iret(64, my_cs, -1);
655 test_bad_iret(32, my_cs, -1);
656 test_bad_iret(16, my_cs, -1);
657
658 /* Try to return to a not-present code segment, triggering #NP(SS). */
659 test_bad_iret(32, my_ss, npcode32_sel);
660
661 /*
662 * Try to return to a not-present but otherwise valid data segment.
663 * This will cause IRET to fail with #SS on the espfix stack. This
664 * exercises CVE-2014-9322.
665 *
666 * Note that, if espfix is enabled, 64-bit Linux will lose track
667 * of the actual cause of failure and report #GP(0) instead.
668 * This would be very difficult for Linux to avoid, because
669 * espfix64 causes IRET failures to be promoted to #DF, so the
670 * original exception frame is never pushed onto the stack.
671 */
672 test_bad_iret(32, npdata32_sel, -1);
673
674 /*
675 * Try to return to a not-present but otherwise valid data
676 * segment without invoking espfix. Newer kernels don't allow
677 * this to happen in the first place. On older kernels, though,
678 * this can trigger CVE-2014-9322.
679 */
680 if (gdt_npdata32_idx)
681 test_bad_iret(32, GDT3(gdt_npdata32_idx), -1);
682
683 return total_nerrs ? 1 : 0;
684}
diff --git a/tools/testing/selftests/x86/single_step_syscall.c b/tools/testing/selftests/x86/single_step_syscall.c
new file mode 100644
index 000000000000..50c26358e8b7
--- /dev/null
+++ b/tools/testing/selftests/x86/single_step_syscall.c
@@ -0,0 +1,181 @@
1/*
2 * single_step_syscall.c - single-steps various x86 syscalls
3 * Copyright (c) 2014-2015 Andrew Lutomirski
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * This is a very simple series of tests that makes system calls with
15 * the TF flag set. This exercises some nasty kernel code in the
16 * SYSENTER case: SYSENTER does not clear TF, so SYSENTER with TF set
17 * immediately issues #DB from CPL 0. This requires special handling in
18 * the kernel.
19 */
20
21#define _GNU_SOURCE
22
23#include <sys/time.h>
24#include <time.h>
25#include <stdlib.h>
26#include <sys/syscall.h>
27#include <unistd.h>
28#include <stdio.h>
29#include <string.h>
30#include <inttypes.h>
31#include <sys/mman.h>
32#include <sys/signal.h>
33#include <sys/ucontext.h>
34#include <asm/ldt.h>
35#include <err.h>
36#include <setjmp.h>
37#include <stddef.h>
38#include <stdbool.h>
39#include <sys/ptrace.h>
40#include <sys/user.h>
41
42static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
43 int flags)
44{
45 struct sigaction sa;
46 memset(&sa, 0, sizeof(sa));
47 sa.sa_sigaction = handler;
48 sa.sa_flags = SA_SIGINFO | flags;
49 sigemptyset(&sa.sa_mask);
50 if (sigaction(sig, &sa, 0))
51 err(1, "sigaction");
52}
53
54static volatile sig_atomic_t sig_traps;
55
56#ifdef __x86_64__
57# define REG_IP REG_RIP
58# define WIDTH "q"
59#else
60# define REG_IP REG_EIP
61# define WIDTH "l"
62#endif
63
64static unsigned long get_eflags(void)
65{
66 unsigned long eflags;
67 asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
68 return eflags;
69}
70
71static void set_eflags(unsigned long eflags)
72{
73 asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
74 : : "rm" (eflags) : "flags");
75}
76
77#define X86_EFLAGS_TF (1UL << 8)
78
79static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
80{
81 ucontext_t *ctx = (ucontext_t*)ctx_void;
82
83 if (get_eflags() & X86_EFLAGS_TF) {
84 set_eflags(get_eflags() & ~X86_EFLAGS_TF);
85 printf("[WARN]\tSIGTRAP handler had TF set\n");
86 _exit(1);
87 }
88
89 sig_traps++;
90
91 if (sig_traps == 10000 || sig_traps == 10001) {
92 printf("[WARN]\tHit %d SIGTRAPs with si_addr 0x%lx, ip 0x%lx\n",
93 (int)sig_traps,
94 (unsigned long)info->si_addr,
95 (unsigned long)ctx->uc_mcontext.gregs[REG_IP]);
96 }
97}
98
99static void check_result(void)
100{
101 unsigned long new_eflags = get_eflags();
102 set_eflags(new_eflags & ~X86_EFLAGS_TF);
103
104 if (!sig_traps) {
105 printf("[FAIL]\tNo SIGTRAP\n");
106 exit(1);
107 }
108
109 if (!(new_eflags & X86_EFLAGS_TF)) {
110 printf("[FAIL]\tTF was cleared\n");
111 exit(1);
112 }
113
114 printf("[OK]\tSurvived with TF set and %d traps\n", (int)sig_traps);
115 sig_traps = 0;
116}
117
118int main()
119{
120 int tmp;
121
122 sethandler(SIGTRAP, sigtrap, 0);
123
124 printf("[RUN]\tSet TF and check nop\n");
125 set_eflags(get_eflags() | X86_EFLAGS_TF);
126 asm volatile ("nop");
127 check_result();
128
129#ifdef __x86_64__
130 printf("[RUN]\tSet TF and check syscall-less opportunistic sysret\n");
131 set_eflags(get_eflags() | X86_EFLAGS_TF);
132 extern unsigned char post_nop[];
133 asm volatile ("pushf" WIDTH "\n\t"
134 "pop" WIDTH " %%r11\n\t"
135 "nop\n\t"
136 "post_nop:"
137 : : "c" (post_nop) : "r11");
138 check_result();
139#endif
140
141 printf("[RUN]\tSet TF and check int80\n");
142 set_eflags(get_eflags() | X86_EFLAGS_TF);
143 asm volatile ("int $0x80" : "=a" (tmp) : "a" (SYS_getpid));
144 check_result();
145
146 /*
147 * This test is particularly interesting if fast syscalls use
148 * SYSENTER: it triggers a nasty design flaw in SYSENTER.
149 * Specifically, SYSENTER does not clear TF, so either SYSENTER
150 * or the next instruction traps at CPL0. (Of course, Intel
151 * mostly forgot to document exactly what happens here.) So we
152 * get a CPL0 fault with usergs (on 64-bit kernels) and possibly
153 * no stack. The only sane way the kernel can possibly handle
154 * it is to clear TF on return from the #DB handler, but this
155 * happens way too early to set TF in the saved pt_regs, so the
156 * kernel has to do something clever to avoid losing track of
157 * the TF bit.
158 *
159 * Needless to say, we've had bugs in this area.
160 */
161 syscall(SYS_getpid); /* Force symbol binding without TF set. */
162 printf("[RUN]\tSet TF and check a fast syscall\n");
163 set_eflags(get_eflags() | X86_EFLAGS_TF);
164 syscall(SYS_getpid);
165 check_result();
166
167 /* Now make sure that another fast syscall doesn't set TF again. */
168 printf("[RUN]\tFast syscall with TF cleared\n");
169 fflush(stdout); /* Force a syscall */
170 if (get_eflags() & X86_EFLAGS_TF) {
171 printf("[FAIL]\tTF is now set\n");
172 exit(1);
173 }
174 if (sig_traps) {
175 printf("[FAIL]\tGot SIGTRAP\n");
176 exit(1);
177 }
178 printf("[OK]\tNothing unexpected happened\n");
179
180 return 0;
181}
diff --git a/tools/testing/selftests/x86/trivial_32bit_program.c b/tools/testing/selftests/x86/trivial_32bit_program.c
new file mode 100644
index 000000000000..2e231beb0a39
--- /dev/null
+++ b/tools/testing/selftests/x86/trivial_32bit_program.c
@@ -0,0 +1,14 @@
1/*
2 * Trivial program to check that we have a valid 32-bit build environment.
3 * Copyright (c) 2015 Andy Lutomirski
4 * GPL v2
5 */
6
7#include <stdio.h>
8
9int main()
10{
11 printf("\n");
12
13 return 0;
14}
diff --git a/tools/thermal/tmon/.gitignore b/tools/thermal/tmon/.gitignore
new file mode 100644
index 000000000000..06e96be65276
--- /dev/null
+++ b/tools/thermal/tmon/.gitignore
@@ -0,0 +1 @@
/tmon
diff --git a/tools/thermal/tmon/Makefile b/tools/thermal/tmon/Makefile
index e775adcbd29f..0788621c8d76 100644
--- a/tools/thermal/tmon/Makefile
+++ b/tools/thermal/tmon/Makefile
@@ -2,8 +2,8 @@ VERSION = 1.0
2 2
3BINDIR=usr/bin 3BINDIR=usr/bin
4WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int 4WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int
5CFLAGS= -O1 ${WARNFLAGS} -fstack-protector 5CFLAGS+= -O1 ${WARNFLAGS} -fstack-protector
6CC=gcc 6CC=$(CROSS_COMPILE)gcc
7 7
8CFLAGS+=-D VERSION=\"$(VERSION)\" 8CFLAGS+=-D VERSION=\"$(VERSION)\"
9LDFLAGS+= 9LDFLAGS+=
@@ -16,12 +16,21 @@ INSTALL_CONFIGFILE=install -m 644 -p
16CONFIG_FILE= 16CONFIG_FILE=
17CONFIG_PATH= 17CONFIG_PATH=
18 18
19# Static builds might require -ltinfo, for instance
20ifneq ($(findstring -static, $(LDFLAGS)),)
21STATIC := --static
22endif
23
24TMON_LIBS=-lm -lpthread
25TMON_LIBS += $(shell pkg-config --libs $(STATIC) panelw ncursesw 2> /dev/null || \
26 pkg-config --libs $(STATIC) panel ncurses 2> /dev/null || \
27 echo -lpanel -lncurses)
19 28
20OBJS = tmon.o tui.o sysfs.o pid.o 29OBJS = tmon.o tui.o sysfs.o pid.o
21OBJS += 30OBJS +=
22 31
23tmon: $(OBJS) Makefile tmon.h 32tmon: $(OBJS) Makefile tmon.h
24 $(CC) ${CFLAGS} $(LDFLAGS) $(OBJS) -o $(TARGET) -lm -lpanel -lncursesw -ltinfo -lpthread 33 $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(TARGET) $(TMON_LIBS)
25 34
26valgrind: tmon 35valgrind: tmon
27 sudo valgrind -v --track-origins=yes --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./$(TARGET) 1> /dev/null 36 sudo valgrind -v --track-origins=yes --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./$(TARGET) 1> /dev/null
diff --git a/tools/thermal/tmon/tmon.8 b/tools/thermal/tmon/tmon.8
index 0be727cb9892..02d5179803aa 100644
--- a/tools/thermal/tmon/tmon.8
+++ b/tools/thermal/tmon/tmon.8
@@ -55,6 +55,8 @@ The \fB-l --log\fP option write data to /var/tmp/tmon.log
55.PP 55.PP
56The \fB-t --time-interval\fP option sets the polling interval in seconds 56The \fB-t --time-interval\fP option sets the polling interval in seconds
57.PP 57.PP
58The \fB-T --target-temp\fP option sets the initial target temperature
59.PP
58The \fB-v --version\fP option shows the version of \fBtmon \fP 60The \fB-v --version\fP option shows the version of \fBtmon \fP
59.PP 61.PP
60The \fB-z --zone\fP option sets the target therma zone instance to be controlled 62The \fB-z --zone\fP option sets the target therma zone instance to be controlled
diff --git a/tools/thermal/tmon/tmon.c b/tools/thermal/tmon/tmon.c
index 09b7c3218334..9aa19652e8e8 100644
--- a/tools/thermal/tmon/tmon.c
+++ b/tools/thermal/tmon/tmon.c
@@ -64,6 +64,7 @@ void usage()
64 printf(" -h, --help show this help message\n"); 64 printf(" -h, --help show this help message\n");
65 printf(" -l, --log log data to /var/tmp/tmon.log\n"); 65 printf(" -l, --log log data to /var/tmp/tmon.log\n");
66 printf(" -t, --time-interval sampling time interval, > 1 sec.\n"); 66 printf(" -t, --time-interval sampling time interval, > 1 sec.\n");
67 printf(" -T, --target-temp initial target temperature\n");
67 printf(" -v, --version show version\n"); 68 printf(" -v, --version show version\n");
68 printf(" -z, --zone target thermal zone id\n"); 69 printf(" -z, --zone target thermal zone id\n");
69 70
@@ -219,6 +220,7 @@ static struct option opts[] = {
219 { "control", 1, NULL, 'c' }, 220 { "control", 1, NULL, 'c' },
220 { "daemon", 0, NULL, 'd' }, 221 { "daemon", 0, NULL, 'd' },
221 { "time-interval", 1, NULL, 't' }, 222 { "time-interval", 1, NULL, 't' },
223 { "target-temp", 1, NULL, 'T' },
222 { "log", 0, NULL, 'l' }, 224 { "log", 0, NULL, 'l' },
223 { "help", 0, NULL, 'h' }, 225 { "help", 0, NULL, 'h' },
224 { "version", 0, NULL, 'v' }, 226 { "version", 0, NULL, 'v' },
@@ -231,7 +233,7 @@ int main(int argc, char **argv)
231{ 233{
232 int err = 0; 234 int err = 0;
233 int id2 = 0, c; 235 int id2 = 0, c;
234 double yk = 0.0; /* controller output */ 236 double yk = 0.0, temp; /* controller output */
235 int target_tz_index; 237 int target_tz_index;
236 238
237 if (geteuid() != 0) { 239 if (geteuid() != 0) {
@@ -239,7 +241,7 @@ int main(int argc, char **argv)
239 exit(EXIT_FAILURE); 241 exit(EXIT_FAILURE);
240 } 242 }
241 243
242 while ((c = getopt_long(argc, argv, "c:dlht:vgz:", opts, &id2)) != -1) { 244 while ((c = getopt_long(argc, argv, "c:dlht:T:vgz:", opts, &id2)) != -1) {
243 switch (c) { 245 switch (c) {
244 case 'c': 246 case 'c':
245 no_control = 0; 247 no_control = 0;
@@ -254,6 +256,14 @@ int main(int argc, char **argv)
254 if (ticktime < 1) 256 if (ticktime < 1)
255 ticktime = 1; 257 ticktime = 1;
256 break; 258 break;
259 case 'T':
260 temp = strtod(optarg, NULL);
261 if (temp < 0) {
262 fprintf(stderr, "error: temperature must be positive\n");
263 return 1;
264 }
265 target_temp_user = temp;
266 break;
257 case 'l': 267 case 'l':
258 printf("Logging data to /var/tmp/tmon.log\n"); 268 printf("Logging data to /var/tmp/tmon.log\n");
259 logging = 1; 269 logging = 1;
diff --git a/tools/thermal/tmon/tui.c b/tools/thermal/tmon/tui.c
index 89f8ef0e15c8..b5d1c6b22dd3 100644
--- a/tools/thermal/tmon/tui.c
+++ b/tools/thermal/tmon/tui.c
@@ -30,6 +30,18 @@
30 30
31#include "tmon.h" 31#include "tmon.h"
32 32
33#define min(x, y) ({ \
34 typeof(x) _min1 = (x); \
35 typeof(y) _min2 = (y); \
36 (void) (&_min1 == &_min2); \
37 _min1 < _min2 ? _min1 : _min2; })
38
39#define max(x, y) ({ \
40 typeof(x) _max1 = (x); \
41 typeof(y) _max2 = (y); \
42 (void) (&_max1 == &_max2); \
43 _max1 > _max2 ? _max1 : _max2; })
44
33static PANEL *data_panel; 45static PANEL *data_panel;
34static PANEL *dialogue_panel; 46static PANEL *dialogue_panel;
35static PANEL *top; 47static PANEL *top;
@@ -98,6 +110,18 @@ void write_status_bar(int x, char *line)
98 wrefresh(status_bar_window); 110 wrefresh(status_bar_window);
99} 111}
100 112
113/* wrap at 5 */
114#define DIAG_DEV_ROWS 5
115/*
116 * list cooling devices + "set temp" entry; wraps after 5 rows, if they fit
117 */
118static int diag_dev_rows(void)
119{
120 int entries = ptdata.nr_cooling_dev + 1;
121 int rows = max(DIAG_DEV_ROWS, (entries + 1) / 2);
122 return min(rows, entries);
123}
124
101void setup_windows(void) 125void setup_windows(void)
102{ 126{
103 int y_begin = 1; 127 int y_begin = 1;
@@ -122,7 +146,7 @@ void setup_windows(void)
122 * dialogue window is a pop-up, when needed it lays on top of cdev win 146 * dialogue window is a pop-up, when needed it lays on top of cdev win
123 */ 147 */
124 148
125 dialogue_window = subwin(stdscr, ptdata.nr_cooling_dev+5, maxx-50, 149 dialogue_window = subwin(stdscr, diag_dev_rows() + 5, maxx-50,
126 DIAG_Y, DIAG_X); 150 DIAG_Y, DIAG_X);
127 151
128 thermal_data_window = subwin(stdscr, ptdata.nr_tz_sensor * 152 thermal_data_window = subwin(stdscr, ptdata.nr_tz_sensor *
@@ -258,21 +282,26 @@ void show_cooling_device(void)
258} 282}
259 283
260const char DIAG_TITLE[] = "[ TUNABLES ]"; 284const char DIAG_TITLE[] = "[ TUNABLES ]";
261#define DIAG_DEV_ROWS 5
262void show_dialogue(void) 285void show_dialogue(void)
263{ 286{
264 int j, x = 0, y = 0; 287 int j, x = 0, y = 0;
288 int rows, cols;
265 WINDOW *w = dialogue_window; 289 WINDOW *w = dialogue_window;
266 290
267 if (tui_disabled || !w) 291 if (tui_disabled || !w)
268 return; 292 return;
269 293
294 getmaxyx(w, rows, cols);
295
296 /* Silence compiler 'unused' warnings */
297 (void)cols;
298
270 werase(w); 299 werase(w);
271 box(w, 0, 0); 300 box(w, 0, 0);
272 mvwprintw(w, 0, maxx/4, DIAG_TITLE); 301 mvwprintw(w, 0, maxx/4, DIAG_TITLE);
273 /* list all the available tunables */ 302 /* list all the available tunables */
274 for (j = 0; j <= ptdata.nr_cooling_dev; j++) { 303 for (j = 0; j <= ptdata.nr_cooling_dev; j++) {
275 y = j % DIAG_DEV_ROWS; 304 y = j % diag_dev_rows();
276 if (y == 0 && j != 0) 305 if (y == 0 && j != 0)
277 x += 20; 306 x += 20;
278 if (j == ptdata.nr_cooling_dev) 307 if (j == ptdata.nr_cooling_dev)
@@ -283,12 +312,10 @@ void show_dialogue(void)
283 ptdata.cdi[j].type, ptdata.cdi[j].instance); 312 ptdata.cdi[j].type, ptdata.cdi[j].instance);
284 } 313 }
285 wattron(w, A_BOLD); 314 wattron(w, A_BOLD);
286 mvwprintw(w, DIAG_DEV_ROWS+1, 1, "Enter Choice [A-Z]?"); 315 mvwprintw(w, diag_dev_rows()+1, 1, "Enter Choice [A-Z]?");
287 wattroff(w, A_BOLD); 316 wattroff(w, A_BOLD);
288 /* y size of dialogue win is nr cdev + 5, so print legend 317 /* print legend at the bottom line */
289 * at the bottom line 318 mvwprintw(w, rows - 2, 1,
290 */
291 mvwprintw(w, ptdata.nr_cooling_dev+3, 1,
292 "Legend: A=Active, P=Passive, C=Critical"); 319 "Legend: A=Active, P=Passive, C=Critical");
293 320
294 wrefresh(dialogue_window); 321 wrefresh(dialogue_window);
@@ -437,7 +464,7 @@ static void handle_input_choice(int ch)
437 snprintf(buf, sizeof(buf), "New Value for %.10s-%2d: ", 464 snprintf(buf, sizeof(buf), "New Value for %.10s-%2d: ",
438 ptdata.cdi[cdev_id].type, 465 ptdata.cdi[cdev_id].type,
439 ptdata.cdi[cdev_id].instance); 466 ptdata.cdi[cdev_id].instance);
440 write_dialogue_win(buf, DIAG_DEV_ROWS+2, 2); 467 write_dialogue_win(buf, diag_dev_rows() + 2, 2);
441 handle_input_val(cdev_id); 468 handle_input_val(cdev_id);
442 } else { 469 } else {
443 snprintf(buf, sizeof(buf), "Invalid selection %d", ch); 470 snprintf(buf, sizeof(buf), "Invalid selection %d", ch);