aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/hv/hv_fcopy_daemon.c33
-rw-r--r--tools/hv/hv_kvp_daemon.c48
-rw-r--r--tools/hv/hv_vss_daemon.c95
-rw-r--r--tools/include/asm-generic/bitops.h27
-rw-r--r--tools/include/asm-generic/bitops/__ffs.h43
-rw-r--r--tools/include/asm-generic/bitops/__fls.h1
-rw-r--r--tools/include/asm-generic/bitops/atomic.h22
-rw-r--r--tools/include/asm-generic/bitops/find.h33
-rw-r--r--tools/include/asm-generic/bitops/fls.h1
-rw-r--r--tools/include/asm-generic/bitops/fls64.h1
-rw-r--r--tools/include/linux/bitops.h53
-rw-r--r--tools/include/linux/log2.h185
-rw-r--r--tools/lib/api/fs/fs.c34
-rw-r--r--tools/lib/api/fs/fs.h3
-rw-r--r--tools/lib/traceevent/plugin_scsi.c9
-rw-r--r--tools/lib/util/find_next_bit.c89
-rw-r--r--tools/perf/.gitignore2
-rw-r--r--tools/perf/Documentation/perf-record.txt6
-rw-r--r--tools/perf/Documentation/perf-report.txt12
-rw-r--r--tools/perf/Documentation/perf.txt4
-rw-r--r--tools/perf/MANIFEST16
-rw-r--r--tools/perf/Makefile.perf66
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c38
-rw-r--r--tools/perf/bench/mem-memcpy.c286
-rw-r--r--tools/perf/bench/mem-memset.c304
-rw-r--r--tools/perf/builtin-buildid-cache.c13
-rw-r--r--tools/perf/builtin-diff.c1
-rw-r--r--tools/perf/builtin-inject.c4
-rw-r--r--tools/perf/builtin-kvm.c28
-rw-r--r--tools/perf/builtin-probe.c65
-rw-r--r--tools/perf/builtin-record.c20
-rw-r--r--tools/perf/builtin-report.c31
-rw-r--r--tools/perf/builtin-script.c8
-rw-r--r--tools/perf/builtin-stat.c105
-rw-r--r--tools/perf/builtin-timechart.c9
-rw-r--r--tools/perf/builtin-trace.c20
-rw-r--r--tools/perf/config/Makefile49
-rw-r--r--tools/perf/config/Makefile.arch8
-rw-r--r--tools/perf/config/feature-checks/Makefile16
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-compile.c4
-rw-r--r--tools/perf/config/feature-checks/test-zlib.c9
-rw-r--r--tools/perf/perf-read-vdso.c34
-rw-r--r--tools/perf/perf.c14
-rw-r--r--tools/perf/perf.h4
-rw-r--r--tools/perf/scripts/python/bin/export-to-postgresql-record8
-rw-r--r--tools/perf/scripts/python/bin/export-to-postgresql-report29
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py444
-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.c2
-rw-r--r--tools/perf/tests/code-reading.c13
-rw-r--r--tools/perf/tests/dwarf-unwind.c18
-rw-r--r--tools/perf/tests/hists_filter.c2
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c2
-rw-r--r--tools/perf/tests/sample-parsing.c55
-rw-r--r--tools/perf/ui/browsers/annotate.c13
-rw-r--r--tools/perf/ui/browsers/hists.c44
-rw-r--r--tools/perf/ui/gtk/hists.c11
-rw-r--r--tools/perf/ui/hist.c4
-rw-r--r--tools/perf/ui/stdio/hist.c23
-rw-r--r--tools/perf/util/annotate.c34
-rw-r--r--tools/perf/util/annotate.h1
-rw-r--r--tools/perf/util/build-id.c345
-rw-r--r--tools/perf/util/build-id.h12
-rw-r--r--tools/perf/util/callchain.c39
-rw-r--r--tools/perf/util/callchain.h11
-rw-r--r--tools/perf/util/comm.h4
-rw-r--r--tools/perf/util/config.c10
-rw-r--r--tools/perf/util/db-export.c428
-rw-r--r--tools/perf/util/db-export.h107
-rw-r--r--tools/perf/util/debug.c4
-rw-r--r--tools/perf/util/dso.c71
-rw-r--r--tools/perf/util/dso.h13
-rw-r--r--tools/perf/util/event.c20
-rw-r--r--tools/perf/util/event.h44
-rw-r--r--tools/perf/util/evlist.c95
-rw-r--r--tools/perf/util/evlist.h1
-rw-r--r--tools/perf/util/evsel.c156
-rw-r--r--tools/perf/util/evsel.h50
-rw-r--r--tools/perf/util/find-vdso-map.c30
-rw-r--r--tools/perf/util/header.c361
-rw-r--r--tools/perf/util/header.h8
-rw-r--r--tools/perf/util/include/asm/hash.h6
-rw-r--r--tools/perf/util/include/linux/bitmap.h17
-rw-r--r--tools/perf/util/include/linux/bitops.h160
-rw-r--r--tools/perf/util/machine.c318
-rw-r--r--tools/perf/util/machine.h17
-rw-r--r--tools/perf/util/map.c10
-rw-r--r--tools/perf/util/map.h4
-rw-r--r--tools/perf/util/parse-events.c2
-rw-r--r--tools/perf/util/parse-options.c78
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/pmu.c115
-rw-r--r--tools/perf/util/pmu.h5
-rw-r--r--tools/perf/util/probe-event.c18
-rw-r--r--tools/perf/util/record.c11
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c29
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c440
-rw-r--r--tools/perf/util/session.c196
-rw-r--r--tools/perf/util/session.h15
-rw-r--r--tools/perf/util/sort.c8
-rw-r--r--tools/perf/util/srcline.c23
-rw-r--r--tools/perf/util/symbol-elf.c56
-rw-r--r--tools/perf/util/symbol-minimal.c9
-rw-r--r--tools/perf/util/symbol.c19
-rw-r--r--tools/perf/util/symbol.h25
-rw-r--r--tools/perf/util/thread-stack.c747
-rw-r--r--tools/perf/util/thread-stack.h111
-rw-r--r--tools/perf/util/thread.c14
-rw-r--r--tools/perf/util/thread.h9
-rw-r--r--tools/perf/util/tool.h3
-rw-r--r--tools/perf/util/unwind-libdw.c8
-rw-r--r--tools/perf/util/unwind-libunwind.c17
-rw-r--r--tools/perf/util/unwind.h2
-rw-r--r--tools/perf/util/util.c26
-rw-r--r--tools/perf/util/util.h42
-rw-r--r--tools/perf/util/vdso.c217
-rw-r--r--tools/perf/util/vdso.h4
-rw-r--r--tools/perf/util/zlib.c78
-rw-r--r--tools/power/cpupower/utils/cpupower.c2
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.c2
-rwxr-xr-xtools/testing/ktest/ktest.pl37
-rw-r--r--tools/testing/selftests/Makefile15
-rw-r--r--tools/testing/selftests/README.txt61
-rw-r--r--tools/testing/selftests/breakpoints/breakpoint_test.c10
-rw-r--r--tools/testing/selftests/exec/.gitignore9
-rw-r--r--tools/testing/selftests/exec/Makefile25
-rw-r--r--tools/testing/selftests/exec/execveat.c397
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest43
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/basic4.tc5
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/event-enable.tc53
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc53
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc47
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc89
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc52
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc80
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions16
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc55
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc1
-rw-r--r--tools/testing/selftests/ipc/msgque.c26
-rw-r--r--tools/testing/selftests/kcmp/Makefile22
-rw-r--r--tools/testing/selftests/kcmp/kcmp_test.c27
-rw-r--r--tools/testing/selftests/kselftest.h62
-rw-r--r--tools/testing/selftests/mount/unprivileged-remount-test.c204
-rw-r--r--tools/testing/selftests/net/Makefile8
-rwxr-xr-xtools/testing/selftests/net/test_bpf.sh10
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh6
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh19
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY022
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE013
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE023
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE02-T3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE035
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE041
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE051
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE061
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE071
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE085
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08-T3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE093
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST14
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP18
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP18
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP19
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp27
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh33
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST17
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP19
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP18
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp19
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP26
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp27
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp18
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP30
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all30
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none30
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp30
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST14
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP19
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP18
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp27
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh44
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST14
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP19
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP18
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp27
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh23
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH22
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh57
-rw-r--r--tools/testing/selftests/rcutorture/doc/TINY_RCU.txt2
-rw-r--r--tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt15
-rw-r--r--tools/testing/selftests/size/.gitignore1
-rw-r--r--tools/testing/selftests/size/Makefile12
-rw-r--r--tools/testing/selftests/size/get_size.c100
-rw-r--r--tools/testing/selftests/timers/posix_timers.c14
-rw-r--r--tools/testing/selftests/user/Makefile8
-rwxr-xr-xtools/testing/selftests/user/test_user_copy.sh10
-rw-r--r--tools/thermal/tmon/sysfs.c6
-rw-r--r--tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c2
-rw-r--r--tools/usb/usbip/libsrc/list.h2
-rw-r--r--tools/usb/usbip/src/usbipd.c2
-rw-r--r--tools/virtio/Makefile2
-rw-r--r--tools/virtio/linux/virtio.h23
-rw-r--r--tools/virtio/linux/virtio_byteorder.h8
-rw-r--r--tools/virtio/linux/virtio_config.h72
-rw-r--r--tools/virtio/uapi/linux/virtio_types.h1
-rw-r--r--tools/virtio/virtio_test.c20
-rw-r--r--tools/virtio/vringh_test.c21
-rw-r--r--tools/vm/Makefile4
-rw-r--r--tools/vm/page_owner_sort.c144
260 files changed, 7237 insertions, 3535 deletions
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index 8f96b3ee0724..f437d739f37d 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -33,6 +33,7 @@
33#include <sys/stat.h> 33#include <sys/stat.h>
34#include <fcntl.h> 34#include <fcntl.h>
35#include <dirent.h> 35#include <dirent.h>
36#include <getopt.h>
36 37
37static int target_fd; 38static int target_fd;
38static char target_fname[W_MAX_PATH]; 39static char target_fname[W_MAX_PATH];
@@ -126,15 +127,43 @@ static int hv_copy_cancel(void)
126 127
127} 128}
128 129
129int main(void) 130void print_usage(char *argv[])
131{
132 fprintf(stderr, "Usage: %s [options]\n"
133 "Options are:\n"
134 " -n, --no-daemon stay in foreground, don't daemonize\n"
135 " -h, --help print this help\n", argv[0]);
136}
137
138int main(int argc, char *argv[])
130{ 139{
131 int fd, fcopy_fd, len; 140 int fd, fcopy_fd, len;
132 int error; 141 int error;
142 int daemonize = 1, long_index = 0, opt;
133 int version = FCOPY_CURRENT_VERSION; 143 int version = FCOPY_CURRENT_VERSION;
134 char *buffer[4096 * 2]; 144 char *buffer[4096 * 2];
135 struct hv_fcopy_hdr *in_msg; 145 struct hv_fcopy_hdr *in_msg;
136 146
137 if (daemon(1, 0)) { 147 static struct option long_options[] = {
148 {"help", no_argument, 0, 'h' },
149 {"no-daemon", no_argument, 0, 'n' },
150 {0, 0, 0, 0 }
151 };
152
153 while ((opt = getopt_long(argc, argv, "hn", long_options,
154 &long_index)) != -1) {
155 switch (opt) {
156 case 'n':
157 daemonize = 0;
158 break;
159 case 'h':
160 default:
161 print_usage(argv);
162 exit(EXIT_FAILURE);
163 }
164 }
165
166 if (daemonize && daemon(1, 0)) {
138 syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); 167 syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno));
139 exit(EXIT_FAILURE); 168 exit(EXIT_FAILURE);
140 } 169 }
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 4088b816a3ee..6a6432a20a1d 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -43,6 +43,7 @@
43#include <fcntl.h> 43#include <fcntl.h>
44#include <dirent.h> 44#include <dirent.h>
45#include <net/if.h> 45#include <net/if.h>
46#include <getopt.h>
46 47
47/* 48/*
48 * KVP protocol: The user mode component first registers with the 49 * KVP protocol: The user mode component first registers with the
@@ -1417,7 +1418,15 @@ netlink_send(int fd, struct cn_msg *msg)
1417 return sendmsg(fd, &message, 0); 1418 return sendmsg(fd, &message, 0);
1418} 1419}
1419 1420
1420int main(void) 1421void print_usage(char *argv[])
1422{
1423 fprintf(stderr, "Usage: %s [options]\n"
1424 "Options are:\n"
1425 " -n, --no-daemon stay in foreground, don't daemonize\n"
1426 " -h, --help print this help\n", argv[0]);
1427}
1428
1429int main(int argc, char *argv[])
1421{ 1430{
1422 int fd, len, nl_group; 1431 int fd, len, nl_group;
1423 int error; 1432 int error;
@@ -1435,9 +1444,30 @@ int main(void)
1435 struct hv_kvp_ipaddr_value *kvp_ip_val; 1444 struct hv_kvp_ipaddr_value *kvp_ip_val;
1436 char *kvp_recv_buffer; 1445 char *kvp_recv_buffer;
1437 size_t kvp_recv_buffer_len; 1446 size_t kvp_recv_buffer_len;
1447 int daemonize = 1, long_index = 0, opt;
1448
1449 static struct option long_options[] = {
1450 {"help", no_argument, 0, 'h' },
1451 {"no-daemon", no_argument, 0, 'n' },
1452 {0, 0, 0, 0 }
1453 };
1454
1455 while ((opt = getopt_long(argc, argv, "hn", long_options,
1456 &long_index)) != -1) {
1457 switch (opt) {
1458 case 'n':
1459 daemonize = 0;
1460 break;
1461 case 'h':
1462 default:
1463 print_usage(argv);
1464 exit(EXIT_FAILURE);
1465 }
1466 }
1438 1467
1439 if (daemon(1, 0)) 1468 if (daemonize && daemon(1, 0))
1440 return 1; 1469 return 1;
1470
1441 openlog("KVP", 0, LOG_USER); 1471 openlog("KVP", 0, LOG_USER);
1442 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); 1472 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
1443 1473
@@ -1529,8 +1559,15 @@ int main(void)
1529 addr_p, &addr_l); 1559 addr_p, &addr_l);
1530 1560
1531 if (len < 0) { 1561 if (len < 0) {
1562 int saved_errno = errno;
1532 syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", 1563 syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s",
1533 addr.nl_pid, errno, strerror(errno)); 1564 addr.nl_pid, errno, strerror(errno));
1565
1566 if (saved_errno == ENOBUFS) {
1567 syslog(LOG_ERR, "receive error: ignored");
1568 continue;
1569 }
1570
1534 close(fd); 1571 close(fd);
1535 return -1; 1572 return -1;
1536 } 1573 }
@@ -1733,8 +1770,15 @@ kvp_done:
1733 1770
1734 len = netlink_send(fd, incoming_cn_msg); 1771 len = netlink_send(fd, incoming_cn_msg);
1735 if (len < 0) { 1772 if (len < 0) {
1773 int saved_errno = errno;
1736 syslog(LOG_ERR, "net_link send failed; error: %d %s", errno, 1774 syslog(LOG_ERR, "net_link send failed; error: %d %s", errno,
1737 strerror(errno)); 1775 strerror(errno));
1776
1777 if (saved_errno == ENOMEM || saved_errno == ENOBUFS) {
1778 syslog(LOG_ERR, "send error: ignored");
1779 continue;
1780 }
1781
1738 exit(EXIT_FAILURE); 1782 exit(EXIT_FAILURE);
1739 } 1783 }
1740 } 1784 }
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 6a213b8cd7b9..5e63f70bd956 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -36,6 +36,7 @@
36#include <linux/hyperv.h> 36#include <linux/hyperv.h>
37#include <linux/netlink.h> 37#include <linux/netlink.h>
38#include <syslog.h> 38#include <syslog.h>
39#include <getopt.h>
39 40
40static struct sockaddr_nl addr; 41static struct sockaddr_nl addr;
41 42
@@ -44,35 +45,51 @@ static struct sockaddr_nl addr;
44#endif 45#endif
45 46
46 47
47static int vss_do_freeze(char *dir, unsigned int cmd, char *fs_op) 48/* Don't use syslog() in the function since that can cause write to disk */
49static int vss_do_freeze(char *dir, unsigned int cmd)
48{ 50{
49 int ret, fd = open(dir, O_RDONLY); 51 int ret, fd = open(dir, O_RDONLY);
50 52
51 if (fd < 0) 53 if (fd < 0)
52 return 1; 54 return 1;
55
53 ret = ioctl(fd, cmd, 0); 56 ret = ioctl(fd, cmd, 0);
54 syslog(LOG_INFO, "VSS: %s of %s: %s\n", fs_op, dir, strerror(errno)); 57
58 /*
59 * If a partition is mounted more than once, only the first
60 * FREEZE/THAW can succeed and the later ones will get
61 * EBUSY/EINVAL respectively: there could be 2 cases:
62 * 1) a user may mount the same partition to differnt directories
63 * by mistake or on purpose;
64 * 2) The subvolume of btrfs appears to have the same partition
65 * mounted more than once.
66 */
67 if (ret) {
68 if ((cmd == FIFREEZE && errno == EBUSY) ||
69 (cmd == FITHAW && errno == EINVAL)) {
70 close(fd);
71 return 0;
72 }
73 }
74
55 close(fd); 75 close(fd);
56 return !!ret; 76 return !!ret;
57} 77}
58 78
59static int vss_operate(int operation) 79static int vss_operate(int operation)
60{ 80{
61 char *fs_op;
62 char match[] = "/dev/"; 81 char match[] = "/dev/";
63 FILE *mounts; 82 FILE *mounts;
64 struct mntent *ent; 83 struct mntent *ent;
65 unsigned int cmd; 84 unsigned int cmd;
66 int error = 0, root_seen = 0; 85 int error = 0, root_seen = 0, save_errno = 0;
67 86
68 switch (operation) { 87 switch (operation) {
69 case VSS_OP_FREEZE: 88 case VSS_OP_FREEZE:
70 cmd = FIFREEZE; 89 cmd = FIFREEZE;
71 fs_op = "freeze";
72 break; 90 break;
73 case VSS_OP_THAW: 91 case VSS_OP_THAW:
74 cmd = FITHAW; 92 cmd = FITHAW;
75 fs_op = "thaw";
76 break; 93 break;
77 default: 94 default:
78 return -1; 95 return -1;
@@ -85,7 +102,7 @@ static int vss_operate(int operation)
85 while ((ent = getmntent(mounts))) { 102 while ((ent = getmntent(mounts))) {
86 if (strncmp(ent->mnt_fsname, match, strlen(match))) 103 if (strncmp(ent->mnt_fsname, match, strlen(match)))
87 continue; 104 continue;
88 if (strcmp(ent->mnt_type, "iso9660") == 0) 105 if (hasmntopt(ent, MNTOPT_RO) != NULL)
89 continue; 106 continue;
90 if (strcmp(ent->mnt_type, "vfat") == 0) 107 if (strcmp(ent->mnt_type, "vfat") == 0)
91 continue; 108 continue;
@@ -93,14 +110,30 @@ static int vss_operate(int operation)
93 root_seen = 1; 110 root_seen = 1;
94 continue; 111 continue;
95 } 112 }
96 error |= vss_do_freeze(ent->mnt_dir, cmd, fs_op); 113 error |= vss_do_freeze(ent->mnt_dir, cmd);
114 if (error && operation == VSS_OP_FREEZE)
115 goto err;
97 } 116 }
98 endmntent(mounts);
99 117
100 if (root_seen) { 118 if (root_seen) {
101 error |= vss_do_freeze("/", cmd, fs_op); 119 error |= vss_do_freeze("/", cmd);
120 if (error && operation == VSS_OP_FREEZE)
121 goto err;
102 } 122 }
103 123
124 goto out;
125err:
126 save_errno = errno;
127 vss_operate(VSS_OP_THAW);
128 /* Call syslog after we thaw all filesystems */
129 if (ent)
130 syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
131 ent->mnt_dir, save_errno, strerror(save_errno));
132 else
133 syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
134 strerror(save_errno));
135out:
136 endmntent(mounts);
104 return error; 137 return error;
105} 138}
106 139
@@ -131,7 +164,15 @@ static int netlink_send(int fd, struct cn_msg *msg)
131 return sendmsg(fd, &message, 0); 164 return sendmsg(fd, &message, 0);
132} 165}
133 166
134int main(void) 167void print_usage(char *argv[])
168{
169 fprintf(stderr, "Usage: %s [options]\n"
170 "Options are:\n"
171 " -n, --no-daemon stay in foreground, don't daemonize\n"
172 " -h, --help print this help\n", argv[0]);
173}
174
175int main(int argc, char *argv[])
135{ 176{
136 int fd, len, nl_group; 177 int fd, len, nl_group;
137 int error; 178 int error;
@@ -143,8 +184,28 @@ int main(void)
143 struct hv_vss_msg *vss_msg; 184 struct hv_vss_msg *vss_msg;
144 char *vss_recv_buffer; 185 char *vss_recv_buffer;
145 size_t vss_recv_buffer_len; 186 size_t vss_recv_buffer_len;
187 int daemonize = 1, long_index = 0, opt;
188
189 static struct option long_options[] = {
190 {"help", no_argument, 0, 'h' },
191 {"no-daemon", no_argument, 0, 'n' },
192 {0, 0, 0, 0 }
193 };
194
195 while ((opt = getopt_long(argc, argv, "hn", long_options,
196 &long_index)) != -1) {
197 switch (opt) {
198 case 'n':
199 daemonize = 0;
200 break;
201 case 'h':
202 default:
203 print_usage(argv);
204 exit(EXIT_FAILURE);
205 }
206 }
146 207
147 if (daemon(1, 0)) 208 if (daemonize && daemon(1, 0))
148 return 1; 209 return 1;
149 210
150 openlog("Hyper-V VSS", 0, LOG_USER); 211 openlog("Hyper-V VSS", 0, LOG_USER);
@@ -249,8 +310,16 @@ int main(void)
249 case VSS_OP_FREEZE: 310 case VSS_OP_FREEZE:
250 case VSS_OP_THAW: 311 case VSS_OP_THAW:
251 error = vss_operate(op); 312 error = vss_operate(op);
252 if (error) 313 syslog(LOG_INFO, "VSS: op=%s: %s\n",
314 op == VSS_OP_FREEZE ? "FREEZE" : "THAW",
315 error ? "failed" : "succeeded");
316
317 if (error) {
253 error = HV_E_FAIL; 318 error = HV_E_FAIL;
319 syslog(LOG_ERR, "op=%d failed!", op);
320 syslog(LOG_ERR, "report it with these files:");
321 syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
322 }
254 break; 323 break;
255 default: 324 default:
256 syslog(LOG_ERR, "Illegal op:%d\n", op); 325 syslog(LOG_ERR, "Illegal op:%d\n", op);
diff --git a/tools/include/asm-generic/bitops.h b/tools/include/asm-generic/bitops.h
new file mode 100644
index 000000000000..6eedba1f7732
--- /dev/null
+++ b/tools/include/asm-generic/bitops.h
@@ -0,0 +1,27 @@
1#ifndef __TOOLS_ASM_GENERIC_BITOPS_H
2#define __TOOLS_ASM_GENERIC_BITOPS_H
3
4/*
5 * tools/ copied this from include/asm-generic/bitops.h, bit by bit as it needed
6 * some functions.
7 *
8 * For the benefit of those who are trying to port Linux to another
9 * architecture, here are some C-language equivalents. You should
10 * recode these in the native assembly language, if at all possible.
11 *
12 * C language equivalents written by Theodore Ts'o, 9/26/92
13 */
14
15#include <asm-generic/bitops/__ffs.h>
16#include <asm-generic/bitops/fls.h>
17#include <asm-generic/bitops/__fls.h>
18#include <asm-generic/bitops/fls64.h>
19#include <asm-generic/bitops/find.h>
20
21#ifndef _TOOLS_LINUX_BITOPS_H_
22#error only <linux/bitops.h> can be included directly
23#endif
24
25#include <asm-generic/bitops/atomic.h>
26
27#endif /* __TOOLS_ASM_GENERIC_BITOPS_H */
diff --git a/tools/include/asm-generic/bitops/__ffs.h b/tools/include/asm-generic/bitops/__ffs.h
new file mode 100644
index 000000000000..c94175015a82
--- /dev/null
+++ b/tools/include/asm-generic/bitops/__ffs.h
@@ -0,0 +1,43 @@
1#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
3
4#include <asm/types.h>
5
6/**
7 * __ffs - find first bit in word.
8 * @word: The word to search
9 *
10 * Undefined if no bit exists, so code should check against 0 first.
11 */
12static __always_inline unsigned long __ffs(unsigned long word)
13{
14 int num = 0;
15
16#if __BITS_PER_LONG == 64
17 if ((word & 0xffffffff) == 0) {
18 num += 32;
19 word >>= 32;
20 }
21#endif
22 if ((word & 0xffff) == 0) {
23 num += 16;
24 word >>= 16;
25 }
26 if ((word & 0xff) == 0) {
27 num += 8;
28 word >>= 8;
29 }
30 if ((word & 0xf) == 0) {
31 num += 4;
32 word >>= 4;
33 }
34 if ((word & 0x3) == 0) {
35 num += 2;
36 word >>= 2;
37 }
38 if ((word & 0x1) == 0)
39 num += 1;
40 return num;
41}
42
43#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ */
diff --git a/tools/include/asm-generic/bitops/__fls.h b/tools/include/asm-generic/bitops/__fls.h
new file mode 100644
index 000000000000..2218b9add4c1
--- /dev/null
+++ b/tools/include/asm-generic/bitops/__fls.h
@@ -0,0 +1 @@
#include <../../../../include/asm-generic/bitops/__fls.h>
diff --git a/tools/include/asm-generic/bitops/atomic.h b/tools/include/asm-generic/bitops/atomic.h
new file mode 100644
index 000000000000..4bccd7c3d5d6
--- /dev/null
+++ b/tools/include/asm-generic/bitops/atomic.h
@@ -0,0 +1,22 @@
1#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
3
4#include <asm/types.h>
5
6static inline void set_bit(int nr, unsigned long *addr)
7{
8 addr[nr / __BITS_PER_LONG] |= 1UL << (nr % __BITS_PER_LONG);
9}
10
11static inline void clear_bit(int nr, unsigned long *addr)
12{
13 addr[nr / __BITS_PER_LONG] &= ~(1UL << (nr % __BITS_PER_LONG));
14}
15
16static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
17{
18 return ((1UL << (nr % __BITS_PER_LONG)) &
19 (((unsigned long *)addr)[nr / __BITS_PER_LONG])) != 0;
20}
21
22#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ */
diff --git a/tools/include/asm-generic/bitops/find.h b/tools/include/asm-generic/bitops/find.h
new file mode 100644
index 000000000000..31f51547fcd4
--- /dev/null
+++ b/tools/include/asm-generic/bitops/find.h
@@ -0,0 +1,33 @@
1#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
3
4#ifndef find_next_bit
5/**
6 * find_next_bit - find the next set bit in a memory region
7 * @addr: The address to base the search on
8 * @offset: The bitnumber to start searching at
9 * @size: The bitmap size in bits
10 *
11 * Returns the bit number for the next set bit
12 * If no bits are set, returns @size.
13 */
14extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
15 size, unsigned long offset);
16#endif
17
18#ifndef find_first_bit
19
20/**
21 * find_first_bit - find the first set bit in a memory region
22 * @addr: The address to start the search at
23 * @size: The maximum number of bits to search
24 *
25 * Returns the bit number of the first set bit.
26 * If no bits are set, returns @size.
27 */
28extern unsigned long find_first_bit(const unsigned long *addr,
29 unsigned long size);
30
31#endif /* find_first_bit */
32
33#endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/tools/include/asm-generic/bitops/fls.h b/tools/include/asm-generic/bitops/fls.h
new file mode 100644
index 000000000000..dbf711a28f71
--- /dev/null
+++ b/tools/include/asm-generic/bitops/fls.h
@@ -0,0 +1 @@
#include <../../../../include/asm-generic/bitops/fls.h>
diff --git a/tools/include/asm-generic/bitops/fls64.h b/tools/include/asm-generic/bitops/fls64.h
new file mode 100644
index 000000000000..980b1f63c047
--- /dev/null
+++ b/tools/include/asm-generic/bitops/fls64.h
@@ -0,0 +1 @@
#include <../../../../include/asm-generic/bitops/fls64.h>
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
new file mode 100644
index 000000000000..26005a15e7e2
--- /dev/null
+++ b/tools/include/linux/bitops.h
@@ -0,0 +1,53 @@
1#ifndef _TOOLS_LINUX_BITOPS_H_
2#define _TOOLS_LINUX_BITOPS_H_
3
4#include <linux/kernel.h>
5#include <linux/compiler.h>
6#include <asm/hweight.h>
7
8#ifndef __WORDSIZE
9#define __WORDSIZE (__SIZEOF_LONG__ * 8)
10#endif
11
12#define BITS_PER_LONG __WORDSIZE
13
14#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
15#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
16#define BITS_PER_BYTE 8
17#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
18#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
19#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
20#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
21
22/*
23 * Include this here because some architectures need generic_ffs/fls in
24 * scope
25 *
26 * XXX: this needs to be asm/bitops.h, when we get to per arch optimizations
27 */
28#include <asm-generic/bitops.h>
29
30#define for_each_set_bit(bit, addr, size) \
31 for ((bit) = find_first_bit((addr), (size)); \
32 (bit) < (size); \
33 (bit) = find_next_bit((addr), (size), (bit) + 1))
34
35/* same as for_each_set_bit() but use bit as value to start with */
36#define for_each_set_bit_from(bit, addr, size) \
37 for ((bit) = find_next_bit((addr), (size), (bit)); \
38 (bit) < (size); \
39 (bit) = find_next_bit((addr), (size), (bit) + 1))
40
41static inline unsigned long hweight_long(unsigned long w)
42{
43 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
44}
45
46static inline unsigned fls_long(unsigned long l)
47{
48 if (sizeof(l) == 4)
49 return fls(l);
50 return fls64(l);
51}
52
53#endif
diff --git a/tools/include/linux/log2.h b/tools/include/linux/log2.h
new file mode 100644
index 000000000000..41446668ccce
--- /dev/null
+++ b/tools/include/linux/log2.h
@@ -0,0 +1,185 @@
1/* Integer base 2 logarithm calculation
2 *
3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#ifndef _TOOLS_LINUX_LOG2_H
13#define _TOOLS_LINUX_LOG2_H
14
15/*
16 * deal with unrepresentable constant logarithms
17 */
18extern __attribute__((const, noreturn))
19int ____ilog2_NaN(void);
20
21/*
22 * non-constant log of base 2 calculators
23 * - the arch may override these in asm/bitops.h if they can be implemented
24 * more efficiently than using fls() and fls64()
25 * - the arch is not required to handle n==0 if implementing the fallback
26 */
27static inline __attribute__((const))
28int __ilog2_u32(u32 n)
29{
30 return fls(n) - 1;
31}
32
33static inline __attribute__((const))
34int __ilog2_u64(u64 n)
35{
36 return fls64(n) - 1;
37}
38
39/*
40 * Determine whether some value is a power of two, where zero is
41 * *not* considered a power of two.
42 */
43
44static inline __attribute__((const))
45bool is_power_of_2(unsigned long n)
46{
47 return (n != 0 && ((n & (n - 1)) == 0));
48}
49
50/*
51 * round up to nearest power of two
52 */
53static inline __attribute__((const))
54unsigned long __roundup_pow_of_two(unsigned long n)
55{
56 return 1UL << fls_long(n - 1);
57}
58
59/*
60 * round down to nearest power of two
61 */
62static inline __attribute__((const))
63unsigned long __rounddown_pow_of_two(unsigned long n)
64{
65 return 1UL << (fls_long(n) - 1);
66}
67
68/**
69 * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
70 * @n - parameter
71 *
72 * constant-capable log of base 2 calculation
73 * - this can be used to initialise global variables from constant data, hence
74 * the massive ternary operator construction
75 *
76 * selects the appropriately-sized optimised version depending on sizeof(n)
77 */
78#define ilog2(n) \
79( \
80 __builtin_constant_p(n) ? ( \
81 (n) < 1 ? ____ilog2_NaN() : \
82 (n) & (1ULL << 63) ? 63 : \
83 (n) & (1ULL << 62) ? 62 : \
84 (n) & (1ULL << 61) ? 61 : \
85 (n) & (1ULL << 60) ? 60 : \
86 (n) & (1ULL << 59) ? 59 : \
87 (n) & (1ULL << 58) ? 58 : \
88 (n) & (1ULL << 57) ? 57 : \
89 (n) & (1ULL << 56) ? 56 : \
90 (n) & (1ULL << 55) ? 55 : \
91 (n) & (1ULL << 54) ? 54 : \
92 (n) & (1ULL << 53) ? 53 : \
93 (n) & (1ULL << 52) ? 52 : \
94 (n) & (1ULL << 51) ? 51 : \
95 (n) & (1ULL << 50) ? 50 : \
96 (n) & (1ULL << 49) ? 49 : \
97 (n) & (1ULL << 48) ? 48 : \
98 (n) & (1ULL << 47) ? 47 : \
99 (n) & (1ULL << 46) ? 46 : \
100 (n) & (1ULL << 45) ? 45 : \
101 (n) & (1ULL << 44) ? 44 : \
102 (n) & (1ULL << 43) ? 43 : \
103 (n) & (1ULL << 42) ? 42 : \
104 (n) & (1ULL << 41) ? 41 : \
105 (n) & (1ULL << 40) ? 40 : \
106 (n) & (1ULL << 39) ? 39 : \
107 (n) & (1ULL << 38) ? 38 : \
108 (n) & (1ULL << 37) ? 37 : \
109 (n) & (1ULL << 36) ? 36 : \
110 (n) & (1ULL << 35) ? 35 : \
111 (n) & (1ULL << 34) ? 34 : \
112 (n) & (1ULL << 33) ? 33 : \
113 (n) & (1ULL << 32) ? 32 : \
114 (n) & (1ULL << 31) ? 31 : \
115 (n) & (1ULL << 30) ? 30 : \
116 (n) & (1ULL << 29) ? 29 : \
117 (n) & (1ULL << 28) ? 28 : \
118 (n) & (1ULL << 27) ? 27 : \
119 (n) & (1ULL << 26) ? 26 : \
120 (n) & (1ULL << 25) ? 25 : \
121 (n) & (1ULL << 24) ? 24 : \
122 (n) & (1ULL << 23) ? 23 : \
123 (n) & (1ULL << 22) ? 22 : \
124 (n) & (1ULL << 21) ? 21 : \
125 (n) & (1ULL << 20) ? 20 : \
126 (n) & (1ULL << 19) ? 19 : \
127 (n) & (1ULL << 18) ? 18 : \
128 (n) & (1ULL << 17) ? 17 : \
129 (n) & (1ULL << 16) ? 16 : \
130 (n) & (1ULL << 15) ? 15 : \
131 (n) & (1ULL << 14) ? 14 : \
132 (n) & (1ULL << 13) ? 13 : \
133 (n) & (1ULL << 12) ? 12 : \
134 (n) & (1ULL << 11) ? 11 : \
135 (n) & (1ULL << 10) ? 10 : \
136 (n) & (1ULL << 9) ? 9 : \
137 (n) & (1ULL << 8) ? 8 : \
138 (n) & (1ULL << 7) ? 7 : \
139 (n) & (1ULL << 6) ? 6 : \
140 (n) & (1ULL << 5) ? 5 : \
141 (n) & (1ULL << 4) ? 4 : \
142 (n) & (1ULL << 3) ? 3 : \
143 (n) & (1ULL << 2) ? 2 : \
144 (n) & (1ULL << 1) ? 1 : \
145 (n) & (1ULL << 0) ? 0 : \
146 ____ilog2_NaN() \
147 ) : \
148 (sizeof(n) <= 4) ? \
149 __ilog2_u32(n) : \
150 __ilog2_u64(n) \
151 )
152
153/**
154 * roundup_pow_of_two - round the given value up to nearest power of two
155 * @n - parameter
156 *
157 * round the given value up to the nearest power of two
158 * - the result is undefined when n == 0
159 * - this can be used to initialise global variables from constant data
160 */
161#define roundup_pow_of_two(n) \
162( \
163 __builtin_constant_p(n) ? ( \
164 (n == 1) ? 1 : \
165 (1UL << (ilog2((n) - 1) + 1)) \
166 ) : \
167 __roundup_pow_of_two(n) \
168 )
169
170/**
171 * rounddown_pow_of_two - round the given value down to nearest power of two
172 * @n - parameter
173 *
174 * round the given value down to the nearest power of two
175 * - the result is undefined when n == 0
176 * - this can be used to initialise global variables from constant data
177 */
178#define rounddown_pow_of_two(n) \
179( \
180 __builtin_constant_p(n) ? ( \
181 (1UL << ilog2(n))) : \
182 __rounddown_pow_of_two(n) \
183 )
184
185#endif /* _TOOLS_LINUX_LOG2_H */
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index c1b49c36a951..65d9be3f9887 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -7,6 +7,10 @@
7#include <stdlib.h> 7#include <stdlib.h>
8#include <string.h> 8#include <string.h>
9#include <sys/vfs.h> 9#include <sys/vfs.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <unistd.h>
10 14
11#include "debugfs.h" 15#include "debugfs.h"
12#include "fs.h" 16#include "fs.h"
@@ -163,3 +167,33 @@ const char *name##__mountpoint(void) \
163 167
164FS__MOUNTPOINT(sysfs, FS__SYSFS); 168FS__MOUNTPOINT(sysfs, FS__SYSFS);
165FS__MOUNTPOINT(procfs, FS__PROCFS); 169FS__MOUNTPOINT(procfs, FS__PROCFS);
170
171int filename__read_int(const char *filename, int *value)
172{
173 char line[64];
174 int fd = open(filename, O_RDONLY), err = -1;
175
176 if (fd < 0)
177 return -1;
178
179 if (read(fd, line, sizeof(line)) > 0) {
180 *value = atoi(line);
181 err = 0;
182 }
183
184 close(fd);
185 return err;
186}
187
188int sysctl__read_int(const char *sysctl, int *value)
189{
190 char path[PATH_MAX];
191 const char *procfs = procfs__mountpoint();
192
193 if (!procfs)
194 return -1;
195
196 snprintf(path, sizeof(path), "%s/sys/%s", procfs, sysctl);
197
198 return filename__read_int(path, value);
199}
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index cb7049551f33..6caa2bbc6cec 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -11,4 +11,7 @@
11 11
12const char *sysfs__mountpoint(void); 12const char *sysfs__mountpoint(void);
13const char *procfs__mountpoint(void); 13const char *procfs__mountpoint(void);
14
15int filename__read_int(const char *filename, int *value);
16int sysctl__read_int(const char *sysctl, int *value);
14#endif /* __API_FS__ */ 17#endif /* __API_FS__ */
diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c
index eda326fc8620..3727de48c8d5 100644
--- a/tools/lib/traceevent/plugin_scsi.c
+++ b/tools/lib/traceevent/plugin_scsi.c
@@ -85,8 +85,9 @@ typedef unsigned int u32;
85#define MOVE_MEDIUM 0xa5 85#define MOVE_MEDIUM 0xa5
86#define EXCHANGE_MEDIUM 0xa6 86#define EXCHANGE_MEDIUM 0xa6
87#define READ_12 0xa8 87#define READ_12 0xa8
88#define SERVICE_ACTION_OUT_12 0xa9
88#define WRITE_12 0xaa 89#define WRITE_12 0xaa
89#define READ_MEDIA_SERIAL_NUMBER 0xab 90#define SERVICE_ACTION_IN_12 0xab
90#define WRITE_VERIFY_12 0xae 91#define WRITE_VERIFY_12 0xae
91#define VERIFY_12 0xaf 92#define VERIFY_12 0xaf
92#define SEARCH_HIGH_12 0xb0 93#define SEARCH_HIGH_12 0xb0
@@ -107,7 +108,9 @@ typedef unsigned int u32;
107#define VERIFY_16 0x8f 108#define VERIFY_16 0x8f
108#define SYNCHRONIZE_CACHE_16 0x91 109#define SYNCHRONIZE_CACHE_16 0x91
109#define WRITE_SAME_16 0x93 110#define WRITE_SAME_16 0x93
110#define SERVICE_ACTION_IN 0x9e 111#define SERVICE_ACTION_BIDIRECTIONAL 0x9d
112#define SERVICE_ACTION_IN_16 0x9e
113#define SERVICE_ACTION_OUT_16 0x9f
111/* values for service action in */ 114/* values for service action in */
112#define SAI_READ_CAPACITY_16 0x10 115#define SAI_READ_CAPACITY_16 0x10
113#define SAI_GET_LBA_STATUS 0x12 116#define SAI_GET_LBA_STATUS 0x12
@@ -393,7 +396,7 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
393 return scsi_trace_rw16(p, cdb, len); 396 return scsi_trace_rw16(p, cdb, len);
394 case UNMAP: 397 case UNMAP:
395 return scsi_trace_unmap(p, cdb, len); 398 return scsi_trace_unmap(p, cdb, len);
396 case SERVICE_ACTION_IN: 399 case SERVICE_ACTION_IN_16:
397 return scsi_trace_service_action_in(p, cdb, len); 400 return scsi_trace_service_action_in(p, cdb, len);
398 case VARIABLE_LENGTH_CMD: 401 case VARIABLE_LENGTH_CMD:
399 return scsi_trace_varlen(p, cdb, len); 402 return scsi_trace_varlen(p, cdb, len);
diff --git a/tools/lib/util/find_next_bit.c b/tools/lib/util/find_next_bit.c
new file mode 100644
index 000000000000..41b44f65a79e
--- /dev/null
+++ b/tools/lib/util/find_next_bit.c
@@ -0,0 +1,89 @@
1/* find_next_bit.c: fallback find next bit implementation
2 *
3 * Copied from lib/find_next_bit.c to tools/lib/next_bit.c
4 *
5 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <linux/bitops.h>
15#include <asm/types.h>
16#include <asm/byteorder.h>
17
18#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
19
20#ifndef find_next_bit
21/*
22 * Find the next set bit in a memory region.
23 */
24unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
25 unsigned long offset)
26{
27 const unsigned long *p = addr + BITOP_WORD(offset);
28 unsigned long result = offset & ~(BITS_PER_LONG-1);
29 unsigned long tmp;
30
31 if (offset >= size)
32 return size;
33 size -= result;
34 offset %= BITS_PER_LONG;
35 if (offset) {
36 tmp = *(p++);
37 tmp &= (~0UL << offset);
38 if (size < BITS_PER_LONG)
39 goto found_first;
40 if (tmp)
41 goto found_middle;
42 size -= BITS_PER_LONG;
43 result += BITS_PER_LONG;
44 }
45 while (size & ~(BITS_PER_LONG-1)) {
46 if ((tmp = *(p++)))
47 goto found_middle;
48 result += BITS_PER_LONG;
49 size -= BITS_PER_LONG;
50 }
51 if (!size)
52 return result;
53 tmp = *p;
54
55found_first:
56 tmp &= (~0UL >> (BITS_PER_LONG - size));
57 if (tmp == 0UL) /* Are any bits set? */
58 return result + size; /* Nope. */
59found_middle:
60 return result + __ffs(tmp);
61}
62#endif
63
64#ifndef find_first_bit
65/*
66 * Find the first set bit in a memory region.
67 */
68unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
69{
70 const unsigned long *p = addr;
71 unsigned long result = 0;
72 unsigned long tmp;
73
74 while (size & ~(BITS_PER_LONG-1)) {
75 if ((tmp = *(p++)))
76 goto found;
77 result += BITS_PER_LONG;
78 size -= BITS_PER_LONG;
79 }
80 if (!size)
81 return result;
82
83 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
84 if (tmp == 0UL) /* Are any bits set? */
85 return result + size; /* Nope. */
86found:
87 return result + __ffs(tmp);
88}
89#endif
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 717221e98450..40399c3d97d6 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -2,6 +2,8 @@ PERF-CFLAGS
2PERF-GUI-VARS 2PERF-GUI-VARS
3PERF-VERSION-FILE 3PERF-VERSION-FILE
4perf 4perf
5perf-read-vdso32
6perf-read-vdsox32
5perf-help 7perf-help
6perf-record 8perf-record
7perf-report 9perf-report
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 398f8d53bd6d..af9a54ece024 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -214,6 +214,12 @@ if combined with -a or -C options.
214After starting the program, wait msecs before measuring. This is useful to 214After starting the program, wait msecs before measuring. This is useful to
215filter out the startup phase of the program, which is often very different. 215filter out the startup phase of the program, which is often very different.
216 216
217-I::
218--intr-regs::
219Capture machine state (registers) at interrupt, i.e., on counter overflows for
220each sample. List of captured registers depends on the architecture. This option
221is off by default.
222
217SEE ALSO 223SEE ALSO
218-------- 224--------
219linkperf:perf-stat[1], linkperf:perf-list[1] 225linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 0927bf4e6c2a..dd7cccdde498 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -159,7 +159,7 @@ OPTIONS
159--dump-raw-trace:: 159--dump-raw-trace::
160 Dump raw trace in ASCII. 160 Dump raw trace in ASCII.
161 161
162-g [type,min[,limit],order[,key]]:: 162-g [type,min[,limit],order[,key][,branch]]::
163--call-graph:: 163--call-graph::
164 Display call chains using type, min percent threshold, optional print 164 Display call chains using type, min percent threshold, optional print
165 limit and order. 165 limit and order.
@@ -177,6 +177,11 @@ OPTIONS
177 - function: compare on functions 177 - function: compare on functions
178 - address: compare on individual code addresses 178 - address: compare on individual code addresses
179 179
180 branch can be:
181 - branch: include last branch information in callgraph
182 when available. Usually more convenient to use --branch-history
183 for this.
184
180 Default: fractal,0.5,callee,function. 185 Default: fractal,0.5,callee,function.
181 186
182--children:: 187--children::
@@ -266,6 +271,11 @@ OPTIONS
266 branch stacks and it will automatically switch to the branch view mode, 271 branch stacks and it will automatically switch to the branch view mode,
267 unless --no-branch-stack is used. 272 unless --no-branch-stack is used.
268 273
274--branch-history::
275 Add the addresses of sampled taken branches to the callstack.
276 This allows to examine the path the program took to each sample.
277 The data collection must have used -b (or -j) and -g.
278
269--objdump=<path>:: 279--objdump=<path>::
270 Path to objdump binary. 280 Path to objdump binary.
271 281
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt
index d240bb2e5b22..1e8e400b4493 100644
--- a/tools/perf/Documentation/perf.txt
+++ b/tools/perf/Documentation/perf.txt
@@ -18,6 +18,10 @@ OPTIONS
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--buildid-dir::
22 Setup buildid cache directory. It has higher priority than
23 buildid.dir config file option.
24
21DESCRIPTION 25DESCRIPTION
22----------- 26-----------
23Performance counters for Linux are a new kernel-based subsystem 27Performance counters for Linux are a new kernel-based subsystem
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 344c4d3d0a4a..83e2887f91a3 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -4,17 +4,31 @@ tools/lib/traceevent
4tools/lib/api 4tools/lib/api
5tools/lib/symbol/kallsyms.c 5tools/lib/symbol/kallsyms.c
6tools/lib/symbol/kallsyms.h 6tools/lib/symbol/kallsyms.h
7tools/lib/util/find_next_bit.c
7tools/include/asm/bug.h 8tools/include/asm/bug.h
9tools/include/asm-generic/bitops/atomic.h
10tools/include/asm-generic/bitops/__ffs.h
11tools/include/asm-generic/bitops/__fls.h
12tools/include/asm-generic/bitops/find.h
13tools/include/asm-generic/bitops/fls64.h
14tools/include/asm-generic/bitops/fls.h
15tools/include/asm-generic/bitops.h
16tools/include/linux/bitops.h
8tools/include/linux/compiler.h 17tools/include/linux/compiler.h
9tools/include/linux/hash.h
10tools/include/linux/export.h 18tools/include/linux/export.h
19tools/include/linux/hash.h
20tools/include/linux/log2.h
11tools/include/linux/types.h 21tools/include/linux/types.h
22include/asm-generic/bitops/fls64.h
23include/asm-generic/bitops/__fls.h
24include/asm-generic/bitops/fls.h
12include/linux/const.h 25include/linux/const.h
13include/linux/perf_event.h 26include/linux/perf_event.h
14include/linux/rbtree.h 27include/linux/rbtree.h
15include/linux/list.h 28include/linux/list.h
16include/linux/hash.h 29include/linux/hash.h
17include/linux/stringify.h 30include/linux/stringify.h
31lib/find_next_bit.c
18lib/rbtree.c 32lib/rbtree.c
19include/linux/swab.h 33include/linux/swab.h
20arch/*/include/asm/unistd*.h 34arch/*/include/asm/unistd*.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 262916f4a377..67a03a825b3c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -60,6 +60,15 @@ include config/utilities.mak
60# 60#
61# Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support 61# Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support
62# for dwarf backtrace post unwind. 62# for dwarf backtrace post unwind.
63#
64# Define NO_PERF_READ_VDSO32 if you do not want to build perf-read-vdso32
65# for reading the 32-bit compatibility VDSO in 64-bit mode
66#
67# Define NO_PERF_READ_VDSOX32 if you do not want to build perf-read-vdsox32
68# for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode
69#
70# Define NO_ZLIB if you do not want to support compressed kernel modules
71
63 72
64ifeq ($(srctree),) 73ifeq ($(srctree),)
65srctree := $(patsubst %/,%,$(dir $(shell pwd))) 74srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -171,11 +180,16 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
171 180
172SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 181SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
173 182
174#
175# Single 'perf' binary right now:
176#
177PROGRAMS += $(OUTPUT)perf 183PROGRAMS += $(OUTPUT)perf
178 184
185ifndef NO_PERF_READ_VDSO32
186PROGRAMS += $(OUTPUT)perf-read-vdso32
187endif
188
189ifndef NO_PERF_READ_VDSOX32
190PROGRAMS += $(OUTPUT)perf-read-vdsox32
191endif
192
179# what 'all' will build and 'install' will install, in perfexecdir 193# what 'all' will build and 'install' will install, in perfexecdir
180ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) 194ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
181 195
@@ -217,8 +231,16 @@ LIB_H += ../../include/uapi/linux/const.h
217LIB_H += ../include/linux/hash.h 231LIB_H += ../include/linux/hash.h
218LIB_H += ../../include/linux/stringify.h 232LIB_H += ../../include/linux/stringify.h
219LIB_H += util/include/linux/bitmap.h 233LIB_H += util/include/linux/bitmap.h
220LIB_H += util/include/linux/bitops.h 234LIB_H += ../include/linux/bitops.h
235LIB_H += ../include/asm-generic/bitops/atomic.h
236LIB_H += ../include/asm-generic/bitops/find.h
237LIB_H += ../include/asm-generic/bitops/fls64.h
238LIB_H += ../include/asm-generic/bitops/fls.h
239LIB_H += ../include/asm-generic/bitops/__ffs.h
240LIB_H += ../include/asm-generic/bitops/__fls.h
241LIB_H += ../include/asm-generic/bitops.h
221LIB_H += ../include/linux/compiler.h 242LIB_H += ../include/linux/compiler.h
243LIB_H += ../include/linux/log2.h
222LIB_H += util/include/linux/const.h 244LIB_H += util/include/linux/const.h
223LIB_H += util/include/linux/ctype.h 245LIB_H += util/include/linux/ctype.h
224LIB_H += util/include/linux/kernel.h 246LIB_H += util/include/linux/kernel.h
@@ -247,12 +269,14 @@ LIB_H += util/annotate.h
247LIB_H += util/cache.h 269LIB_H += util/cache.h
248LIB_H += util/callchain.h 270LIB_H += util/callchain.h
249LIB_H += util/build-id.h 271LIB_H += util/build-id.h
272LIB_H += util/db-export.h
250LIB_H += util/debug.h 273LIB_H += util/debug.h
251LIB_H += util/pmu.h 274LIB_H += util/pmu.h
252LIB_H += util/event.h 275LIB_H += util/event.h
253LIB_H += util/evsel.h 276LIB_H += util/evsel.h
254LIB_H += util/evlist.h 277LIB_H += util/evlist.h
255LIB_H += util/exec_cmd.h 278LIB_H += util/exec_cmd.h
279LIB_H += util/find-vdso-map.c
256LIB_H += util/levenshtein.h 280LIB_H += util/levenshtein.h
257LIB_H += util/machine.h 281LIB_H += util/machine.h
258LIB_H += util/map.h 282LIB_H += util/map.h
@@ -304,6 +328,7 @@ LIB_H += ui/util.h
304LIB_H += ui/ui.h 328LIB_H += ui/ui.h
305LIB_H += util/data.h 329LIB_H += util/data.h
306LIB_H += util/kvm-stat.h 330LIB_H += util/kvm-stat.h
331LIB_H += util/thread-stack.h
307 332
308LIB_OBJS += $(OUTPUT)util/abspath.o 333LIB_OBJS += $(OUTPUT)util/abspath.o
309LIB_OBJS += $(OUTPUT)util/alias.o 334LIB_OBJS += $(OUTPUT)util/alias.o
@@ -311,12 +336,14 @@ LIB_OBJS += $(OUTPUT)util/annotate.o
311LIB_OBJS += $(OUTPUT)util/build-id.o 336LIB_OBJS += $(OUTPUT)util/build-id.o
312LIB_OBJS += $(OUTPUT)util/config.o 337LIB_OBJS += $(OUTPUT)util/config.o
313LIB_OBJS += $(OUTPUT)util/ctype.o 338LIB_OBJS += $(OUTPUT)util/ctype.o
339LIB_OBJS += $(OUTPUT)util/db-export.o
314LIB_OBJS += $(OUTPUT)util/pmu.o 340LIB_OBJS += $(OUTPUT)util/pmu.o
315LIB_OBJS += $(OUTPUT)util/environment.o 341LIB_OBJS += $(OUTPUT)util/environment.o
316LIB_OBJS += $(OUTPUT)util/event.o 342LIB_OBJS += $(OUTPUT)util/event.o
317LIB_OBJS += $(OUTPUT)util/evlist.o 343LIB_OBJS += $(OUTPUT)util/evlist.o
318LIB_OBJS += $(OUTPUT)util/evsel.o 344LIB_OBJS += $(OUTPUT)util/evsel.o
319LIB_OBJS += $(OUTPUT)util/exec_cmd.o 345LIB_OBJS += $(OUTPUT)util/exec_cmd.o
346LIB_OBJS += $(OUTPUT)util/find_next_bit.o
320LIB_OBJS += $(OUTPUT)util/help.o 347LIB_OBJS += $(OUTPUT)util/help.o
321LIB_OBJS += $(OUTPUT)util/kallsyms.o 348LIB_OBJS += $(OUTPUT)util/kallsyms.o
322LIB_OBJS += $(OUTPUT)util/levenshtein.o 349LIB_OBJS += $(OUTPUT)util/levenshtein.o
@@ -380,6 +407,7 @@ LIB_OBJS += $(OUTPUT)util/srcline.o
380LIB_OBJS += $(OUTPUT)util/data.o 407LIB_OBJS += $(OUTPUT)util/data.o
381LIB_OBJS += $(OUTPUT)util/tsc.o 408LIB_OBJS += $(OUTPUT)util/tsc.o
382LIB_OBJS += $(OUTPUT)util/cloexec.o 409LIB_OBJS += $(OUTPUT)util/cloexec.o
410LIB_OBJS += $(OUTPUT)util/thread-stack.o
383 411
384LIB_OBJS += $(OUTPUT)ui/setup.o 412LIB_OBJS += $(OUTPUT)ui/setup.o
385LIB_OBJS += $(OUTPUT)ui/helpline.o 413LIB_OBJS += $(OUTPUT)ui/helpline.o
@@ -439,7 +467,6 @@ BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
439BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o 467BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
440endif 468endif
441BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 469BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
442BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
443BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o 470BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
444BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o 471BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
445BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o 472BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
@@ -478,8 +505,6 @@ ifneq ($(OUTPUT),)
478endif 505endif
479 506
480ifdef NO_LIBELF 507ifdef NO_LIBELF
481EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
482
483# Remove ELF/DWARF dependent codes 508# Remove ELF/DWARF dependent codes
484LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS)) 509LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
485LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS)) 510LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
@@ -568,6 +593,10 @@ ifndef NO_LIBNUMA
568 BUILTIN_OBJS += $(OUTPUT)bench/numa.o 593 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
569endif 594endif
570 595
596ifndef NO_ZLIB
597 LIB_OBJS += $(OUTPUT)util/zlib.o
598endif
599
571ifdef ASCIIDOC8 600ifdef ASCIIDOC8
572 export ASCIIDOC8 601 export ASCIIDOC8
573endif 602endif
@@ -714,6 +743,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
714$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 743$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
715 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 744 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
716 745
746$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS
747 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
748
717$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS 749$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
718 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< 750 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
719 751
@@ -732,6 +764,16 @@ $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Uti
732$(OUTPUT)perf-%: %.o $(PERFLIBS) 764$(OUTPUT)perf-%: %.o $(PERFLIBS)
733 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS) 765 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
734 766
767ifndef NO_PERF_READ_VDSO32
768$(OUTPUT)perf-read-vdso32: perf-read-vdso.c util/find-vdso-map.c
769 $(QUIET_CC)$(CC) -m32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
770endif
771
772ifndef NO_PERF_READ_VDSOX32
773$(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
774 $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
775endif
776
735$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) 777$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
736$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) 778$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
737 779
@@ -876,6 +918,14 @@ install-bin: all install-gtk
876 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \ 918 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
877 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \ 919 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
878 $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace' 920 $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'
921ifndef NO_PERF_READ_VDSO32
922 $(call QUIET_INSTALL, perf-read-vdso32) \
923 $(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(bindir_SQ)';
924endif
925ifndef NO_PERF_READ_VDSOX32
926 $(call QUIET_INSTALL, perf-read-vdsox32) \
927 $(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)';
928endif
879 $(call QUIET_INSTALL, libexec) \ 929 $(call QUIET_INSTALL, libexec) \
880 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 930 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
881 $(call QUIET_INSTALL, perf-archive) \ 931 $(call QUIET_INSTALL, perf-archive) \
@@ -928,7 +978,7 @@ config-clean:
928 978
929clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 979clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
930 $(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) 980 $(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)
931 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 981 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
932 $(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* 982 $(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*
933 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 983 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
934 $(python-clean) 984 $(python-clean)
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index d73ef8bb08c7..3bb50eac5542 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
145 * yet used) 145 * yet used)
146 * -1 in case of errors 146 * -1 in case of errors
147 */ 147 */
148static int check_return_addr(const char *exec_file, Dwarf_Addr pc) 148static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
149{ 149{
150 int rc = -1; 150 int rc = -1;
151 Dwfl *dwfl; 151 Dwfl *dwfl;
@@ -156,15 +156,27 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
156 Dwarf_Addr end = pc; 156 Dwarf_Addr end = pc;
157 bool signalp; 157 bool signalp;
158 158
159 dwfl = dwfl_begin(&offline_callbacks); 159 dwfl = dso->dwfl;
160 if (!dwfl) {
161 pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
162 return -1;
163 }
164 160
165 if (dwfl_report_offline(dwfl, "", exec_file, -1) == NULL) { 161 if (!dwfl) {
166 pr_debug("dwfl_report_offline() failed %s\n", dwarf_errmsg(-1)); 162 dwfl = dwfl_begin(&offline_callbacks);
167 goto out; 163 if (!dwfl) {
164 pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
165 return -1;
166 }
167
168 if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) {
169 pr_debug("dwfl_report_offline() failed %s\n",
170 dwarf_errmsg(-1));
171 /*
172 * We normally cache the DWARF debug info and never
173 * call dwfl_end(). But to prevent fd leak, free in
174 * case of error.
175 */
176 dwfl_end(dwfl);
177 goto out;
178 }
179 dso->dwfl = dwfl;
168 } 180 }
169 181
170 mod = dwfl_addrmodule(dwfl, pc); 182 mod = dwfl_addrmodule(dwfl, pc);
@@ -194,7 +206,6 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
194 rc = check_return_reg(ra_regno, frame); 206 rc = check_return_reg(ra_regno, frame);
195 207
196out: 208out:
197 dwfl_end(dwfl);
198 return rc; 209 return rc;
199} 210}
200 211
@@ -221,8 +232,7 @@ out:
221 * index: of callchain entry that needs to be ignored (if any) 232 * index: of callchain entry that needs to be ignored (if any)
222 * -1 if no entry needs to be ignored or in case of errors 233 * -1 if no entry needs to be ignored or in case of errors
223 */ 234 */
224int arch_skip_callchain_idx(struct machine *machine, struct thread *thread, 235int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
225 struct ip_callchain *chain)
226{ 236{
227 struct addr_location al; 237 struct addr_location al;
228 struct dso *dso = NULL; 238 struct dso *dso = NULL;
@@ -235,7 +245,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread,
235 245
236 ip = chain->ips[2]; 246 ip = chain->ips[2];
237 247
238 thread__find_addr_location(thread, machine, PERF_RECORD_MISC_USER, 248 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
239 MAP__FUNCTION, ip, &al); 249 MAP__FUNCTION, ip, &al);
240 250
241 if (al.map) 251 if (al.map)
@@ -246,7 +256,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread,
246 return skip_slot; 256 return skip_slot;
247 } 257 }
248 258
249 rc = check_return_addr(dso->long_name, ip); 259 rc = check_return_addr(dso, ip);
250 260
251 pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n", 261 pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n",
252 dso->long_name, chain->nr, ip, rc); 262 dso->long_name, chain->nr, ip, rc);
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 2465141b554b..6c14afe8c1b1 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -13,6 +13,7 @@
13#include "../util/cloexec.h" 13#include "../util/cloexec.h"
14#include "bench.h" 14#include "bench.h"
15#include "mem-memcpy-arch.h" 15#include "mem-memcpy-arch.h"
16#include "mem-memset-arch.h"
16 17
17#include <stdio.h> 18#include <stdio.h>
18#include <stdlib.h> 19#include <stdlib.h>
@@ -48,20 +49,24 @@ static const struct option options[] = {
48}; 49};
49 50
50typedef void *(*memcpy_t)(void *, const void *, size_t); 51typedef void *(*memcpy_t)(void *, const void *, size_t);
52typedef void *(*memset_t)(void *, int, size_t);
51 53
52struct routine { 54struct routine {
53 const char *name; 55 const char *name;
54 const char *desc; 56 const char *desc;
55 memcpy_t fn; 57 union {
58 memcpy_t memcpy;
59 memset_t memset;
60 } fn;
56}; 61};
57 62
58struct routine routines[] = { 63struct routine memcpy_routines[] = {
59 { "default", 64 { .name = "default",
60 "Default memcpy() provided by glibc", 65 .desc = "Default memcpy() provided by glibc",
61 memcpy }, 66 .fn.memcpy = memcpy },
62#ifdef HAVE_ARCH_X86_64_SUPPORT 67#ifdef HAVE_ARCH_X86_64_SUPPORT
63 68
64#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, 69#define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn},
65#include "mem-memcpy-x86-64-asm-def.h" 70#include "mem-memcpy-x86-64-asm-def.h"
66#undef MEMCPY_FN 71#undef MEMCPY_FN
67 72
@@ -69,7 +74,7 @@ struct routine routines[] = {
69 74
70 { NULL, 75 { NULL,
71 NULL, 76 NULL,
72 NULL } 77 {NULL} }
73}; 78};
74 79
75static const char * const bench_mem_memcpy_usage[] = { 80static const char * const bench_mem_memcpy_usage[] = {
@@ -110,63 +115,6 @@ static double timeval2double(struct timeval *ts)
110 (double)ts->tv_usec / (double)1000000; 115 (double)ts->tv_usec / (double)1000000;
111} 116}
112 117
113static void alloc_mem(void **dst, void **src, size_t length)
114{
115 *dst = zalloc(length);
116 if (!*dst)
117 die("memory allocation failed - maybe length is too large?\n");
118
119 *src = zalloc(length);
120 if (!*src)
121 die("memory allocation failed - maybe length is too large?\n");
122 /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */
123 memset(*src, 0, length);
124}
125
126static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
127{
128 u64 cycle_start = 0ULL, cycle_end = 0ULL;
129 void *src = NULL, *dst = NULL;
130 int i;
131
132 alloc_mem(&src, &dst, len);
133
134 if (prefault)
135 fn(dst, src, len);
136
137 cycle_start = get_cycle();
138 for (i = 0; i < iterations; ++i)
139 fn(dst, src, len);
140 cycle_end = get_cycle();
141
142 free(src);
143 free(dst);
144 return cycle_end - cycle_start;
145}
146
147static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
148{
149 struct timeval tv_start, tv_end, tv_diff;
150 void *src = NULL, *dst = NULL;
151 int i;
152
153 alloc_mem(&src, &dst, len);
154
155 if (prefault)
156 fn(dst, src, len);
157
158 BUG_ON(gettimeofday(&tv_start, NULL));
159 for (i = 0; i < iterations; ++i)
160 fn(dst, src, len);
161 BUG_ON(gettimeofday(&tv_end, NULL));
162
163 timersub(&tv_end, &tv_start, &tv_diff);
164
165 free(src);
166 free(dst);
167 return (double)((double)len / timeval2double(&tv_diff));
168}
169
170#define pf (no_prefault ? 0 : 1) 118#define pf (no_prefault ? 0 : 1)
171 119
172#define print_bps(x) do { \ 120#define print_bps(x) do { \
@@ -180,16 +128,25 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
180 printf(" %14lf GB/Sec", x / K / K / K); \ 128 printf(" %14lf GB/Sec", x / K / K / K); \
181 } while (0) 129 } while (0)
182 130
183int bench_mem_memcpy(int argc, const char **argv, 131struct bench_mem_info {
184 const char *prefix __maybe_unused) 132 const struct routine *routines;
133 u64 (*do_cycle)(const struct routine *r, size_t len, bool prefault);
134 double (*do_gettimeofday)(const struct routine *r, size_t len, bool prefault);
135 const char *const *usage;
136};
137
138static int bench_mem_common(int argc, const char **argv,
139 const char *prefix __maybe_unused,
140 struct bench_mem_info *info)
185{ 141{
186 int i; 142 int i;
187 size_t len; 143 size_t len;
144 double totallen;
188 double result_bps[2]; 145 double result_bps[2];
189 u64 result_cycle[2]; 146 u64 result_cycle[2];
190 147
191 argc = parse_options(argc, argv, options, 148 argc = parse_options(argc, argv, options,
192 bench_mem_memcpy_usage, 0); 149 info->usage, 0);
193 150
194 if (no_prefault && only_prefault) { 151 if (no_prefault && only_prefault) {
195 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); 152 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
@@ -200,6 +157,7 @@ int bench_mem_memcpy(int argc, const char **argv,
200 init_cycle(); 157 init_cycle();
201 158
202 len = (size_t)perf_atoll((char *)length_str); 159 len = (size_t)perf_atoll((char *)length_str);
160 totallen = (double)len * iterations;
203 161
204 result_cycle[0] = result_cycle[1] = 0ULL; 162 result_cycle[0] = result_cycle[1] = 0ULL;
205 result_bps[0] = result_bps[1] = 0.0; 163 result_bps[0] = result_bps[1] = 0.0;
@@ -213,16 +171,16 @@ int bench_mem_memcpy(int argc, const char **argv,
213 if (only_prefault && no_prefault) 171 if (only_prefault && no_prefault)
214 only_prefault = no_prefault = false; 172 only_prefault = no_prefault = false;
215 173
216 for (i = 0; routines[i].name; i++) { 174 for (i = 0; info->routines[i].name; i++) {
217 if (!strcmp(routines[i].name, routine)) 175 if (!strcmp(info->routines[i].name, routine))
218 break; 176 break;
219 } 177 }
220 if (!routines[i].name) { 178 if (!info->routines[i].name) {
221 printf("Unknown routine:%s\n", routine); 179 printf("Unknown routine:%s\n", routine);
222 printf("Available routines...\n"); 180 printf("Available routines...\n");
223 for (i = 0; routines[i].name; i++) { 181 for (i = 0; info->routines[i].name; i++) {
224 printf("\t%s ... %s\n", 182 printf("\t%s ... %s\n",
225 routines[i].name, routines[i].desc); 183 info->routines[i].name, info->routines[i].desc);
226 } 184 }
227 return 1; 185 return 1;
228 } 186 }
@@ -234,25 +192,25 @@ int bench_mem_memcpy(int argc, const char **argv,
234 /* show both of results */ 192 /* show both of results */
235 if (use_cycle) { 193 if (use_cycle) {
236 result_cycle[0] = 194 result_cycle[0] =
237 do_memcpy_cycle(routines[i].fn, len, false); 195 info->do_cycle(&info->routines[i], len, false);
238 result_cycle[1] = 196 result_cycle[1] =
239 do_memcpy_cycle(routines[i].fn, len, true); 197 info->do_cycle(&info->routines[i], len, true);
240 } else { 198 } else {
241 result_bps[0] = 199 result_bps[0] =
242 do_memcpy_gettimeofday(routines[i].fn, 200 info->do_gettimeofday(&info->routines[i],
243 len, false); 201 len, false);
244 result_bps[1] = 202 result_bps[1] =
245 do_memcpy_gettimeofday(routines[i].fn, 203 info->do_gettimeofday(&info->routines[i],
246 len, true); 204 len, true);
247 } 205 }
248 } else { 206 } else {
249 if (use_cycle) { 207 if (use_cycle) {
250 result_cycle[pf] = 208 result_cycle[pf] =
251 do_memcpy_cycle(routines[i].fn, 209 info->do_cycle(&info->routines[i],
252 len, only_prefault); 210 len, only_prefault);
253 } else { 211 } else {
254 result_bps[pf] = 212 result_bps[pf] =
255 do_memcpy_gettimeofday(routines[i].fn, 213 info->do_gettimeofday(&info->routines[i],
256 len, only_prefault); 214 len, only_prefault);
257 } 215 }
258 } 216 }
@@ -263,10 +221,10 @@ int bench_mem_memcpy(int argc, const char **argv,
263 if (use_cycle) { 221 if (use_cycle) {
264 printf(" %14lf Cycle/Byte\n", 222 printf(" %14lf Cycle/Byte\n",
265 (double)result_cycle[0] 223 (double)result_cycle[0]
266 / (double)len); 224 / totallen);
267 printf(" %14lf Cycle/Byte (with prefault)\n", 225 printf(" %14lf Cycle/Byte (with prefault)\n",
268 (double)result_cycle[1] 226 (double)result_cycle[1]
269 / (double)len); 227 / totallen);
270 } else { 228 } else {
271 print_bps(result_bps[0]); 229 print_bps(result_bps[0]);
272 printf("\n"); 230 printf("\n");
@@ -277,7 +235,7 @@ int bench_mem_memcpy(int argc, const char **argv,
277 if (use_cycle) { 235 if (use_cycle) {
278 printf(" %14lf Cycle/Byte", 236 printf(" %14lf Cycle/Byte",
279 (double)result_cycle[pf] 237 (double)result_cycle[pf]
280 / (double)len); 238 / totallen);
281 } else 239 } else
282 print_bps(result_bps[pf]); 240 print_bps(result_bps[pf]);
283 241
@@ -288,8 +246,8 @@ int bench_mem_memcpy(int argc, const char **argv,
288 if (!only_prefault && !no_prefault) { 246 if (!only_prefault && !no_prefault) {
289 if (use_cycle) { 247 if (use_cycle) {
290 printf("%lf %lf\n", 248 printf("%lf %lf\n",
291 (double)result_cycle[0] / (double)len, 249 (double)result_cycle[0] / totallen,
292 (double)result_cycle[1] / (double)len); 250 (double)result_cycle[1] / totallen);
293 } else { 251 } else {
294 printf("%lf %lf\n", 252 printf("%lf %lf\n",
295 result_bps[0], result_bps[1]); 253 result_bps[0], result_bps[1]);
@@ -297,7 +255,7 @@ int bench_mem_memcpy(int argc, const char **argv,
297 } else { 255 } else {
298 if (use_cycle) { 256 if (use_cycle) {
299 printf("%lf\n", (double)result_cycle[pf] 257 printf("%lf\n", (double)result_cycle[pf]
300 / (double)len); 258 / totallen);
301 } else 259 } else
302 printf("%lf\n", result_bps[pf]); 260 printf("%lf\n", result_bps[pf]);
303 } 261 }
@@ -310,3 +268,163 @@ int bench_mem_memcpy(int argc, const char **argv,
310 268
311 return 0; 269 return 0;
312} 270}
271
272static void memcpy_alloc_mem(void **dst, void **src, size_t length)
273{
274 *dst = zalloc(length);
275 if (!*dst)
276 die("memory allocation failed - maybe length is too large?\n");
277
278 *src = zalloc(length);
279 if (!*src)
280 die("memory allocation failed - maybe length is too large?\n");
281 /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */
282 memset(*src, 0, length);
283}
284
285static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault)
286{
287 u64 cycle_start = 0ULL, cycle_end = 0ULL;
288 void *src = NULL, *dst = NULL;
289 memcpy_t fn = r->fn.memcpy;
290 int i;
291
292 memcpy_alloc_mem(&src, &dst, len);
293
294 if (prefault)
295 fn(dst, src, len);
296
297 cycle_start = get_cycle();
298 for (i = 0; i < iterations; ++i)
299 fn(dst, src, len);
300 cycle_end = get_cycle();
301
302 free(src);
303 free(dst);
304 return cycle_end - cycle_start;
305}
306
307static double do_memcpy_gettimeofday(const struct routine *r, size_t len,
308 bool prefault)
309{
310 struct timeval tv_start, tv_end, tv_diff;
311 memcpy_t fn = r->fn.memcpy;
312 void *src = NULL, *dst = NULL;
313 int i;
314
315 memcpy_alloc_mem(&src, &dst, len);
316
317 if (prefault)
318 fn(dst, src, len);
319
320 BUG_ON(gettimeofday(&tv_start, NULL));
321 for (i = 0; i < iterations; ++i)
322 fn(dst, src, len);
323 BUG_ON(gettimeofday(&tv_end, NULL));
324
325 timersub(&tv_end, &tv_start, &tv_diff);
326
327 free(src);
328 free(dst);
329 return (double)(((double)len * iterations) / timeval2double(&tv_diff));
330}
331
332int bench_mem_memcpy(int argc, const char **argv,
333 const char *prefix __maybe_unused)
334{
335 struct bench_mem_info info = {
336 .routines = memcpy_routines,
337 .do_cycle = do_memcpy_cycle,
338 .do_gettimeofday = do_memcpy_gettimeofday,
339 .usage = bench_mem_memcpy_usage,
340 };
341
342 return bench_mem_common(argc, argv, prefix, &info);
343}
344
345static void memset_alloc_mem(void **dst, size_t length)
346{
347 *dst = zalloc(length);
348 if (!*dst)
349 die("memory allocation failed - maybe length is too large?\n");
350}
351
352static u64 do_memset_cycle(const struct routine *r, size_t len, bool prefault)
353{
354 u64 cycle_start = 0ULL, cycle_end = 0ULL;
355 memset_t fn = r->fn.memset;
356 void *dst = NULL;
357 int i;
358
359 memset_alloc_mem(&dst, len);
360
361 if (prefault)
362 fn(dst, -1, len);
363
364 cycle_start = get_cycle();
365 for (i = 0; i < iterations; ++i)
366 fn(dst, i, len);
367 cycle_end = get_cycle();
368
369 free(dst);
370 return cycle_end - cycle_start;
371}
372
373static double do_memset_gettimeofday(const struct routine *r, size_t len,
374 bool prefault)
375{
376 struct timeval tv_start, tv_end, tv_diff;
377 memset_t fn = r->fn.memset;
378 void *dst = NULL;
379 int i;
380
381 memset_alloc_mem(&dst, len);
382
383 if (prefault)
384 fn(dst, -1, len);
385
386 BUG_ON(gettimeofday(&tv_start, NULL));
387 for (i = 0; i < iterations; ++i)
388 fn(dst, i, len);
389 BUG_ON(gettimeofday(&tv_end, NULL));
390
391 timersub(&tv_end, &tv_start, &tv_diff);
392
393 free(dst);
394 return (double)(((double)len * iterations) / timeval2double(&tv_diff));
395}
396
397static const char * const bench_mem_memset_usage[] = {
398 "perf bench mem memset <options>",
399 NULL
400};
401
402static const struct routine memset_routines[] = {
403 { .name ="default",
404 .desc = "Default memset() provided by glibc",
405 .fn.memset = memset },
406#ifdef HAVE_ARCH_X86_64_SUPPORT
407
408#define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn },
409#include "mem-memset-x86-64-asm-def.h"
410#undef MEMSET_FN
411
412#endif
413
414 { .name = NULL,
415 .desc = NULL,
416 .fn.memset = NULL }
417};
418
419int bench_mem_memset(int argc, const char **argv,
420 const char *prefix __maybe_unused)
421{
422 struct bench_mem_info info = {
423 .routines = memset_routines,
424 .do_cycle = do_memset_cycle,
425 .do_gettimeofday = do_memset_gettimeofday,
426 .usage = bench_mem_memset_usage,
427 };
428
429 return bench_mem_common(argc, argv, prefix, &info);
430}
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
deleted file mode 100644
index 75fc3e65fb2a..000000000000
--- a/tools/perf/bench/mem-memset.c
+++ /dev/null
@@ -1,304 +0,0 @@
1/*
2 * mem-memset.c
3 *
4 * memset: Simple memory set in various ways
5 *
6 * Trivial clone of mem-memcpy.c.
7 */
8
9#include "../perf.h"
10#include "../util/util.h"
11#include "../util/parse-options.h"
12#include "../util/header.h"
13#include "../util/cloexec.h"
14#include "bench.h"
15#include "mem-memset-arch.h"
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/time.h>
21#include <errno.h>
22
23#define K 1024
24
25static const char *length_str = "1MB";
26static const char *routine = "default";
27static int iterations = 1;
28static bool use_cycle;
29static int cycle_fd;
30static bool only_prefault;
31static bool no_prefault;
32
33static const struct option options[] = {
34 OPT_STRING('l', "length", &length_str, "1MB",
35 "Specify length of memory to set. "
36 "Available units: B, KB, MB, GB and TB (upper and lower)"),
37 OPT_STRING('r', "routine", &routine, "default",
38 "Specify routine to set"),
39 OPT_INTEGER('i', "iterations", &iterations,
40 "repeat memset() invocation this number of times"),
41 OPT_BOOLEAN('c', "cycle", &use_cycle,
42 "Use cycles event instead of gettimeofday() for measuring"),
43 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
44 "Show only the result with page faults before memset()"),
45 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
46 "Show only the result without page faults before memset()"),
47 OPT_END()
48};
49
50typedef void *(*memset_t)(void *, int, size_t);
51
52struct routine {
53 const char *name;
54 const char *desc;
55 memset_t fn;
56};
57
58static const struct routine routines[] = {
59 { "default",
60 "Default memset() provided by glibc",
61 memset },
62#ifdef HAVE_ARCH_X86_64_SUPPORT
63
64#define MEMSET_FN(fn, name, desc) { name, desc, fn },
65#include "mem-memset-x86-64-asm-def.h"
66#undef MEMSET_FN
67
68#endif
69
70 { NULL,
71 NULL,
72 NULL }
73};
74
75static const char * const bench_mem_memset_usage[] = {
76 "perf bench mem memset <options>",
77 NULL
78};
79
80static struct perf_event_attr cycle_attr = {
81 .type = PERF_TYPE_HARDWARE,
82 .config = PERF_COUNT_HW_CPU_CYCLES
83};
84
85static void init_cycle(void)
86{
87 cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
88 perf_event_open_cloexec_flag());
89
90 if (cycle_fd < 0 && errno == ENOSYS)
91 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
92 else
93 BUG_ON(cycle_fd < 0);
94}
95
96static u64 get_cycle(void)
97{
98 int ret;
99 u64 clk;
100
101 ret = read(cycle_fd, &clk, sizeof(u64));
102 BUG_ON(ret != sizeof(u64));
103
104 return clk;
105}
106
107static double timeval2double(struct timeval *ts)
108{
109 return (double)ts->tv_sec +
110 (double)ts->tv_usec / (double)1000000;
111}
112
113static void alloc_mem(void **dst, size_t length)
114{
115 *dst = zalloc(length);
116 if (!*dst)
117 die("memory allocation failed - maybe length is too large?\n");
118}
119
120static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault)
121{
122 u64 cycle_start = 0ULL, cycle_end = 0ULL;
123 void *dst = NULL;
124 int i;
125
126 alloc_mem(&dst, len);
127
128 if (prefault)
129 fn(dst, -1, len);
130
131 cycle_start = get_cycle();
132 for (i = 0; i < iterations; ++i)
133 fn(dst, i, len);
134 cycle_end = get_cycle();
135
136 free(dst);
137 return cycle_end - cycle_start;
138}
139
140static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
141{
142 struct timeval tv_start, tv_end, tv_diff;
143 void *dst = NULL;
144 int i;
145
146 alloc_mem(&dst, len);
147
148 if (prefault)
149 fn(dst, -1, len);
150
151 BUG_ON(gettimeofday(&tv_start, NULL));
152 for (i = 0; i < iterations; ++i)
153 fn(dst, i, len);
154 BUG_ON(gettimeofday(&tv_end, NULL));
155
156 timersub(&tv_end, &tv_start, &tv_diff);
157
158 free(dst);
159 return (double)((double)len / timeval2double(&tv_diff));
160}
161
162#define pf (no_prefault ? 0 : 1)
163
164#define print_bps(x) do { \
165 if (x < K) \
166 printf(" %14lf B/Sec", x); \
167 else if (x < K * K) \
168 printf(" %14lfd KB/Sec", x / K); \
169 else if (x < K * K * K) \
170 printf(" %14lf MB/Sec", x / K / K); \
171 else \
172 printf(" %14lf GB/Sec", x / K / K / K); \
173 } while (0)
174
175int bench_mem_memset(int argc, const char **argv,
176 const char *prefix __maybe_unused)
177{
178 int i;
179 size_t len;
180 double result_bps[2];
181 u64 result_cycle[2];
182
183 argc = parse_options(argc, argv, options,
184 bench_mem_memset_usage, 0);
185
186 if (no_prefault && only_prefault) {
187 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
188 return 1;
189 }
190
191 if (use_cycle)
192 init_cycle();
193
194 len = (size_t)perf_atoll((char *)length_str);
195
196 result_cycle[0] = result_cycle[1] = 0ULL;
197 result_bps[0] = result_bps[1] = 0.0;
198
199 if ((s64)len <= 0) {
200 fprintf(stderr, "Invalid length:%s\n", length_str);
201 return 1;
202 }
203
204 /* same to without specifying either of prefault and no-prefault */
205 if (only_prefault && no_prefault)
206 only_prefault = no_prefault = false;
207
208 for (i = 0; routines[i].name; i++) {
209 if (!strcmp(routines[i].name, routine))
210 break;
211 }
212 if (!routines[i].name) {
213 printf("Unknown routine:%s\n", routine);
214 printf("Available routines...\n");
215 for (i = 0; routines[i].name; i++) {
216 printf("\t%s ... %s\n",
217 routines[i].name, routines[i].desc);
218 }
219 return 1;
220 }
221
222 if (bench_format == BENCH_FORMAT_DEFAULT)
223 printf("# Copying %s Bytes ...\n\n", length_str);
224
225 if (!only_prefault && !no_prefault) {
226 /* show both of results */
227 if (use_cycle) {
228 result_cycle[0] =
229 do_memset_cycle(routines[i].fn, len, false);
230 result_cycle[1] =
231 do_memset_cycle(routines[i].fn, len, true);
232 } else {
233 result_bps[0] =
234 do_memset_gettimeofday(routines[i].fn,
235 len, false);
236 result_bps[1] =
237 do_memset_gettimeofday(routines[i].fn,
238 len, true);
239 }
240 } else {
241 if (use_cycle) {
242 result_cycle[pf] =
243 do_memset_cycle(routines[i].fn,
244 len, only_prefault);
245 } else {
246 result_bps[pf] =
247 do_memset_gettimeofday(routines[i].fn,
248 len, only_prefault);
249 }
250 }
251
252 switch (bench_format) {
253 case BENCH_FORMAT_DEFAULT:
254 if (!only_prefault && !no_prefault) {
255 if (use_cycle) {
256 printf(" %14lf Cycle/Byte\n",
257 (double)result_cycle[0]
258 / (double)len);
259 printf(" %14lf Cycle/Byte (with prefault)\n ",
260 (double)result_cycle[1]
261 / (double)len);
262 } else {
263 print_bps(result_bps[0]);
264 printf("\n");
265 print_bps(result_bps[1]);
266 printf(" (with prefault)\n");
267 }
268 } else {
269 if (use_cycle) {
270 printf(" %14lf Cycle/Byte",
271 (double)result_cycle[pf]
272 / (double)len);
273 } else
274 print_bps(result_bps[pf]);
275
276 printf("%s\n", only_prefault ? " (with prefault)" : "");
277 }
278 break;
279 case BENCH_FORMAT_SIMPLE:
280 if (!only_prefault && !no_prefault) {
281 if (use_cycle) {
282 printf("%lf %lf\n",
283 (double)result_cycle[0] / (double)len,
284 (double)result_cycle[1] / (double)len);
285 } else {
286 printf("%lf %lf\n",
287 result_bps[0], result_bps[1]);
288 }
289 } else {
290 if (use_cycle) {
291 printf("%lf\n", (double)result_cycle[pf]
292 / (double)len);
293 } else
294 printf("%lf\n", result_bps[pf]);
295 }
296 break;
297 default:
298 /* reaching this means there's some disaster: */
299 die("unknown format: %d\n", bench_format);
300 break;
301 }
302
303 return 0;
304}
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 70385756da63..77d5cae54c6a 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -285,12 +285,11 @@ int cmd_buildid_cache(int argc, const char **argv,
285 struct str_node *pos; 285 struct str_node *pos;
286 int ret = 0; 286 int ret = 0;
287 bool force = false; 287 bool force = false;
288 char debugdir[PATH_MAX];
289 char const *add_name_list_str = NULL, 288 char const *add_name_list_str = NULL,
290 *remove_name_list_str = NULL, 289 *remove_name_list_str = NULL,
291 *missing_filename = NULL, 290 *missing_filename = NULL,
292 *update_name_list_str = NULL, 291 *update_name_list_str = NULL,
293 *kcore_filename; 292 *kcore_filename = NULL;
294 char sbuf[STRERR_BUFSIZE]; 293 char sbuf[STRERR_BUFSIZE];
295 294
296 struct perf_data_file file = { 295 struct perf_data_file file = {
@@ -335,13 +334,11 @@ int cmd_buildid_cache(int argc, const char **argv,
335 334
336 setup_pager(); 335 setup_pager();
337 336
338 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
339
340 if (add_name_list_str) { 337 if (add_name_list_str) {
341 list = strlist__new(true, add_name_list_str); 338 list = strlist__new(true, add_name_list_str);
342 if (list) { 339 if (list) {
343 strlist__for_each(pos, list) 340 strlist__for_each(pos, list)
344 if (build_id_cache__add_file(pos->s, debugdir)) { 341 if (build_id_cache__add_file(pos->s, buildid_dir)) {
345 if (errno == EEXIST) { 342 if (errno == EEXIST) {
346 pr_debug("%s already in the cache\n", 343 pr_debug("%s already in the cache\n",
347 pos->s); 344 pos->s);
@@ -359,7 +356,7 @@ int cmd_buildid_cache(int argc, const char **argv,
359 list = strlist__new(true, remove_name_list_str); 356 list = strlist__new(true, remove_name_list_str);
360 if (list) { 357 if (list) {
361 strlist__for_each(pos, list) 358 strlist__for_each(pos, list)
362 if (build_id_cache__remove_file(pos->s, debugdir)) { 359 if (build_id_cache__remove_file(pos->s, buildid_dir)) {
363 if (errno == ENOENT) { 360 if (errno == ENOENT) {
364 pr_debug("%s wasn't in the cache\n", 361 pr_debug("%s wasn't in the cache\n",
365 pos->s); 362 pos->s);
@@ -380,7 +377,7 @@ int cmd_buildid_cache(int argc, const char **argv,
380 list = strlist__new(true, update_name_list_str); 377 list = strlist__new(true, update_name_list_str);
381 if (list) { 378 if (list) {
382 strlist__for_each(pos, list) 379 strlist__for_each(pos, list)
383 if (build_id_cache__update_file(pos->s, debugdir)) { 380 if (build_id_cache__update_file(pos->s, buildid_dir)) {
384 if (errno == ENOENT) { 381 if (errno == ENOENT) {
385 pr_debug("%s wasn't in the cache\n", 382 pr_debug("%s wasn't in the cache\n",
386 pos->s); 383 pos->s);
@@ -395,7 +392,7 @@ int cmd_buildid_cache(int argc, const char **argv,
395 } 392 }
396 393
397 if (kcore_filename && 394 if (kcore_filename &&
398 build_id_cache__add_kcore(kcore_filename, debugdir, force)) 395 build_id_cache__add_kcore(kcore_filename, buildid_dir, force))
399 pr_warning("Couldn't add %s\n", kcore_filename); 396 pr_warning("Couldn't add %s\n", kcore_filename);
400 397
401out: 398out:
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 25114c9a6801..1ce425d101a9 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -357,6 +357,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
357static struct perf_tool tool = { 357static struct perf_tool tool = {
358 .sample = diff__process_sample_event, 358 .sample = diff__process_sample_event,
359 .mmap = perf_event__process_mmap, 359 .mmap = perf_event__process_mmap,
360 .mmap2 = perf_event__process_mmap2,
360 .comm = perf_event__process_comm, 361 .comm = perf_event__process_comm,
361 .exit = perf_event__process_exit, 362 .exit = perf_event__process_exit,
362 .fork = perf_event__process_fork, 363 .fork = perf_event__process_fork,
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index de99ca1bb942..84df2deed988 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -217,8 +217,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
217 goto repipe; 217 goto repipe;
218 } 218 }
219 219
220 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 220 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al);
221 sample->ip, &al);
222 221
223 if (al.map != NULL) { 222 if (al.map != NULL) {
224 if (!al.map->dso->hit) { 223 if (!al.map->dso->hit) {
@@ -410,6 +409,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
410 .tracing_data = perf_event__repipe_op2_synth, 409 .tracing_data = perf_event__repipe_op2_synth,
411 .finished_round = perf_event__repipe_op2_synth, 410 .finished_round = perf_event__repipe_op2_synth,
412 .build_id = perf_event__repipe_op2_synth, 411 .build_id = perf_event__repipe_op2_synth,
412 .id_index = perf_event__repipe_op2_synth,
413 }, 413 },
414 .input_name = "-", 414 .input_name = "-",
415 .samples = LIST_HEAD_INIT(inject.samples), 415 .samples = LIST_HEAD_INIT(inject.samples),
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index b65eb0507b38..0894a817f67e 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1132,6 +1132,10 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1132 "-m", "1024", 1132 "-m", "1024",
1133 "-c", "1", 1133 "-c", "1",
1134 }; 1134 };
1135 const char * const kvm_stat_record_usage[] = {
1136 "perf kvm stat record [<options>]",
1137 NULL
1138 };
1135 const char * const *events_tp; 1139 const char * const *events_tp;
1136 events_tp_size = 0; 1140 events_tp_size = 0;
1137 1141
@@ -1159,6 +1163,27 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1159 for (j = 1; j < (unsigned int)argc; j++, i++) 1163 for (j = 1; j < (unsigned int)argc; j++, i++)
1160 rec_argv[i] = argv[j]; 1164 rec_argv[i] = argv[j];
1161 1165
1166 set_option_flag(record_options, 'e', "event", PARSE_OPT_HIDDEN);
1167 set_option_flag(record_options, 0, "filter", PARSE_OPT_HIDDEN);
1168 set_option_flag(record_options, 'R', "raw-samples", PARSE_OPT_HIDDEN);
1169
1170 set_option_flag(record_options, 'F', "freq", PARSE_OPT_DISABLED);
1171 set_option_flag(record_options, 0, "group", PARSE_OPT_DISABLED);
1172 set_option_flag(record_options, 'g', NULL, PARSE_OPT_DISABLED);
1173 set_option_flag(record_options, 0, "call-graph", PARSE_OPT_DISABLED);
1174 set_option_flag(record_options, 'd', "data", PARSE_OPT_DISABLED);
1175 set_option_flag(record_options, 'T', "timestamp", PARSE_OPT_DISABLED);
1176 set_option_flag(record_options, 'P', "period", PARSE_OPT_DISABLED);
1177 set_option_flag(record_options, 'n', "no-samples", PARSE_OPT_DISABLED);
1178 set_option_flag(record_options, 'N', "no-buildid-cache", PARSE_OPT_DISABLED);
1179 set_option_flag(record_options, 'B', "no-buildid", PARSE_OPT_DISABLED);
1180 set_option_flag(record_options, 'G', "cgroup", PARSE_OPT_DISABLED);
1181 set_option_flag(record_options, 'b', "branch-any", PARSE_OPT_DISABLED);
1182 set_option_flag(record_options, 'j', "branch-filter", PARSE_OPT_DISABLED);
1183 set_option_flag(record_options, 'W', "weight", PARSE_OPT_DISABLED);
1184 set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
1185
1186 record_usage = kvm_stat_record_usage;
1162 return cmd_record(i, rec_argv, NULL); 1187 return cmd_record(i, rec_argv, NULL);
1163} 1188}
1164 1189
@@ -1268,7 +1293,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1268 OPT_UINTEGER('d', "display", &kvm->display_time, 1293 OPT_UINTEGER('d', "display", &kvm->display_time,
1269 "time in seconds between display updates"), 1294 "time in seconds between display updates"),
1270 OPT_STRING(0, "event", &kvm->report_event, "report event", 1295 OPT_STRING(0, "event", &kvm->report_event, "report event",
1271 "event for reporting: vmexit, mmio, ioport"), 1296 "event for reporting: "
1297 "vmexit, mmio (x86 only), ioport (x86 only)"),
1272 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, 1298 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
1273 "vcpu id to report"), 1299 "vcpu id to report"),
1274 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1300 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 7af26acf06d9..921bb6942503 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -55,6 +55,7 @@ static struct {
55 bool show_funcs; 55 bool show_funcs;
56 bool mod_events; 56 bool mod_events;
57 bool uprobes; 57 bool uprobes;
58 bool quiet;
58 int nevents; 59 int nevents;
59 struct perf_probe_event events[MAX_PROBES]; 60 struct perf_probe_event events[MAX_PROBES];
60 struct strlist *dellist; 61 struct strlist *dellist;
@@ -312,9 +313,11 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
312#endif 313#endif
313 NULL 314 NULL
314}; 315};
315 const struct option options[] = { 316 struct option options[] = {
316 OPT_INCR('v', "verbose", &verbose, 317 OPT_INCR('v', "verbose", &verbose,
317 "be more verbose (show parsed arguments, etc)"), 318 "be more verbose (show parsed arguments, etc)"),
319 OPT_BOOLEAN('q', "quiet", &params.quiet,
320 "be quiet (do not show any mesages)"),
318 OPT_BOOLEAN('l', "list", &params.list_events, 321 OPT_BOOLEAN('l', "list", &params.list_events,
319 "list up current probe events"), 322 "list up current probe events"),
320 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 323 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
@@ -382,6 +385,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
382 }; 385 };
383 int ret; 386 int ret;
384 387
388 set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
389 set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
390 set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
391#ifdef HAVE_DWARF_SUPPORT
392 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
393 set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
394#endif
395
385 argc = parse_options(argc, argv, options, probe_usage, 396 argc = parse_options(argc, argv, options, probe_usage,
386 PARSE_OPT_STOP_AT_NON_OPTION); 397 PARSE_OPT_STOP_AT_NON_OPTION);
387 if (argc > 0) { 398 if (argc > 0) {
@@ -396,6 +407,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
396 } 407 }
397 } 408 }
398 409
410 if (params.quiet) {
411 if (verbose != 0) {
412 pr_err(" Error: -v and -q are exclusive.\n");
413 return -EINVAL;
414 }
415 verbose = -1;
416 }
417
399 if (params.max_probe_points == 0) 418 if (params.max_probe_points == 0)
400 params.max_probe_points = MAX_PROBES; 419 params.max_probe_points = MAX_PROBES;
401 420
@@ -409,22 +428,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
409 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 428 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
410 429
411 if (params.list_events) { 430 if (params.list_events) {
412 if (params.mod_events) {
413 pr_err(" Error: Don't use --list with --add/--del.\n");
414 usage_with_options(probe_usage, options);
415 }
416 if (params.show_lines) {
417 pr_err(" Error: Don't use --list with --line.\n");
418 usage_with_options(probe_usage, options);
419 }
420 if (params.show_vars) {
421 pr_err(" Error: Don't use --list with --vars.\n");
422 usage_with_options(probe_usage, options);
423 }
424 if (params.show_funcs) {
425 pr_err(" Error: Don't use --list with --funcs.\n");
426 usage_with_options(probe_usage, options);
427 }
428 if (params.uprobes) { 431 if (params.uprobes) {
429 pr_warning(" Error: Don't use --list with --exec.\n"); 432 pr_warning(" Error: Don't use --list with --exec.\n");
430 usage_with_options(probe_usage, options); 433 usage_with_options(probe_usage, options);
@@ -435,19 +438,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
435 return ret; 438 return ret;
436 } 439 }
437 if (params.show_funcs) { 440 if (params.show_funcs) {
438 if (params.nevents != 0 || params.dellist) {
439 pr_err(" Error: Don't use --funcs with"
440 " --add/--del.\n");
441 usage_with_options(probe_usage, options);
442 }
443 if (params.show_lines) {
444 pr_err(" Error: Don't use --funcs with --line.\n");
445 usage_with_options(probe_usage, options);
446 }
447 if (params.show_vars) {
448 pr_err(" Error: Don't use --funcs with --vars.\n");
449 usage_with_options(probe_usage, options);
450 }
451 if (!params.filter) 441 if (!params.filter)
452 params.filter = strfilter__new(DEFAULT_FUNC_FILTER, 442 params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
453 NULL); 443 NULL);
@@ -462,16 +452,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
462 452
463#ifdef HAVE_DWARF_SUPPORT 453#ifdef HAVE_DWARF_SUPPORT
464 if (params.show_lines) { 454 if (params.show_lines) {
465 if (params.mod_events) {
466 pr_err(" Error: Don't use --line with"
467 " --add/--del.\n");
468 usage_with_options(probe_usage, options);
469 }
470 if (params.show_vars) {
471 pr_err(" Error: Don't use --line with --vars.\n");
472 usage_with_options(probe_usage, options);
473 }
474
475 ret = show_line_range(&params.line_range, params.target, 455 ret = show_line_range(&params.line_range, params.target,
476 params.uprobes); 456 params.uprobes);
477 if (ret < 0) 457 if (ret < 0)
@@ -479,11 +459,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
479 return ret; 459 return ret;
480 } 460 }
481 if (params.show_vars) { 461 if (params.show_vars) {
482 if (params.mod_events) {
483 pr_err(" Error: Don't use --vars with"
484 " --add/--del.\n");
485 usage_with_options(probe_usage, options);
486 }
487 if (!params.filter) 462 if (!params.filter)
488 params.filter = strfilter__new(DEFAULT_VAR_FILTER, 463 params.filter = strfilter__new(DEFAULT_VAR_FILTER,
489 NULL); 464 NULL);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 2583a9b04317..8648c6d3003d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -200,6 +200,17 @@ static int process_buildids(struct record *rec)
200 if (size == 0) 200 if (size == 0)
201 return 0; 201 return 0;
202 202
203 /*
204 * During this process, it'll load kernel map and replace the
205 * dso->long_name to a real pathname it found. In this case
206 * we prefer the vmlinux path like
207 * /lib/modules/3.16.4/build/vmlinux
208 *
209 * rather than build-id path (in debug directory).
210 * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
211 */
212 symbol_conf.ignore_vmlinux_buildid = true;
213
203 return __perf_session__process_events(session, start, 214 return __perf_session__process_events(session, start,
204 size - start, 215 size - start,
205 size, &build_id__mark_dso_hit_ops); 216 size, &build_id__mark_dso_hit_ops);
@@ -680,11 +691,12 @@ static int perf_record_config(const char *var, const char *value, void *cb)
680 return perf_default_config(var, value, cb); 691 return perf_default_config(var, value, cb);
681} 692}
682 693
683static const char * const record_usage[] = { 694static const char * const __record_usage[] = {
684 "perf record [<options>] [<command>]", 695 "perf record [<options>] [<command>]",
685 "perf record [<options>] -- <command> [<options>]", 696 "perf record [<options>] -- <command> [<options>]",
686 NULL 697 NULL
687}; 698};
699const char * const *record_usage = __record_usage;
688 700
689/* 701/*
690 * XXX Ideally would be local to cmd_record() and passed to a record__new 702 * XXX Ideally would be local to cmd_record() and passed to a record__new
@@ -725,7 +737,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp";
725 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 737 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
726 * using pipes, etc. 738 * using pipes, etc.
727 */ 739 */
728const struct option record_options[] = { 740struct option __record_options[] = {
729 OPT_CALLBACK('e', "event", &record.evlist, "event", 741 OPT_CALLBACK('e', "event", &record.evlist, "event",
730 "event selector. use 'perf list' to list available events", 742 "event selector. use 'perf list' to list available events",
731 parse_events_option), 743 parse_events_option),
@@ -799,9 +811,13 @@ const struct option record_options[] = {
799 "sample transaction flags (special events only)"), 811 "sample transaction flags (special events only)"),
800 OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 812 OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
801 "use per-thread mmaps"), 813 "use per-thread mmaps"),
814 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
815 "Sample machine registers on interrupt"),
802 OPT_END() 816 OPT_END()
803}; 817};
804 818
819struct option *record_options = __record_options;
820
805int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 821int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
806{ 822{
807 int err = -ENOMEM; 823 int err = -ENOMEM;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 140a6cd88351..39367609c707 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -226,8 +226,9 @@ static int report__setup_sample_type(struct report *rep)
226 return -EINVAL; 226 return -EINVAL;
227 } 227 }
228 if (symbol_conf.use_callchain) { 228 if (symbol_conf.use_callchain) {
229 ui__error("Selected -g but no callchain data. Did " 229 ui__error("Selected -g or --branch-history but no "
230 "you call 'perf record' without -g?\n"); 230 "callchain data. Did\n"
231 "you call 'perf record' without -g?\n");
231 return -1; 232 return -1;
232 } 233 }
233 } else if (!rep->dont_use_callchains && 234 } else if (!rep->dont_use_callchains &&
@@ -575,6 +576,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
575 struct stat st; 576 struct stat st;
576 bool has_br_stack = false; 577 bool has_br_stack = false;
577 int branch_mode = -1; 578 int branch_mode = -1;
579 bool branch_call_mode = false;
578 char callchain_default_opt[] = "fractal,0.5,callee"; 580 char callchain_default_opt[] = "fractal,0.5,callee";
579 const char * const report_usage[] = { 581 const char * const report_usage[] = {
580 "perf report [<options>]", 582 "perf report [<options>]",
@@ -637,8 +639,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
637 "regex filter to identify parent, see: '--sort parent'"), 639 "regex filter to identify parent, see: '--sort parent'"),
638 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 640 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
639 "Only display entries with parent-match"), 641 "Only display entries with parent-match"),
640 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order", 642 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]",
641 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). " 643 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. "
642 "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt), 644 "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt),
643 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 645 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
644 "Accumulate callchains of children and show total overhead as well"), 646 "Accumulate callchains of children and show total overhead as well"),
@@ -684,7 +686,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
684 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 686 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
685 "Show event group information together"), 687 "Show event group information together"),
686 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", 688 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
687 "use branch records for histogram filling", parse_branch_mode), 689 "use branch records for per branch histogram filling",
690 parse_branch_mode),
691 OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
692 "add last branch records to call history"),
688 OPT_STRING(0, "objdump", &objdump_path, "path", 693 OPT_STRING(0, "objdump", &objdump_path, "path",
689 "objdump binary to use for disassembly and annotations"), 694 "objdump binary to use for disassembly and annotations"),
690 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 695 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
@@ -745,10 +750,24 @@ repeat:
745 has_br_stack = perf_header__has_feat(&session->header, 750 has_br_stack = perf_header__has_feat(&session->header,
746 HEADER_BRANCH_STACK); 751 HEADER_BRANCH_STACK);
747 752
748 if ((branch_mode == -1 && has_br_stack) || branch_mode == 1) { 753 /*
754 * Branch mode is a tristate:
755 * -1 means default, so decide based on the file having branch data.
756 * 0/1 means the user chose a mode.
757 */
758 if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
759 branch_call_mode == -1) {
749 sort__mode = SORT_MODE__BRANCH; 760 sort__mode = SORT_MODE__BRANCH;
750 symbol_conf.cumulate_callchain = false; 761 symbol_conf.cumulate_callchain = false;
751 } 762 }
763 if (branch_call_mode) {
764 callchain_param.key = CCKEY_ADDRESS;
765 callchain_param.branch_callstack = 1;
766 symbol_conf.use_callchain = true;
767 callchain_register_param(&callchain_param);
768 if (sort_order == NULL)
769 sort_order = "srcline,symbol,dso";
770 }
752 771
753 if (report.mem_mode) { 772 if (report.mem_mode) {
754 if (sort__mode == SORT_MODE__BRANCH) { 773 if (sort__mode == SORT_MODE__BRANCH) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9708a1290571..ce304dfd962a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -23,7 +23,6 @@ static char const *generate_script_lang;
23static bool debug_mode; 23static bool debug_mode;
24static u64 last_timestamp; 24static u64 last_timestamp;
25static u64 nr_unordered; 25static u64 nr_unordered;
26extern const struct option record_options[];
27static bool no_callchain; 26static bool no_callchain;
28static bool latency_format; 27static bool latency_format;
29static bool system_wide; 28static bool system_wide;
@@ -379,7 +378,6 @@ static void print_sample_start(struct perf_sample *sample,
379 378
380static void print_sample_addr(union perf_event *event, 379static void print_sample_addr(union perf_event *event,
381 struct perf_sample *sample, 380 struct perf_sample *sample,
382 struct machine *machine,
383 struct thread *thread, 381 struct thread *thread,
384 struct perf_event_attr *attr) 382 struct perf_event_attr *attr)
385{ 383{
@@ -390,7 +388,7 @@ static void print_sample_addr(union perf_event *event,
390 if (!sample_addr_correlates_sym(attr)) 388 if (!sample_addr_correlates_sym(attr))
391 return; 389 return;
392 390
393 perf_event__preprocess_sample_addr(event, sample, machine, thread, &al); 391 perf_event__preprocess_sample_addr(event, sample, thread, &al);
394 392
395 if (PRINT_FIELD(SYM)) { 393 if (PRINT_FIELD(SYM)) {
396 printf(" "); 394 printf(" ");
@@ -438,7 +436,7 @@ static void print_sample_bts(union perf_event *event,
438 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 436 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
439 !output[attr->type].user_set)) { 437 !output[attr->type].user_set)) {
440 printf(" => "); 438 printf(" => ");
441 print_sample_addr(event, sample, al->machine, thread, attr); 439 print_sample_addr(event, sample, thread, attr);
442 } 440 }
443 441
444 if (print_srcline_last) 442 if (print_srcline_last)
@@ -475,7 +473,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
475 event_format__print(evsel->tp_format, sample->cpu, 473 event_format__print(evsel->tp_format, sample->cpu,
476 sample->raw_data, sample->raw_size); 474 sample->raw_data, sample->raw_size);
477 if (PRINT_FIELD(ADDR)) 475 if (PRINT_FIELD(ADDR))
478 print_sample_addr(event, sample, al->machine, thread, attr); 476 print_sample_addr(event, sample, thread, attr);
479 477
480 if (PRINT_FIELD(IP)) { 478 if (PRINT_FIELD(IP)) {
481 if (!symbol_conf.use_callchain) 479 if (!symbol_conf.use_callchain)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 055ce9232c9e..891086376381 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -388,20 +388,102 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
388 update_stats(&runtime_itlb_cache_stats[0], count[0]); 388 update_stats(&runtime_itlb_cache_stats[0], count[0]);
389} 389}
390 390
391static void zero_per_pkg(struct perf_evsel *counter)
392{
393 if (counter->per_pkg_mask)
394 memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
395}
396
397static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
398{
399 unsigned long *mask = counter->per_pkg_mask;
400 struct cpu_map *cpus = perf_evsel__cpus(counter);
401 int s;
402
403 *skip = false;
404
405 if (!counter->per_pkg)
406 return 0;
407
408 if (cpu_map__empty(cpus))
409 return 0;
410
411 if (!mask) {
412 mask = zalloc(MAX_NR_CPUS);
413 if (!mask)
414 return -ENOMEM;
415
416 counter->per_pkg_mask = mask;
417 }
418
419 s = cpu_map__get_socket(cpus, cpu);
420 if (s < 0)
421 return -1;
422
423 *skip = test_and_set_bit(s, mask) == 1;
424 return 0;
425}
426
427static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
428 struct perf_counts_values *count)
429{
430 struct perf_counts_values *aggr = &evsel->counts->aggr;
431 static struct perf_counts_values zero;
432 bool skip = false;
433
434 if (check_per_pkg(evsel, cpu, &skip)) {
435 pr_err("failed to read per-pkg counter\n");
436 return -1;
437 }
438
439 if (skip)
440 count = &zero;
441
442 switch (aggr_mode) {
443 case AGGR_CORE:
444 case AGGR_SOCKET:
445 case AGGR_NONE:
446 if (!evsel->snapshot)
447 perf_evsel__compute_deltas(evsel, cpu, count);
448 perf_counts_values__scale(count, scale, NULL);
449 evsel->counts->cpu[cpu] = *count;
450 update_shadow_stats(evsel, count->values);
451 break;
452 case AGGR_GLOBAL:
453 aggr->val += count->val;
454 if (scale) {
455 aggr->ena += count->ena;
456 aggr->run += count->run;
457 }
458 default:
459 break;
460 }
461
462 return 0;
463}
464
465static int read_counter(struct perf_evsel *counter);
466
391/* 467/*
392 * Read out the results of a single counter: 468 * Read out the results of a single counter:
393 * aggregate counts across CPUs in system-wide mode 469 * aggregate counts across CPUs in system-wide mode
394 */ 470 */
395static int read_counter_aggr(struct perf_evsel *counter) 471static int read_counter_aggr(struct perf_evsel *counter)
396{ 472{
473 struct perf_counts_values *aggr = &counter->counts->aggr;
397 struct perf_stat *ps = counter->priv; 474 struct perf_stat *ps = counter->priv;
398 u64 *count = counter->counts->aggr.values; 475 u64 *count = counter->counts->aggr.values;
399 int i; 476 int i;
400 477
401 if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter), 478 aggr->val = aggr->ena = aggr->run = 0;
402 thread_map__nr(evsel_list->threads), scale) < 0) 479
480 if (read_counter(counter))
403 return -1; 481 return -1;
404 482
483 if (!counter->snapshot)
484 perf_evsel__compute_deltas(counter, -1, aggr);
485 perf_counts_values__scale(aggr, scale, &counter->counts->scaled);
486
405 for (i = 0; i < 3; i++) 487 for (i = 0; i < 3; i++)
406 update_stats(&ps->res_stats[i], count[i]); 488 update_stats(&ps->res_stats[i], count[i]);
407 489
@@ -424,16 +506,21 @@ static int read_counter_aggr(struct perf_evsel *counter)
424 */ 506 */
425static int read_counter(struct perf_evsel *counter) 507static int read_counter(struct perf_evsel *counter)
426{ 508{
427 u64 *count; 509 int nthreads = thread_map__nr(evsel_list->threads);
428 int cpu; 510 int ncpus = perf_evsel__nr_cpus(counter);
511 int cpu, thread;
429 512
430 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 513 if (counter->system_wide)
431 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 514 nthreads = 1;
432 return -1;
433 515
434 count = counter->counts->cpu[cpu].values; 516 if (counter->per_pkg)
517 zero_per_pkg(counter);
435 518
436 update_shadow_stats(counter, count); 519 for (thread = 0; thread < nthreads; thread++) {
520 for (cpu = 0; cpu < ncpus; cpu++) {
521 if (perf_evsel__read_cb(counter, cpu, thread, read_cb))
522 return -1;
523 }
437 } 524 }
438 525
439 return 0; 526 return 0;
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 35b425b6293f..f3bb1a4bf060 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -528,7 +528,7 @@ static const char *cat_backtrace(union perf_event *event,
528 } 528 }
529 529
530 tal.filtered = 0; 530 tal.filtered = 0;
531 thread__find_addr_location(al.thread, machine, cpumode, 531 thread__find_addr_location(al.thread, cpumode,
532 MAP__FUNCTION, ip, &tal); 532 MAP__FUNCTION, ip, &tal);
533 533
534 if (tal.sym) 534 if (tal.sym)
@@ -1963,7 +1963,7 @@ int cmd_timechart(int argc, const char **argv,
1963 NULL 1963 NULL
1964 }; 1964 };
1965 1965
1966 const struct option record_options[] = { 1966 const struct option timechart_record_options[] = {
1967 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), 1967 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
1968 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, 1968 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
1969 "output processes data only"), 1969 "output processes data only"),
@@ -1972,7 +1972,7 @@ int cmd_timechart(int argc, const char **argv,
1972 OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"), 1972 OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"),
1973 OPT_END() 1973 OPT_END()
1974 }; 1974 };
1975 const char * const record_usage[] = { 1975 const char * const timechart_record_usage[] = {
1976 "perf timechart record [<options>]", 1976 "perf timechart record [<options>]",
1977 NULL 1977 NULL
1978 }; 1978 };
@@ -1985,7 +1985,8 @@ int cmd_timechart(int argc, const char **argv,
1985 } 1985 }
1986 1986
1987 if (argc && !strncmp(argv[0], "rec", 3)) { 1987 if (argc && !strncmp(argv[0], "rec", 3)) {
1988 argc = parse_options(argc, argv, record_options, record_usage, 1988 argc = parse_options(argc, argv, timechart_record_options,
1989 timechart_record_usage,
1989 PARSE_OPT_STOP_AT_NON_OPTION); 1990 PARSE_OPT_STOP_AT_NON_OPTION);
1990 1991
1991 if (tchart.power_only && tchart.tasks_only) { 1992 if (tchart.power_only && tchart.tasks_only) {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index fb126459b134..badfabc6a01f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1846,7 +1846,7 @@ static int trace__pgfault(struct trace *trace,
1846 if (trace->summary_only) 1846 if (trace->summary_only)
1847 return 0; 1847 return 0;
1848 1848
1849 thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION, 1849 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
1850 sample->ip, &al); 1850 sample->ip, &al);
1851 1851
1852 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output); 1852 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
@@ -1859,11 +1859,11 @@ static int trace__pgfault(struct trace *trace,
1859 1859
1860 fprintf(trace->output, "] => "); 1860 fprintf(trace->output, "] => ");
1861 1861
1862 thread__find_addr_location(thread, trace->host, cpumode, MAP__VARIABLE, 1862 thread__find_addr_location(thread, cpumode, MAP__VARIABLE,
1863 sample->addr, &al); 1863 sample->addr, &al);
1864 1864
1865 if (!al.map) { 1865 if (!al.map) {
1866 thread__find_addr_location(thread, trace->host, cpumode, 1866 thread__find_addr_location(thread, cpumode,
1867 MAP__FUNCTION, sample->addr, &al); 1867 MAP__FUNCTION, sample->addr, &al);
1868 1868
1869 if (al.map) 1869 if (al.map)
@@ -2045,7 +2045,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2045 unsigned long before; 2045 unsigned long before;
2046 const bool forks = argc > 0; 2046 const bool forks = argc > 0;
2047 bool draining = false; 2047 bool draining = false;
2048 char sbuf[STRERR_BUFSIZE];
2049 2048
2050 trace->live = true; 2049 trace->live = true;
2051 2050
@@ -2106,11 +2105,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2106 goto out_error_open; 2105 goto out_error_open;
2107 2106
2108 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2107 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
2109 if (err < 0) { 2108 if (err < 0)
2110 fprintf(trace->output, "Couldn't mmap the events: %s\n", 2109 goto out_error_mmap;
2111 strerror_r(errno, sbuf, sizeof(sbuf)));
2112 goto out_delete_evlist;
2113 }
2114 2110
2115 perf_evlist__enable(evlist); 2111 perf_evlist__enable(evlist);
2116 2112
@@ -2210,6 +2206,10 @@ out_error_tp:
2210 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf)); 2206 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
2211 goto out_error; 2207 goto out_error;
2212 2208
2209out_error_mmap:
2210 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2211 goto out_error;
2212
2213out_error_open: 2213out_error_open:
2214 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); 2214 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2215 2215
@@ -2485,7 +2485,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2485 .user_freq = UINT_MAX, 2485 .user_freq = UINT_MAX,
2486 .user_interval = ULLONG_MAX, 2486 .user_interval = ULLONG_MAX,
2487 .no_buffering = true, 2487 .no_buffering = true,
2488 .mmap_pages = 1024, 2488 .mmap_pages = UINT_MAX,
2489 }, 2489 },
2490 .output = stdout, 2490 .output = stdout,
2491 .show_comm = true, 2491 .show_comm = true,
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 58f609198c6d..5d4b039fe1ed 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -150,7 +150,7 @@ CFLAGS += -std=gnu99
150# adding assembler files missing the .GNU-stack linker note. 150# adding assembler files missing the .GNU-stack linker note.
151LDFLAGS += -Wl,-z,noexecstack 151LDFLAGS += -Wl,-z,noexecstack
152 152
153EXTLIBS = -lelf -lpthread -lrt -lm -ldl 153EXTLIBS = -lpthread -lrt -lm -ldl
154 154
155ifneq ($(OUTPUT),) 155ifneq ($(OUTPUT),)
156 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ 156 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
@@ -200,7 +200,8 @@ CORE_FEATURE_TESTS = \
200 libunwind \ 200 libunwind \
201 stackprotector-all \ 201 stackprotector-all \
202 timerfd \ 202 timerfd \
203 libdw-dwarf-unwind 203 libdw-dwarf-unwind \
204 zlib
204 205
205LIB_FEATURE_TESTS = \ 206LIB_FEATURE_TESTS = \
206 dwarf \ 207 dwarf \
@@ -214,7 +215,8 @@ LIB_FEATURE_TESTS = \
214 libpython \ 215 libpython \
215 libslang \ 216 libslang \
216 libunwind \ 217 libunwind \
217 libdw-dwarf-unwind 218 libdw-dwarf-unwind \
219 zlib
218 220
219VF_FEATURE_TESTS = \ 221VF_FEATURE_TESTS = \
220 backtrace \ 222 backtrace \
@@ -230,7 +232,9 @@ VF_FEATURE_TESTS = \
230 bionic \ 232 bionic \
231 liberty \ 233 liberty \
232 liberty-z \ 234 liberty-z \
233 cplus-demangle 235 cplus-demangle \
236 compile-32 \
237 compile-x32
234 238
235# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. 239# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
236# If in the future we need per-feature checks/flags for features not 240# If in the future we need per-feature checks/flags for features not
@@ -350,6 +354,7 @@ endif # NO_LIBELF
350 354
351ifndef NO_LIBELF 355ifndef NO_LIBELF
352 CFLAGS += -DHAVE_LIBELF_SUPPORT 356 CFLAGS += -DHAVE_LIBELF_SUPPORT
357 EXTLIBS += -lelf
353 358
354 ifeq ($(feature-libelf-mmap), 1) 359 ifeq ($(feature-libelf-mmap), 1)
355 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT 360 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
@@ -369,7 +374,7 @@ ifndef NO_LIBELF
369 else 374 else
370 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) 375 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
371 LDFLAGS += $(LIBDW_LDFLAGS) 376 LDFLAGS += $(LIBDW_LDFLAGS)
372 EXTLIBS += -lelf -ldw 377 EXTLIBS += -ldw
373 endif # PERF_HAVE_DWARF_REGS 378 endif # PERF_HAVE_DWARF_REGS
374 endif # NO_DWARF 379 endif # NO_DWARF
375endif # NO_LIBELF 380endif # NO_LIBELF
@@ -602,6 +607,15 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),)
602 CFLAGS += -DHAVE_LIBBFD_SUPPORT 607 CFLAGS += -DHAVE_LIBBFD_SUPPORT
603endif 608endif
604 609
610ifndef NO_ZLIB
611 ifeq ($(feature-zlib), 1)
612 CFLAGS += -DHAVE_ZLIB_SUPPORT
613 EXTLIBS += -lz
614 else
615 NO_ZLIB := 1
616 endif
617endif
618
605ifndef NO_BACKTRACE 619ifndef NO_BACKTRACE
606 ifeq ($(feature-backtrace), 1) 620 ifeq ($(feature-backtrace), 1)
607 CFLAGS += -DHAVE_BACKTRACE_SUPPORT 621 CFLAGS += -DHAVE_BACKTRACE_SUPPORT
@@ -622,6 +636,31 @@ ifdef HAVE_KVM_STAT_SUPPORT
622 CFLAGS += -DHAVE_KVM_STAT_SUPPORT 636 CFLAGS += -DHAVE_KVM_STAT_SUPPORT
623endif 637endif
624 638
639ifeq (${IS_64_BIT}, 1)
640 ifndef NO_PERF_READ_VDSO32
641 $(call feature_check,compile-32)
642 ifeq ($(feature-compile-32), 1)
643 CFLAGS += -DHAVE_PERF_READ_VDSO32
644 else
645 NO_PERF_READ_VDSO32 := 1
646 endif
647 endif
648 ifneq (${IS_X86_64}, 1)
649 NO_PERF_READ_VDSOX32 := 1
650 endif
651 ifndef NO_PERF_READ_VDSOX32
652 $(call feature_check,compile-x32)
653 ifeq ($(feature-compile-x32), 1)
654 CFLAGS += -DHAVE_PERF_READ_VDSOX32
655 else
656 NO_PERF_READ_VDSOX32 := 1
657 endif
658 endif
659else
660 NO_PERF_READ_VDSO32 := 1
661 NO_PERF_READ_VDSOX32 := 1
662endif
663
625# Among the variables below, these: 664# Among the variables below, these:
626# perfexecdir 665# perfexecdir
627# template_dir 666# template_dir
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
index 4b06719ee984..851cd0172a76 100644
--- a/tools/perf/config/Makefile.arch
+++ b/tools/perf/config/Makefile.arch
@@ -21,3 +21,11 @@ ifeq ($(ARCH),x86_64)
21 RAW_ARCH := x86_64 21 RAW_ARCH := x86_64
22 endif 22 endif
23endif 23endif
24
25ifeq (${IS_X86_64}, 1)
26 IS_64_BIT := 1
27else ifeq ($(ARCH),x86)
28 IS_64_BIT := 0
29else
30 IS_64_BIT := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
31endif
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 72ab2984718e..53f19b5dbc37 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -27,7 +27,10 @@ FILES= \
27 test-libunwind-debug-frame.bin \ 27 test-libunwind-debug-frame.bin \
28 test-stackprotector-all.bin \ 28 test-stackprotector-all.bin \
29 test-timerfd.bin \ 29 test-timerfd.bin \
30 test-libdw-dwarf-unwind.bin 30 test-libdw-dwarf-unwind.bin \
31 test-compile-32.bin \
32 test-compile-x32.bin \
33 test-zlib.bin
31 34
32CC := $(CROSS_COMPILE)gcc -MD 35CC := $(CROSS_COMPILE)gcc -MD
33PKG_CONFIG := $(CROSS_COMPILE)pkg-config 36PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -39,7 +42,7 @@ BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
39############################### 42###############################
40 43
41test-all.bin: 44test-all.bin:
42 $(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 45 $(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
43 46
44test-hello.bin: 47test-hello.bin:
45 $(BUILD) 48 $(BUILD)
@@ -131,6 +134,15 @@ test-libdw-dwarf-unwind.bin:
131test-sync-compare-and-swap.bin: 134test-sync-compare-and-swap.bin:
132 $(BUILD) -Werror 135 $(BUILD) -Werror
133 136
137test-compile-32.bin:
138 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
139
140test-compile-x32.bin:
141 $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c
142
143test-zlib.bin:
144 $(BUILD) -lz
145
134-include *.d 146-include *.d
135 147
136############################### 148###############################
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index a7d022e161c0..652e0098eba6 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -93,6 +93,10 @@
93# include "test-sync-compare-and-swap.c" 93# include "test-sync-compare-and-swap.c"
94#undef main 94#undef main
95 95
96#define main main_test_zlib
97# include "test-zlib.c"
98#undef main
99
96int main(int argc, char *argv[]) 100int main(int argc, char *argv[])
97{ 101{
98 main_test_libpython(); 102 main_test_libpython();
@@ -116,6 +120,7 @@ int main(int argc, char *argv[])
116 main_test_stackprotector_all(); 120 main_test_stackprotector_all();
117 main_test_libdw_dwarf_unwind(); 121 main_test_libdw_dwarf_unwind();
118 main_test_sync_compare_and_swap(argc, argv); 122 main_test_sync_compare_and_swap(argc, argv);
123 main_test_zlib();
119 124
120 return 0; 125 return 0;
121} 126}
diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/perf/config/feature-checks/test-compile.c
new file mode 100644
index 000000000000..31dbf45bf99c
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-compile.c
@@ -0,0 +1,4 @@
1int main(void)
2{
3 return 0;
4}
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
new file mode 100644
index 000000000000..e111fff6240e
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-zlib.c
@@ -0,0 +1,9 @@
1#include <zlib.h>
2
3int main(void)
4{
5 z_stream zs;
6
7 inflateInit(&zs);
8 return 0;
9}
diff --git a/tools/perf/perf-read-vdso.c b/tools/perf/perf-read-vdso.c
new file mode 100644
index 000000000000..764e2547c25a
--- /dev/null
+++ b/tools/perf/perf-read-vdso.c
@@ -0,0 +1,34 @@
1#include <stdio.h>
2#include <string.h>
3
4#define VDSO__MAP_NAME "[vdso]"
5
6/*
7 * Include definition of find_vdso_map() also used in util/vdso.c for
8 * building perf.
9 */
10#include "util/find-vdso-map.c"
11
12int main(void)
13{
14 void *start, *end;
15 size_t size, written;
16
17 if (find_vdso_map(&start, &end))
18 return 1;
19
20 size = end - start;
21
22 while (size) {
23 written = fwrite(start, 1, size, stdout);
24 if (!written)
25 return 1;
26 start += written;
27 size -= written;
28 }
29
30 if (fflush(stdout))
31 return 1;
32
33 return 0;
34}
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 452a8474d29d..3700a7faca6c 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -200,6 +200,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
200 *envchanged = 1; 200 *envchanged = 1;
201 (*argv)++; 201 (*argv)++;
202 (*argc)--; 202 (*argc)--;
203 } else if (!strcmp(cmd, "--buildid-dir")) {
204 if (*argc < 2) {
205 fprintf(stderr, "No directory given for --buildid-dir.\n");
206 usage(perf_usage_string);
207 }
208 set_buildid_dir((*argv)[1]);
209 if (envchanged)
210 *envchanged = 1;
211 (*argv)++;
212 (*argc)--;
203 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 213 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
204 perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR)); 214 perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR));
205 fprintf(stderr, "dir: %s\n", debugfs_mountpoint); 215 fprintf(stderr, "dir: %s\n", debugfs_mountpoint);
@@ -499,7 +509,7 @@ int main(int argc, const char **argv)
499 } 509 }
500 if (!prefixcmp(cmd, "trace")) { 510 if (!prefixcmp(cmd, "trace")) {
501#ifdef HAVE_LIBAUDIT_SUPPORT 511#ifdef HAVE_LIBAUDIT_SUPPORT
502 set_buildid_dir(); 512 set_buildid_dir(NULL);
503 setup_path(); 513 setup_path();
504 argv[0] = "trace"; 514 argv[0] = "trace";
505 return cmd_trace(argc, argv, NULL); 515 return cmd_trace(argc, argv, NULL);
@@ -514,7 +524,7 @@ int main(int argc, const char **argv)
514 argc--; 524 argc--;
515 handle_options(&argv, &argc, NULL); 525 handle_options(&argv, &argc, NULL);
516 commit_pager_choice(); 526 commit_pager_choice();
517 set_buildid_dir(); 527 set_buildid_dir(NULL);
518 528
519 if (argc > 0) { 529 if (argc > 0) {
520 if (!prefixcmp(argv[0], "--")) 530 if (!prefixcmp(argv[0], "--"))
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 220d44e44c1b..1dabb8553499 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -52,6 +52,7 @@ struct record_opts {
52 bool sample_weight; 52 bool sample_weight;
53 bool sample_time; 53 bool sample_time;
54 bool period; 54 bool period;
55 bool sample_intr_regs;
55 unsigned int freq; 56 unsigned int freq;
56 unsigned int mmap_pages; 57 unsigned int mmap_pages;
57 unsigned int user_freq; 58 unsigned int user_freq;
@@ -62,4 +63,7 @@ struct record_opts {
62 unsigned initial_delay; 63 unsigned initial_delay;
63}; 64};
64 65
66struct option;
67extern const char * const *record_usage;
68extern struct option *record_options;
65#endif 69#endif
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-record b/tools/perf/scripts/python/bin/export-to-postgresql-record
new file mode 100644
index 000000000000..221d66e05713
--- /dev/null
+++ b/tools/perf/scripts/python/bin/export-to-postgresql-record
@@ -0,0 +1,8 @@
1#!/bin/bash
2
3#
4# export perf data to a postgresql database. Can cover
5# perf ip samples (excluding the tracepoints). No special
6# record requirements, just record what you want to export.
7#
8perf record $@
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-report b/tools/perf/scripts/python/bin/export-to-postgresql-report
new file mode 100644
index 000000000000..cd335b6e2a01
--- /dev/null
+++ b/tools/perf/scripts/python/bin/export-to-postgresql-report
@@ -0,0 +1,29 @@
1#!/bin/bash
2# description: export perf data to a postgresql database
3# args: [database name] [columns] [calls]
4n_args=0
5for i in "$@"
6do
7 if expr match "$i" "-" > /dev/null ; then
8 break
9 fi
10 n_args=$(( $n_args + 1 ))
11done
12if [ "$n_args" -gt 3 ] ; then
13 echo "usage: export-to-postgresql-report [database name] [columns] [calls]"
14 exit
15fi
16if [ "$n_args" -gt 2 ] ; then
17 dbname=$1
18 columns=$2
19 calls=$3
20 shift 3
21elif [ "$n_args" -gt 1 ] ; then
22 dbname=$1
23 columns=$2
24 shift 2
25elif [ "$n_args" -gt 0 ] ; then
26 dbname=$1
27 shift
28fi
29perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/export-to-postgresql.py $dbname $columns $calls
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
new file mode 100644
index 000000000000..4cdafd880074
--- /dev/null
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -0,0 +1,444 @@
1# export-to-postgresql.py: export perf data to a postgresql database
2# Copyright (c) 2014, Intel Corporation.
3#
4# This program is free software; you can redistribute it and/or modify it
5# under the terms and conditions of the GNU General Public License,
6# version 2, as published by the Free Software Foundation.
7#
8# This program is distributed in the hope it will be useful, but WITHOUT
9# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11# more details.
12
13import os
14import sys
15import struct
16import datetime
17
18from PySide.QtSql import *
19
20# Need to access PostgreSQL C library directly to use COPY FROM STDIN
21from ctypes import *
22libpq = CDLL("libpq.so.5")
23PQconnectdb = libpq.PQconnectdb
24PQconnectdb.restype = c_void_p
25PQfinish = libpq.PQfinish
26PQstatus = libpq.PQstatus
27PQexec = libpq.PQexec
28PQexec.restype = c_void_p
29PQresultStatus = libpq.PQresultStatus
30PQputCopyData = libpq.PQputCopyData
31PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ]
32PQputCopyEnd = libpq.PQputCopyEnd
33PQputCopyEnd.argtypes = [ c_void_p, c_void_p ]
34
35sys.path.append(os.environ['PERF_EXEC_PATH'] + \
36 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
37
38# These perf imports are not used at present
39#from perf_trace_context import *
40#from Core import *
41
42perf_db_export_mode = True
43perf_db_export_calls = False
44
45def usage():
46 print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>]"
47 print >> sys.stderr, "where: columns 'all' or 'branches'"
48 print >> sys.stderr, " calls 'calls' => create calls table"
49 raise Exception("Too few arguments")
50
51if (len(sys.argv) < 2):
52 usage()
53
54dbname = sys.argv[1]
55
56if (len(sys.argv) >= 3):
57 columns = sys.argv[2]
58else:
59 columns = "all"
60
61if columns not in ("all", "branches"):
62 usage()
63
64branches = (columns == "branches")
65
66if (len(sys.argv) >= 4):
67 if (sys.argv[3] == "calls"):
68 perf_db_export_calls = True
69 else:
70 usage()
71
72output_dir_name = os.getcwd() + "/" + dbname + "-perf-data"
73os.mkdir(output_dir_name)
74
75def do_query(q, s):
76 if (q.exec_(s)):
77 return
78 raise Exception("Query failed: " + q.lastError().text())
79
80print datetime.datetime.today(), "Creating database..."
81
82db = QSqlDatabase.addDatabase('QPSQL')
83query = QSqlQuery(db)
84db.setDatabaseName('postgres')
85db.open()
86try:
87 do_query(query, 'CREATE DATABASE ' + dbname)
88except:
89 os.rmdir(output_dir_name)
90 raise
91query.finish()
92query.clear()
93db.close()
94
95db.setDatabaseName(dbname)
96db.open()
97
98query = QSqlQuery(db)
99do_query(query, 'SET client_min_messages TO WARNING')
100
101do_query(query, 'CREATE TABLE selected_events ('
102 'id bigint NOT NULL,'
103 'name varchar(80))')
104do_query(query, 'CREATE TABLE machines ('
105 'id bigint NOT NULL,'
106 'pid integer,'
107 'root_dir varchar(4096))')
108do_query(query, 'CREATE TABLE threads ('
109 'id bigint NOT NULL,'
110 'machine_id bigint,'
111 'process_id bigint,'
112 'pid integer,'
113 'tid integer)')
114do_query(query, 'CREATE TABLE comms ('
115 'id bigint NOT NULL,'
116 'comm varchar(16))')
117do_query(query, 'CREATE TABLE comm_threads ('
118 'id bigint NOT NULL,'
119 'comm_id bigint,'
120 'thread_id bigint)')
121do_query(query, 'CREATE TABLE dsos ('
122 'id bigint NOT NULL,'
123 'machine_id bigint,'
124 'short_name varchar(256),'
125 'long_name varchar(4096),'
126 'build_id varchar(64))')
127do_query(query, 'CREATE TABLE symbols ('
128 'id bigint NOT NULL,'
129 'dso_id bigint,'
130 'sym_start bigint,'
131 'sym_end bigint,'
132 'binding integer,'
133 'name varchar(2048))')
134do_query(query, 'CREATE TABLE branch_types ('
135 'id integer NOT NULL,'
136 'name varchar(80))')
137
138if branches:
139 do_query(query, 'CREATE TABLE samples ('
140 'id bigint NOT NULL,'
141 'evsel_id bigint,'
142 'machine_id bigint,'
143 'thread_id bigint,'
144 'comm_id bigint,'
145 'dso_id bigint,'
146 'symbol_id bigint,'
147 'sym_offset bigint,'
148 'ip bigint,'
149 'time bigint,'
150 'cpu integer,'
151 'to_dso_id bigint,'
152 'to_symbol_id bigint,'
153 'to_sym_offset bigint,'
154 'to_ip bigint,'
155 'branch_type integer,'
156 'in_tx boolean)')
157else:
158 do_query(query, 'CREATE TABLE samples ('
159 'id bigint NOT NULL,'
160 'evsel_id bigint,'
161 'machine_id bigint,'
162 'thread_id bigint,'
163 'comm_id bigint,'
164 'dso_id bigint,'
165 'symbol_id bigint,'
166 'sym_offset bigint,'
167 'ip bigint,'
168 'time bigint,'
169 'cpu integer,'
170 'to_dso_id bigint,'
171 'to_symbol_id bigint,'
172 'to_sym_offset bigint,'
173 'to_ip bigint,'
174 'period bigint,'
175 'weight bigint,'
176 'transaction bigint,'
177 'data_src bigint,'
178 'branch_type integer,'
179 'in_tx boolean)')
180
181if perf_db_export_calls:
182 do_query(query, 'CREATE TABLE call_paths ('
183 'id bigint NOT NULL,'
184 'parent_id bigint,'
185 'symbol_id bigint,'
186 'ip bigint)')
187 do_query(query, 'CREATE TABLE calls ('
188 'id bigint NOT NULL,'
189 'thread_id bigint,'
190 'comm_id bigint,'
191 'call_path_id bigint,'
192 'call_time bigint,'
193 'return_time bigint,'
194 'branch_count bigint,'
195 'call_id bigint,'
196 'return_id bigint,'
197 'parent_call_path_id bigint,'
198 'flags integer)')
199
200do_query(query, 'CREATE VIEW samples_view AS '
201 'SELECT '
202 'id,'
203 'time,'
204 'cpu,'
205 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
206 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
207 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
208 '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
209 'to_hex(ip) AS ip_hex,'
210 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
211 'sym_offset,'
212 '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
213 'to_hex(to_ip) AS to_ip_hex,'
214 '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
215 'to_sym_offset,'
216 '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
217 '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
218 'in_tx'
219 ' FROM samples')
220
221
222file_header = struct.pack("!11sii", "PGCOPY\n\377\r\n\0", 0, 0)
223file_trailer = "\377\377"
224
225def open_output_file(file_name):
226 path_name = output_dir_name + "/" + file_name
227 file = open(path_name, "w+")
228 file.write(file_header)
229 return file
230
231def close_output_file(file):
232 file.write(file_trailer)
233 file.close()
234
235def copy_output_file_direct(file, table_name):
236 close_output_file(file)
237 sql = "COPY " + table_name + " FROM '" + file.name + "' (FORMAT 'binary')"
238 do_query(query, sql)
239
240# Use COPY FROM STDIN because security may prevent postgres from accessing the files directly
241def copy_output_file(file, table_name):
242 conn = PQconnectdb("dbname = " + dbname)
243 if (PQstatus(conn)):
244 raise Exception("COPY FROM STDIN PQconnectdb failed")
245 file.write(file_trailer)
246 file.seek(0)
247 sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')"
248 res = PQexec(conn, sql)
249 if (PQresultStatus(res) != 4):
250 raise Exception("COPY FROM STDIN PQexec failed")
251 data = file.read(65536)
252 while (len(data)):
253 ret = PQputCopyData(conn, data, len(data))
254 if (ret != 1):
255 raise Exception("COPY FROM STDIN PQputCopyData failed, error " + str(ret))
256 data = file.read(65536)
257 ret = PQputCopyEnd(conn, None)
258 if (ret != 1):
259 raise Exception("COPY FROM STDIN PQputCopyEnd failed, error " + str(ret))
260 PQfinish(conn)
261
262def remove_output_file(file):
263 name = file.name
264 file.close()
265 os.unlink(name)
266
267evsel_file = open_output_file("evsel_table.bin")
268machine_file = open_output_file("machine_table.bin")
269thread_file = open_output_file("thread_table.bin")
270comm_file = open_output_file("comm_table.bin")
271comm_thread_file = open_output_file("comm_thread_table.bin")
272dso_file = open_output_file("dso_table.bin")
273symbol_file = open_output_file("symbol_table.bin")
274branch_type_file = open_output_file("branch_type_table.bin")
275sample_file = open_output_file("sample_table.bin")
276if perf_db_export_calls:
277 call_path_file = open_output_file("call_path_table.bin")
278 call_file = open_output_file("call_table.bin")
279
280def trace_begin():
281 print datetime.datetime.today(), "Writing to intermediate files..."
282 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
283 evsel_table(0, "unknown")
284 machine_table(0, 0, "unknown")
285 thread_table(0, 0, 0, -1, -1)
286 comm_table(0, "unknown")
287 dso_table(0, 0, "unknown", "unknown", "")
288 symbol_table(0, 0, 0, 0, 0, "unknown")
289 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
290 if perf_db_export_calls:
291 call_path_table(0, 0, 0, 0)
292
293unhandled_count = 0
294
295def trace_end():
296 print datetime.datetime.today(), "Copying to database..."
297 copy_output_file(evsel_file, "selected_events")
298 copy_output_file(machine_file, "machines")
299 copy_output_file(thread_file, "threads")
300 copy_output_file(comm_file, "comms")
301 copy_output_file(comm_thread_file, "comm_threads")
302 copy_output_file(dso_file, "dsos")
303 copy_output_file(symbol_file, "symbols")
304 copy_output_file(branch_type_file, "branch_types")
305 copy_output_file(sample_file, "samples")
306 if perf_db_export_calls:
307 copy_output_file(call_path_file, "call_paths")
308 copy_output_file(call_file, "calls")
309
310 print datetime.datetime.today(), "Removing intermediate files..."
311 remove_output_file(evsel_file)
312 remove_output_file(machine_file)
313 remove_output_file(thread_file)
314 remove_output_file(comm_file)
315 remove_output_file(comm_thread_file)
316 remove_output_file(dso_file)
317 remove_output_file(symbol_file)
318 remove_output_file(branch_type_file)
319 remove_output_file(sample_file)
320 if perf_db_export_calls:
321 remove_output_file(call_path_file)
322 remove_output_file(call_file)
323 os.rmdir(output_dir_name)
324 print datetime.datetime.today(), "Adding primary keys"
325 do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)')
326 do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)')
327 do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)')
328 do_query(query, 'ALTER TABLE comms ADD PRIMARY KEY (id)')
329 do_query(query, 'ALTER TABLE comm_threads ADD PRIMARY KEY (id)')
330 do_query(query, 'ALTER TABLE dsos ADD PRIMARY KEY (id)')
331 do_query(query, 'ALTER TABLE symbols ADD PRIMARY KEY (id)')
332 do_query(query, 'ALTER TABLE branch_types ADD PRIMARY KEY (id)')
333 do_query(query, 'ALTER TABLE samples ADD PRIMARY KEY (id)')
334 if perf_db_export_calls:
335 do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)')
336 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)')
337
338 print datetime.datetime.today(), "Adding foreign keys"
339 do_query(query, 'ALTER TABLE threads '
340 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
341 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)')
342 do_query(query, 'ALTER TABLE comm_threads '
343 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
344 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id)')
345 do_query(query, 'ALTER TABLE dsos '
346 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id)')
347 do_query(query, 'ALTER TABLE symbols '
348 'ADD CONSTRAINT dsofk FOREIGN KEY (dso_id) REFERENCES dsos (id)')
349 do_query(query, 'ALTER TABLE samples '
350 'ADD CONSTRAINT evselfk FOREIGN KEY (evsel_id) REFERENCES selected_events (id),'
351 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
352 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'
353 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
354 'ADD CONSTRAINT dsofk FOREIGN KEY (dso_id) REFERENCES dsos (id),'
355 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id),'
356 'ADD CONSTRAINT todsofk FOREIGN KEY (to_dso_id) REFERENCES dsos (id),'
357 'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols (id)')
358 if perf_db_export_calls:
359 do_query(query, 'ALTER TABLE call_paths '
360 'ADD CONSTRAINT parentfk FOREIGN KEY (parent_id) REFERENCES call_paths (id),'
361 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id)')
362 do_query(query, 'ALTER TABLE calls '
363 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'
364 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
365 'ADD CONSTRAINT call_pathfk FOREIGN KEY (call_path_id) REFERENCES call_paths (id),'
366 'ADD CONSTRAINT callfk FOREIGN KEY (call_id) REFERENCES samples (id),'
367 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),'
368 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)')
369 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
370
371 if (unhandled_count):
372 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events"
373 print datetime.datetime.today(), "Done"
374
375def trace_unhandled(event_name, context, event_fields_dict):
376 global unhandled_count
377 unhandled_count += 1
378
379def sched__sched_switch(*x):
380 pass
381
382def evsel_table(evsel_id, evsel_name, *x):
383 n = len(evsel_name)
384 fmt = "!hiqi" + str(n) + "s"
385 value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name)
386 evsel_file.write(value)
387
388def machine_table(machine_id, pid, root_dir, *x):
389 n = len(root_dir)
390 fmt = "!hiqiii" + str(n) + "s"
391 value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir)
392 machine_file.write(value)
393
394def thread_table(thread_id, machine_id, process_id, pid, tid, *x):
395 value = struct.pack("!hiqiqiqiiii", 5, 8, thread_id, 8, machine_id, 8, process_id, 4, pid, 4, tid)
396 thread_file.write(value)
397
398def comm_table(comm_id, comm_str, *x):
399 n = len(comm_str)
400 fmt = "!hiqi" + str(n) + "s"
401 value = struct.pack(fmt, 2, 8, comm_id, n, comm_str)
402 comm_file.write(value)
403
404def comm_thread_table(comm_thread_id, comm_id, thread_id, *x):
405 fmt = "!hiqiqiq"
406 value = struct.pack(fmt, 3, 8, comm_thread_id, 8, comm_id, 8, thread_id)
407 comm_thread_file.write(value)
408
409def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x):
410 n1 = len(short_name)
411 n2 = len(long_name)
412 n3 = len(build_id)
413 fmt = "!hiqiqi" + str(n1) + "si" + str(n2) + "si" + str(n3) + "s"
414 value = struct.pack(fmt, 5, 8, dso_id, 8, machine_id, n1, short_name, n2, long_name, n3, build_id)
415 dso_file.write(value)
416
417def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x):
418 n = len(symbol_name)
419 fmt = "!hiqiqiqiqiii" + str(n) + "s"
420 value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name)
421 symbol_file.write(value)
422
423def branch_type_table(branch_type, name, *x):
424 n = len(name)
425 fmt = "!hiii" + str(n) + "s"
426 value = struct.pack(fmt, 2, 4, branch_type, n, name)
427 branch_type_file.write(value)
428
429def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, *x):
430 if branches:
431 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiB", 17, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx)
432 else:
433 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiB", 21, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx)
434 sample_file.write(value)
435
436def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
437 fmt = "!hiqiqiqiq"
438 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip)
439 call_path_file.write(value)
440
441def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x):
442 fmt = "!hiqiqiqiqiqiqiqiqiqiqii"
443 value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags)
444 call_file.write(value)
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index f710b92ccff6..d3095dafed36 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=96 8size=104
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 dc3ada2470c0..872ed7e24c7c 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=96 8size=104
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 162c978f1491..4b7d9ab0f049 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -85,7 +85,7 @@ static struct test {
85 .func = test__hists_link, 85 .func = test__hists_link,
86 }, 86 },
87 { 87 {
88 .desc = "Try 'use perf' in python, checking link problems", 88 .desc = "Try 'import perf' in python, checking link problems",
89 .func = test__python_use, 89 .func = test__python_use,
90 }, 90 },
91 { 91 {
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 67f2d6323558..f671ec37a7c4 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -133,8 +133,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
133} 133}
134 134
135static int read_object_code(u64 addr, size_t len, u8 cpumode, 135static int read_object_code(u64 addr, size_t len, u8 cpumode,
136 struct thread *thread, struct machine *machine, 136 struct thread *thread, struct state *state)
137 struct state *state)
138{ 137{
139 struct addr_location al; 138 struct addr_location al;
140 unsigned char buf1[BUFSZ]; 139 unsigned char buf1[BUFSZ];
@@ -145,8 +144,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
145 144
146 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 145 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
147 146
148 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr, 147 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
149 &al);
150 if (!al.map || !al.map->dso) { 148 if (!al.map || !al.map->dso) {
151 pr_debug("thread__find_addr_map failed\n"); 149 pr_debug("thread__find_addr_map failed\n");
152 return -1; 150 return -1;
@@ -170,8 +168,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
170 len = al.map->end - addr; 168 len = al.map->end - addr;
171 169
172 /* Read the object code using perf */ 170 /* Read the object code using perf */
173 ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1, 171 ret_len = dso__data_read_offset(al.map->dso, thread->mg->machine,
174 len); 172 al.addr, buf1, len);
175 if (ret_len != len) { 173 if (ret_len != len) {
176 pr_debug("dso__data_read_offset failed\n"); 174 pr_debug("dso__data_read_offset failed\n");
177 return -1; 175 return -1;
@@ -264,8 +262,7 @@ static int process_sample_event(struct machine *machine,
264 262
265 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 263 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
266 264
267 return read_object_code(sample.ip, READLEN, cpumode, thread, machine, 265 return read_object_code(sample.ip, READLEN, cpumode, thread, state);
268 state);
269} 266}
270 267
271static int process_event(struct machine *machine, struct perf_evlist *evlist, 268static int process_event(struct machine *machine, struct perf_evlist *evlist,
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index fc25e57f4a5d..ab28cca2cb97 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -59,7 +59,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
59} 59}
60 60
61__attribute__ ((noinline)) 61__attribute__ ((noinline))
62static int unwind_thread(struct thread *thread, struct machine *machine) 62static int unwind_thread(struct thread *thread)
63{ 63{
64 struct perf_sample sample; 64 struct perf_sample sample;
65 unsigned long cnt = 0; 65 unsigned long cnt = 0;
@@ -72,7 +72,7 @@ static int unwind_thread(struct thread *thread, struct machine *machine)
72 goto out; 72 goto out;
73 } 73 }
74 74
75 err = unwind__get_entries(unwind_entry, &cnt, machine, thread, 75 err = unwind__get_entries(unwind_entry, &cnt, thread,
76 &sample, MAX_STACK); 76 &sample, MAX_STACK);
77 if (err) 77 if (err)
78 pr_debug("unwind failed\n"); 78 pr_debug("unwind failed\n");
@@ -89,21 +89,21 @@ static int unwind_thread(struct thread *thread, struct machine *machine)
89} 89}
90 90
91__attribute__ ((noinline)) 91__attribute__ ((noinline))
92static int krava_3(struct thread *thread, struct machine *machine) 92static int krava_3(struct thread *thread)
93{ 93{
94 return unwind_thread(thread, machine); 94 return unwind_thread(thread);
95} 95}
96 96
97__attribute__ ((noinline)) 97__attribute__ ((noinline))
98static int krava_2(struct thread *thread, struct machine *machine) 98static int krava_2(struct thread *thread)
99{ 99{
100 return krava_3(thread, machine); 100 return krava_3(thread);
101} 101}
102 102
103__attribute__ ((noinline)) 103__attribute__ ((noinline))
104static int krava_1(struct thread *thread, struct machine *machine) 104static int krava_1(struct thread *thread)
105{ 105{
106 return krava_2(thread, machine); 106 return krava_2(thread);
107} 107}
108 108
109int test__dwarf_unwind(void) 109int test__dwarf_unwind(void)
@@ -137,7 +137,7 @@ int test__dwarf_unwind(void)
137 goto out; 137 goto out;
138 } 138 }
139 139
140 err = krava_1(thread, machine); 140 err = krava_1(thread);
141 141
142 out: 142 out:
143 machine__delete_threads(machine); 143 machine__delete_threads(machine);
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 5a31787cc6b9..74f257a81265 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -43,7 +43,7 @@ static struct sample fake_samples[] = {
43}; 43};
44 44
45static int add_hist_entries(struct perf_evlist *evlist, 45static int add_hist_entries(struct perf_evlist *evlist,
46 struct machine *machine __maybe_unused) 46 struct machine *machine)
47{ 47{
48 struct perf_evsel *evsel; 48 struct perf_evsel *evsel;
49 struct addr_location al; 49 struct addr_location al;
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 4a456fef66ca..2113f1c8611f 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -187,7 +187,7 @@ static int mmap_events(synth_cb synth)
187 187
188 pr_debug("looking for map %p\n", td->map); 188 pr_debug("looking for map %p\n", td->map);
189 189
190 thread__find_addr_map(thread, machine, 190 thread__find_addr_map(thread,
191 PERF_RECORD_MISC_USER, MAP__FUNCTION, 191 PERF_RECORD_MISC_USER, MAP__FUNCTION,
192 (unsigned long) (td->map + 1), &al); 192 (unsigned long) (td->map + 1), &al);
193 193
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index ca292f9a4ae2..4908c648a597 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -126,16 +126,28 @@ static bool samples_same(const struct perf_sample *s1,
126 if (type & PERF_SAMPLE_TRANSACTION) 126 if (type & PERF_SAMPLE_TRANSACTION)
127 COMP(transaction); 127 COMP(transaction);
128 128
129 if (type & PERF_SAMPLE_REGS_INTR) {
130 size_t sz = hweight_long(s1->intr_regs.mask) * sizeof(u64);
131
132 COMP(intr_regs.mask);
133 COMP(intr_regs.abi);
134 if (s1->intr_regs.abi &&
135 (!s1->intr_regs.regs || !s2->intr_regs.regs ||
136 memcmp(s1->intr_regs.regs, s2->intr_regs.regs, sz))) {
137 pr_debug("Samples differ at 'intr_regs'\n");
138 return false;
139 }
140 }
141
129 return true; 142 return true;
130} 143}
131 144
132static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) 145static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
133{ 146{
134 struct perf_evsel evsel = { 147 struct perf_evsel evsel = {
135 .needs_swap = false, 148 .needs_swap = false,
136 .attr = { 149 .attr = {
137 .sample_type = sample_type, 150 .sample_type = sample_type,
138 .sample_regs_user = sample_regs_user,
139 .read_format = read_format, 151 .read_format = read_format,
140 }, 152 },
141 }; 153 };
@@ -154,7 +166,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
154 /* 1 branch_entry */ 166 /* 1 branch_entry */
155 .data = {1, 211, 212, 213}, 167 .data = {1, 211, 212, 213},
156 }; 168 };
157 u64 user_regs[64]; 169 u64 regs[64];
158 const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL}; 170 const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL};
159 const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; 171 const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL};
160 struct perf_sample sample = { 172 struct perf_sample sample = {
@@ -176,8 +188,8 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
176 .branch_stack = &branch_stack.branch_stack, 188 .branch_stack = &branch_stack.branch_stack,
177 .user_regs = { 189 .user_regs = {
178 .abi = PERF_SAMPLE_REGS_ABI_64, 190 .abi = PERF_SAMPLE_REGS_ABI_64,
179 .mask = sample_regs_user, 191 .mask = sample_regs,
180 .regs = user_regs, 192 .regs = regs,
181 }, 193 },
182 .user_stack = { 194 .user_stack = {
183 .size = sizeof(data), 195 .size = sizeof(data),
@@ -187,14 +199,25 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
187 .time_enabled = 0x030a59d664fca7deULL, 199 .time_enabled = 0x030a59d664fca7deULL,
188 .time_running = 0x011b6ae553eb98edULL, 200 .time_running = 0x011b6ae553eb98edULL,
189 }, 201 },
202 .intr_regs = {
203 .abi = PERF_SAMPLE_REGS_ABI_64,
204 .mask = sample_regs,
205 .regs = regs,
206 },
190 }; 207 };
191 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; 208 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
192 struct perf_sample sample_out; 209 struct perf_sample sample_out;
193 size_t i, sz, bufsz; 210 size_t i, sz, bufsz;
194 int err, ret = -1; 211 int err, ret = -1;
195 212
196 for (i = 0; i < sizeof(user_regs); i++) 213 if (sample_type & PERF_SAMPLE_REGS_USER)
197 *(i + (u8 *)user_regs) = i & 0xfe; 214 evsel.attr.sample_regs_user = sample_regs;
215
216 if (sample_type & PERF_SAMPLE_REGS_INTR)
217 evsel.attr.sample_regs_intr = sample_regs;
218
219 for (i = 0; i < sizeof(regs); i++)
220 *(i + (u8 *)regs) = i & 0xfe;
198 221
199 if (read_format & PERF_FORMAT_GROUP) { 222 if (read_format & PERF_FORMAT_GROUP) {
200 sample.read.group.nr = 4; 223 sample.read.group.nr = 4;
@@ -271,7 +294,7 @@ int test__sample_parsing(void)
271{ 294{
272 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; 295 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
273 u64 sample_type; 296 u64 sample_type;
274 u64 sample_regs_user; 297 u64 sample_regs;
275 size_t i; 298 size_t i;
276 int err; 299 int err;
277 300
@@ -280,7 +303,7 @@ int test__sample_parsing(void)
280 * were added. Please actually update the test rather than just change 303 * were added. Please actually update the test rather than just change
281 * the condition below. 304 * the condition below.
282 */ 305 */
283 if (PERF_SAMPLE_MAX > PERF_SAMPLE_TRANSACTION << 1) { 306 if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) {
284 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); 307 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
285 return -1; 308 return -1;
286 } 309 }
@@ -297,22 +320,24 @@ int test__sample_parsing(void)
297 } 320 }
298 continue; 321 continue;
299 } 322 }
323 sample_regs = 0;
300 324
301 if (sample_type == PERF_SAMPLE_REGS_USER) 325 if (sample_type == PERF_SAMPLE_REGS_USER)
302 sample_regs_user = 0x3fff; 326 sample_regs = 0x3fff;
303 else 327
304 sample_regs_user = 0; 328 if (sample_type == PERF_SAMPLE_REGS_INTR)
329 sample_regs = 0xff0fff;
305 330
306 err = do_test(sample_type, sample_regs_user, 0); 331 err = do_test(sample_type, sample_regs, 0);
307 if (err) 332 if (err)
308 return err; 333 return err;
309 } 334 }
310 335
311 /* Test all sample format bits together */ 336 /* Test all sample format bits together */
312 sample_type = PERF_SAMPLE_MAX - 1; 337 sample_type = PERF_SAMPLE_MAX - 1;
313 sample_regs_user = 0x3fff; 338 sample_regs = 0x3fff; /* shared yb intr and user regs */
314 for (i = 0; i < ARRAY_SIZE(rf); i++) { 339 for (i = 0; i < ARRAY_SIZE(rf); i++) {
315 err = do_test(sample_type, sample_regs_user, rf[i]); 340 err = do_test(sample_type, sample_regs, rf[i]);
316 if (err) 341 if (err)
317 return err; 342 return err;
318 } 343 }
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index f0697a3aede0..1e0a2fd80115 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -27,6 +27,7 @@ static struct annotate_browser_opt {
27 bool hide_src_code, 27 bool hide_src_code,
28 use_offset, 28 use_offset,
29 jump_arrows, 29 jump_arrows,
30 show_linenr,
30 show_nr_jumps; 31 show_nr_jumps;
31} annotate_browser__opts = { 32} annotate_browser__opts = {
32 .use_offset = true, 33 .use_offset = true,
@@ -128,7 +129,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
128 if (!*dl->line) 129 if (!*dl->line)
129 slsmg_write_nstring(" ", width - pcnt_width); 130 slsmg_write_nstring(" ", width - pcnt_width);
130 else if (dl->offset == -1) { 131 else if (dl->offset == -1) {
131 printed = scnprintf(bf, sizeof(bf), "%*s ", 132 if (dl->line_nr && annotate_browser__opts.show_linenr)
133 printed = scnprintf(bf, sizeof(bf), "%-*d ",
134 ab->addr_width + 1, dl->line_nr);
135 else
136 printed = scnprintf(bf, sizeof(bf), "%*s ",
132 ab->addr_width, " "); 137 ab->addr_width, " ");
133 slsmg_write_nstring(bf, printed); 138 slsmg_write_nstring(bf, printed);
134 slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); 139 slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1);
@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
733 "o Toggle disassembler output/simplified view\n" 738 "o Toggle disassembler output/simplified view\n"
734 "s Toggle source code view\n" 739 "s Toggle source code view\n"
735 "/ Search string\n" 740 "/ Search string\n"
741 "k Toggle line numbers\n"
736 "r Run available scripts\n" 742 "r Run available scripts\n"
737 "? Search string backwards\n"); 743 "? Search string backwards\n");
738 continue; 744 continue;
@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser,
741 script_browse(NULL); 747 script_browse(NULL);
742 continue; 748 continue;
743 } 749 }
750 case 'k':
751 annotate_browser__opts.show_linenr =
752 !annotate_browser__opts.show_linenr;
753 break;
744 case 'H': 754 case 'H':
745 nd = browser->curr_hot; 755 nd = browser->curr_hot;
746 break; 756 break;
@@ -984,6 +994,7 @@ static struct annotate_config {
984} annotate__configs[] = { 994} annotate__configs[] = {
985 ANNOTATE_CFG(hide_src_code), 995 ANNOTATE_CFG(hide_src_code),
986 ANNOTATE_CFG(jump_arrows), 996 ANNOTATE_CFG(jump_arrows),
997 ANNOTATE_CFG(show_linenr),
987 ANNOTATE_CFG(show_nr_jumps), 998 ANNOTATE_CFG(show_nr_jumps),
988 ANNOTATE_CFG(use_offset), 999 ANNOTATE_CFG(use_offset),
989}; 1000};
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index cfb976b3de3a..e6bb04b5b09b 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -227,10 +227,14 @@ static void callchain_node__init_have_children_rb_tree(struct callchain_node *no
227 } 227 }
228} 228}
229 229
230static void callchain_node__init_have_children(struct callchain_node *node) 230static void callchain_node__init_have_children(struct callchain_node *node,
231 bool has_sibling)
231{ 232{
232 struct callchain_list *chain; 233 struct callchain_list *chain;
233 234
235 chain = list_entry(node->val.next, struct callchain_list, list);
236 chain->ms.has_children = has_sibling;
237
234 if (!list_empty(&node->val)) { 238 if (!list_empty(&node->val)) {
235 chain = list_entry(node->val.prev, struct callchain_list, list); 239 chain = list_entry(node->val.prev, struct callchain_list, list);
236 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); 240 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root);
@@ -241,11 +245,12 @@ static void callchain_node__init_have_children(struct callchain_node *node)
241 245
242static void callchain__init_have_children(struct rb_root *root) 246static void callchain__init_have_children(struct rb_root *root)
243{ 247{
244 struct rb_node *nd; 248 struct rb_node *nd = rb_first(root);
249 bool has_sibling = nd && rb_next(nd);
245 250
246 for (nd = rb_first(root); nd; nd = rb_next(nd)) { 251 for (nd = rb_first(root); nd; nd = rb_next(nd)) {
247 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 252 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
248 callchain_node__init_have_children(node); 253 callchain_node__init_have_children(node, has_sibling);
249 } 254 }
250} 255}
251 256
@@ -463,23 +468,6 @@ out:
463 return key; 468 return key;
464} 469}
465 470
466static char *callchain_list__sym_name(struct callchain_list *cl,
467 char *bf, size_t bfsize, bool show_dso)
468{
469 int printed;
470
471 if (cl->ms.sym)
472 printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
473 else
474 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
475
476 if (show_dso)
477 scnprintf(bf + printed, bfsize - printed, " %s",
478 cl->ms.map ? cl->ms.map->dso->short_name : "unknown");
479
480 return bf;
481}
482
483struct callchain_print_arg { 471struct callchain_print_arg {
484 /* for hists browser */ 472 /* for hists browser */
485 off_t row_offset; 473 off_t row_offset;
@@ -559,8 +547,11 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
559 struct rb_node *node; 547 struct rb_node *node;
560 int first_row = row, offset = level * LEVEL_OFFSET_STEP; 548 int first_row = row, offset = level * LEVEL_OFFSET_STEP;
561 u64 new_total; 549 u64 new_total;
550 bool need_percent;
562 551
563 node = rb_first(root); 552 node = rb_first(root);
553 need_percent = !!rb_next(node);
554
564 while (node) { 555 while (node) {
565 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 556 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
566 struct rb_node *next = rb_next(node); 557 struct rb_node *next = rb_next(node);
@@ -577,7 +568,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
577 568
578 if (first) 569 if (first)
579 first = false; 570 first = false;
580 else if (level > 1) 571 else if (need_percent)
581 extra_offset = LEVEL_OFFSET_STEP; 572 extra_offset = LEVEL_OFFSET_STEP;
582 573
583 folded_sign = callchain_list__folded(chain); 574 folded_sign = callchain_list__folded(chain);
@@ -590,7 +581,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
590 str = callchain_list__sym_name(chain, bf, sizeof(bf), 581 str = callchain_list__sym_name(chain, bf, sizeof(bf),
591 browser->show_dso); 582 browser->show_dso);
592 583
593 if (was_first && level > 1) { 584 if (was_first && need_percent) {
594 double percent = cumul * 100.0 / total; 585 double percent = cumul * 100.0 / total;
595 586
596 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) 587 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
@@ -807,6 +798,13 @@ static int hist_browser__show_entry(struct hist_browser *browser,
807 .is_current_entry = current_entry, 798 .is_current_entry = current_entry,
808 }; 799 };
809 800
801 if (callchain_param.mode == CHAIN_GRAPH_REL) {
802 if (symbol_conf.cumulate_callchain)
803 total = entry->stat_acc->period;
804 else
805 total = entry->stat.period;
806 }
807
810 printed += hist_browser__show_callchain(browser, 808 printed += hist_browser__show_callchain(browser,
811 &entry->sorted_chain, 1, row, total, 809 &entry->sorted_chain, 1, row, total,
812 hist_browser__show_callchain_entry, &arg, 810 hist_browser__show_callchain_entry, &arg,
@@ -1254,7 +1252,7 @@ static int hists__browser_title(struct hists *hists,
1254 1252
1255 nr_samples = convert_unit(nr_samples, &unit); 1253 nr_samples = convert_unit(nr_samples, &unit);
1256 printed = scnprintf(bf, size, 1254 printed = scnprintf(bf, size,
1257 "Samples: %lu%c of event '%s', Event count (approx.): %lu", 1255 "Samples: %lu%c of event '%s', Event count (approx.): %" PRIu64,
1258 nr_samples, unit, ev_name, nr_events); 1256 nr_samples, unit, ev_name, nr_events);
1259 1257
1260 1258
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index fc654fb77ace..4b3585eed1e8 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -89,15 +89,6 @@ void perf_gtk__init_hpp(void)
89 perf_gtk__hpp_color_overhead_acc; 89 perf_gtk__hpp_color_overhead_acc;
90} 90}
91 91
92static void callchain_list__sym_name(struct callchain_list *cl,
93 char *bf, size_t bfsize)
94{
95 if (cl->ms.sym)
96 scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
97 else
98 scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
99}
100
101static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, 92static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
102 GtkTreeIter *parent, int col, u64 total) 93 GtkTreeIter *parent, int col, u64 total)
103{ 94{
@@ -128,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
128 scnprintf(buf, sizeof(buf), "%5.2f%%", percent); 119 scnprintf(buf, sizeof(buf), "%5.2f%%", percent);
129 gtk_tree_store_set(store, &iter, 0, buf, -1); 120 gtk_tree_store_set(store, &iter, 0, buf, -1);
130 121
131 callchain_list__sym_name(chain, buf, sizeof(buf)); 122 callchain_list__sym_name(chain, buf, sizeof(buf), false);
132 gtk_tree_store_set(store, &iter, col, buf, -1); 123 gtk_tree_store_set(store, &iter, col, buf, -1);
133 124
134 if (need_new_parent) { 125 if (need_new_parent) {
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 2af18376b077..dc0d095f318c 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -162,8 +162,8 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b,
162 return ret; 162 return ret;
163 163
164 nr_members = evsel->nr_members; 164 nr_members = evsel->nr_members;
165 fields_a = calloc(sizeof(*fields_a), nr_members); 165 fields_a = calloc(nr_members, sizeof(*fields_a));
166 fields_b = calloc(sizeof(*fields_b), nr_members); 166 fields_b = calloc(nr_members, sizeof(*fields_b));
167 167
168 if (!fields_a || !fields_b) 168 if (!fields_a || !fields_b)
169 goto out; 169 goto out;
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 15b451acbde6..dfcbc90146ef 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
41{ 41{
42 int i; 42 int i;
43 size_t ret = 0; 43 size_t ret = 0;
44 char bf[1024];
44 45
45 ret += callchain__fprintf_left_margin(fp, left_margin); 46 ret += callchain__fprintf_left_margin(fp, left_margin);
46 for (i = 0; i < depth; i++) { 47 for (i = 0; i < depth; i++) {
@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
56 } else 57 } else
57 ret += fprintf(fp, "%s", " "); 58 ret += fprintf(fp, "%s", " ");
58 } 59 }
59 if (chain->ms.sym) 60 fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp);
60 ret += fprintf(fp, "%s\n", chain->ms.sym->name); 61 fputc('\n', fp);
61 else
62 ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
63
64 return ret; 62 return ret;
65} 63}
66 64
@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
168 struct rb_node *node; 166 struct rb_node *node;
169 int i = 0; 167 int i = 0;
170 int ret = 0; 168 int ret = 0;
169 char bf[1024];
171 170
172 /* 171 /*
173 * If have one single callchain root, don't bother printing 172 * If have one single callchain root, don't bother printing
@@ -196,10 +195,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
196 } else 195 } else
197 ret += callchain__fprintf_left_margin(fp, left_margin); 196 ret += callchain__fprintf_left_margin(fp, left_margin);
198 197
199 if (chain->ms.sym) 198 ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf),
200 ret += fprintf(fp, " %s\n", chain->ms.sym->name); 199 false));
201 else
202 ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
203 200
204 if (++entries_printed == callchain_param.print_limit) 201 if (++entries_printed == callchain_param.print_limit)
205 break; 202 break;
@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
219{ 216{
220 struct callchain_list *chain; 217 struct callchain_list *chain;
221 size_t ret = 0; 218 size_t ret = 0;
219 char bf[1024];
222 220
223 if (!node) 221 if (!node)
224 return 0; 222 return 0;
@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
229 list_for_each_entry(chain, &node->val, list) { 227 list_for_each_entry(chain, &node->val, list) {
230 if (chain->ip >= PERF_CONTEXT_MAX) 228 if (chain->ip >= PERF_CONTEXT_MAX)
231 continue; 229 continue;
232 if (chain->ms.sym) 230 ret += fprintf(fp, " %s\n", callchain_list__sym_name(chain,
233 ret += fprintf(fp, " %s\n", chain->ms.sym->name); 231 bf, sizeof(bf), false));
234 else
235 ret += fprintf(fp, " %p\n",
236 (void *)(long)chain->ip);
237 } 232 }
238 233
239 return ret; 234 return ret;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7dabde14ea54..79999ceaf2be 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -17,11 +17,13 @@
17#include "debug.h" 17#include "debug.h"
18#include "annotate.h" 18#include "annotate.h"
19#include "evsel.h" 19#include "evsel.h"
20#include <regex.h>
20#include <pthread.h> 21#include <pthread.h>
21#include <linux/bitops.h> 22#include <linux/bitops.h>
22 23
23const char *disassembler_style; 24const char *disassembler_style;
24const char *objdump_path; 25const char *objdump_path;
26static regex_t file_lineno;
25 27
26static struct ins *ins__find(const char *name); 28static struct ins *ins__find(const char *name);
27static int disasm_line__parse(char *line, char **namep, char **rawp); 29static int disasm_line__parse(char *line, char **namep, char **rawp);
@@ -570,13 +572,15 @@ out_free_name:
570 return -1; 572 return -1;
571} 573}
572 574
573static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) 575static struct disasm_line *disasm_line__new(s64 offset, char *line,
576 size_t privsize, int line_nr)
574{ 577{
575 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); 578 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
576 579
577 if (dl != NULL) { 580 if (dl != NULL) {
578 dl->offset = offset; 581 dl->offset = offset;
579 dl->line = strdup(line); 582 dl->line = strdup(line);
583 dl->line_nr = line_nr;
580 if (dl->line == NULL) 584 if (dl->line == NULL)
581 goto out_delete; 585 goto out_delete;
582 586
@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
788 * The ops.raw part will be parsed further according to type of the instruction. 792 * The ops.raw part will be parsed further according to type of the instruction.
789 */ 793 */
790static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, 794static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
791 FILE *file, size_t privsize) 795 FILE *file, size_t privsize,
796 int *line_nr)
792{ 797{
793 struct annotation *notes = symbol__annotation(sym); 798 struct annotation *notes = symbol__annotation(sym);
794 struct disasm_line *dl; 799 struct disasm_line *dl;
795 char *line = NULL, *parsed_line, *tmp, *tmp2, *c; 800 char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
796 size_t line_len; 801 size_t line_len;
797 s64 line_ip, offset = -1; 802 s64 line_ip, offset = -1;
803 regmatch_t match[2];
798 804
799 if (getline(&line, &line_len, file) < 0) 805 if (getline(&line, &line_len, file) < 0)
800 return -1; 806 return -1;
@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
812 line_ip = -1; 818 line_ip = -1;
813 parsed_line = line; 819 parsed_line = line;
814 820
821 /* /filename:linenr ? Save line number and ignore. */
822 if (regexec(&file_lineno, line, 2, match, 0) == 0) {
823 *line_nr = atoi(line + match[1].rm_so);
824 return 0;
825 }
826
815 /* 827 /*
816 * Strip leading spaces: 828 * Strip leading spaces:
817 */ 829 */
@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
842 parsed_line = tmp2 + 1; 854 parsed_line = tmp2 + 1;
843 } 855 }
844 856
845 dl = disasm_line__new(offset, parsed_line, privsize); 857 dl = disasm_line__new(offset, parsed_line, privsize, *line_nr);
846 free(line); 858 free(line);
859 (*line_nr)++;
847 860
848 if (dl == NULL) 861 if (dl == NULL)
849 return -1; 862 return -1;
@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
869 return 0; 882 return 0;
870} 883}
871 884
885static __attribute__((constructor)) void symbol__init_regexpr(void)
886{
887 regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
888}
889
872static void delete_last_nop(struct symbol *sym) 890static void delete_last_nop(struct symbol *sym)
873{ 891{
874 struct annotation *notes = symbol__annotation(sym); 892 struct annotation *notes = symbol__annotation(sym);
@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
904 char symfs_filename[PATH_MAX]; 922 char symfs_filename[PATH_MAX];
905 struct kcore_extract kce; 923 struct kcore_extract kce;
906 bool delete_extract = false; 924 bool delete_extract = false;
925 int lineno = 0;
907 926
908 if (filename) 927 if (filename)
909 symbol__join_symfs(symfs_filename, filename); 928 symbol__join_symfs(symfs_filename, filename);
@@ -915,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
915 return -ENOMEM; 934 return -ENOMEM;
916 } 935 }
917 goto fallback; 936 goto fallback;
937 } else if (dso__is_kcore(dso)) {
938 goto fallback;
918 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 939 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
919 strstr(command, "[kernel.kallsyms]") || 940 strstr(command, "[kernel.kallsyms]") ||
920 access(symfs_filename, R_OK)) { 941 access(symfs_filename, R_OK)) {
@@ -982,7 +1003,7 @@ fallback:
982 snprintf(command, sizeof(command), 1003 snprintf(command, sizeof(command),
983 "%s %s%s --start-address=0x%016" PRIx64 1004 "%s %s%s --start-address=0x%016" PRIx64
984 " --stop-address=0x%016" PRIx64 1005 " --stop-address=0x%016" PRIx64
985 " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", 1006 " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
986 objdump_path ? objdump_path : "objdump", 1007 objdump_path ? objdump_path : "objdump",
987 disassembler_style ? "-M " : "", 1008 disassembler_style ? "-M " : "",
988 disassembler_style ? disassembler_style : "", 1009 disassembler_style ? disassembler_style : "",
@@ -999,7 +1020,8 @@ fallback:
999 goto out_free_filename; 1020 goto out_free_filename;
1000 1021
1001 while (!feof(file)) 1022 while (!feof(file))
1002 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) 1023 if (symbol__parse_objdump_line(sym, map, file, privsize,
1024 &lineno) < 0)
1003 break; 1025 break;
1004 1026
1005 /* 1027 /*
@@ -1170,7 +1192,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1170 goto next; 1192 goto next;
1171 1193
1172 offset = start + i; 1194 offset = start + i;
1173 src_line->path = get_srcline(map->dso, offset); 1195 src_line->path = get_srcline(map->dso, offset, NULL, false);
1174 insert_source_line(&tmp_root, src_line); 1196 insert_source_line(&tmp_root, src_line);
1175 1197
1176 next: 1198 next:
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 112d6e268150..0784a9420528 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -58,6 +58,7 @@ struct disasm_line {
58 char *line; 58 char *line;
59 char *name; 59 char *name;
60 struct ins *ins; 60 struct ins *ins;
61 int line_nr;
61 struct ins_operands ops; 62 struct ins_operands ops;
62}; 63};
63 64
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a904a4cfe7d3..0c72680a977f 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -15,6 +15,11 @@
15#include "debug.h" 15#include "debug.h"
16#include "session.h" 16#include "session.h"
17#include "tool.h" 17#include "tool.h"
18#include "header.h"
19#include "vdso.h"
20
21
22static bool no_buildid_cache;
18 23
19int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, 24int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
20 union perf_event *event, 25 union perf_event *event,
@@ -33,8 +38,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
33 return -1; 38 return -1;
34 } 39 }
35 40
36 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 41 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al);
37 sample->ip, &al);
38 42
39 if (al.map != NULL) 43 if (al.map != NULL)
40 al.map->dso->hit = 1; 44 al.map->dso->hit = 1;
@@ -106,3 +110,340 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
106 build_id_hex, build_id_hex + 2); 110 build_id_hex, build_id_hex + 2);
107 return bf; 111 return bf;
108} 112}
113
114#define dsos__for_each_with_build_id(pos, head) \
115 list_for_each_entry(pos, head, node) \
116 if (!pos->has_build_id) \
117 continue; \
118 else
119
120static int write_buildid(const char *name, size_t name_len, u8 *build_id,
121 pid_t pid, u16 misc, int fd)
122{
123 int err;
124 struct build_id_event b;
125 size_t len;
126
127 len = name_len + 1;
128 len = PERF_ALIGN(len, NAME_ALIGN);
129
130 memset(&b, 0, sizeof(b));
131 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
132 b.pid = pid;
133 b.header.misc = misc;
134 b.header.size = sizeof(b) + len;
135
136 err = writen(fd, &b, sizeof(b));
137 if (err < 0)
138 return err;
139
140 return write_padded(fd, name, name_len + 1, len);
141}
142
143static int __dsos__write_buildid_table(struct list_head *head,
144 struct machine *machine,
145 pid_t pid, u16 misc, int fd)
146{
147 char nm[PATH_MAX];
148 struct dso *pos;
149
150 dsos__for_each_with_build_id(pos, head) {
151 int err;
152 const char *name;
153 size_t name_len;
154
155 if (!pos->hit)
156 continue;
157
158 if (dso__is_vdso(pos)) {
159 name = pos->short_name;
160 name_len = pos->short_name_len + 1;
161 } else if (dso__is_kcore(pos)) {
162 machine__mmap_name(machine, nm, sizeof(nm));
163 name = nm;
164 name_len = strlen(nm) + 1;
165 } else {
166 name = pos->long_name;
167 name_len = pos->long_name_len + 1;
168 }
169
170 err = write_buildid(name, name_len, pos->build_id,
171 pid, misc, fd);
172 if (err)
173 return err;
174 }
175
176 return 0;
177}
178
179static int machine__write_buildid_table(struct machine *machine, int fd)
180{
181 int err;
182 u16 kmisc = PERF_RECORD_MISC_KERNEL,
183 umisc = PERF_RECORD_MISC_USER;
184
185 if (!machine__is_host(machine)) {
186 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
187 umisc = PERF_RECORD_MISC_GUEST_USER;
188 }
189
190 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
191 machine->pid, kmisc, fd);
192 if (err == 0)
193 err = __dsos__write_buildid_table(&machine->user_dsos.head,
194 machine, machine->pid, umisc,
195 fd);
196 return err;
197}
198
199int perf_session__write_buildid_table(struct perf_session *session, int fd)
200{
201 struct rb_node *nd;
202 int err = machine__write_buildid_table(&session->machines.host, fd);
203
204 if (err)
205 return err;
206
207 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
208 struct machine *pos = rb_entry(nd, struct machine, rb_node);
209 err = machine__write_buildid_table(pos, fd);
210 if (err)
211 break;
212 }
213 return err;
214}
215
216static int __dsos__hit_all(struct list_head *head)
217{
218 struct dso *pos;
219
220 list_for_each_entry(pos, head, node)
221 pos->hit = true;
222
223 return 0;
224}
225
226static int machine__hit_all_dsos(struct machine *machine)
227{
228 int err;
229
230 err = __dsos__hit_all(&machine->kernel_dsos.head);
231 if (err)
232 return err;
233
234 return __dsos__hit_all(&machine->user_dsos.head);
235}
236
237int dsos__hit_all(struct perf_session *session)
238{
239 struct rb_node *nd;
240 int err;
241
242 err = machine__hit_all_dsos(&session->machines.host);
243 if (err)
244 return err;
245
246 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
247 struct machine *pos = rb_entry(nd, struct machine, rb_node);
248
249 err = machine__hit_all_dsos(pos);
250 if (err)
251 return err;
252 }
253
254 return 0;
255}
256
257void disable_buildid_cache(void)
258{
259 no_buildid_cache = true;
260}
261
262int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
263 const char *name, bool is_kallsyms, bool is_vdso)
264{
265 const size_t size = PATH_MAX;
266 char *realname, *filename = zalloc(size),
267 *linkname = zalloc(size), *targetname;
268 int len, err = -1;
269 bool slash = is_kallsyms || is_vdso;
270
271 if (is_kallsyms) {
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);
280
281 if (realname == NULL || filename == NULL || linkname == NULL)
282 goto out_free;
283
284 len = scnprintf(filename, size, "%s%s%s",
285 debugdir, slash ? "/" : "",
286 is_vdso ? DSO__NAME_VDSO : realname);
287 if (mkdir_p(filename, 0755))
288 goto out_free;
289
290 snprintf(filename + len, size - len, "/%s", sbuild_id);
291
292 if (access(filename, F_OK)) {
293 if (is_kallsyms) {
294 if (copyfile("/proc/kallsyms", filename))
295 goto out_free;
296 } else if (link(realname, filename) && copyfile(name, filename))
297 goto out_free;
298 }
299
300 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
301 debugdir, sbuild_id);
302
303 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
304 goto out_free;
305
306 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
307 targetname = filename + strlen(debugdir) - 5;
308 memcpy(targetname, "../..", 5);
309
310 if (symlink(targetname, linkname) == 0)
311 err = 0;
312out_free:
313 if (!is_kallsyms)
314 free(realname);
315 free(filename);
316 free(linkname);
317 return err;
318}
319
320static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
321 const char *name, const char *debugdir,
322 bool is_kallsyms, bool is_vdso)
323{
324 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
325
326 build_id__sprintf(build_id, build_id_size, sbuild_id);
327
328 return build_id_cache__add_s(sbuild_id, debugdir, name,
329 is_kallsyms, is_vdso);
330}
331
332int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
333{
334 const size_t size = PATH_MAX;
335 char *filename = zalloc(size),
336 *linkname = zalloc(size);
337 int err = -1;
338
339 if (filename == NULL || linkname == NULL)
340 goto out_free;
341
342 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
343 debugdir, sbuild_id, sbuild_id + 2);
344
345 if (access(linkname, F_OK))
346 goto out_free;
347
348 if (readlink(linkname, filename, size - 1) < 0)
349 goto out_free;
350
351 if (unlink(linkname))
352 goto out_free;
353
354 /*
355 * Since the link is relative, we must make it absolute:
356 */
357 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
358 debugdir, sbuild_id, filename);
359
360 if (unlink(linkname))
361 goto out_free;
362
363 err = 0;
364out_free:
365 free(filename);
366 free(linkname);
367 return err;
368}
369
370static int dso__cache_build_id(struct dso *dso, struct machine *machine,
371 const char *debugdir)
372{
373 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
374 bool is_vdso = dso__is_vdso(dso);
375 const char *name = dso->long_name;
376 char nm[PATH_MAX];
377
378 if (dso__is_kcore(dso)) {
379 is_kallsyms = true;
380 machine__mmap_name(machine, nm, sizeof(nm));
381 name = nm;
382 }
383 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
384 debugdir, is_kallsyms, is_vdso);
385}
386
387static int __dsos__cache_build_ids(struct list_head *head,
388 struct machine *machine, const char *debugdir)
389{
390 struct dso *pos;
391 int err = 0;
392
393 dsos__for_each_with_build_id(pos, head)
394 if (dso__cache_build_id(pos, machine, debugdir))
395 err = -1;
396
397 return err;
398}
399
400static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
401{
402 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
403 debugdir);
404 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
405 debugdir);
406 return ret;
407}
408
409int perf_session__cache_build_ids(struct perf_session *session)
410{
411 struct rb_node *nd;
412 int ret;
413
414 if (no_buildid_cache)
415 return 0;
416
417 if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST)
418 return -1;
419
420 ret = machine__cache_build_ids(&session->machines.host, buildid_dir);
421
422 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
423 struct machine *pos = rb_entry(nd, struct machine, rb_node);
424 ret |= machine__cache_build_ids(pos, buildid_dir);
425 }
426 return ret ? -1 : 0;
427}
428
429static bool machine__read_build_ids(struct machine *machine, bool with_hits)
430{
431 bool ret;
432
433 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
434 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
435 return ret;
436}
437
438bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
439{
440 struct rb_node *nd;
441 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
442
443 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
444 struct machine *pos = rb_entry(nd, struct machine, rb_node);
445 ret |= machine__read_build_ids(pos, with_hits);
446 }
447
448 return ret;
449}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index ae392561470b..8236319514d5 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -15,4 +15,16 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
16 struct perf_sample *sample, struct perf_evsel *evsel, 16 struct perf_sample *sample, struct perf_evsel *evsel,
17 struct machine *machine); 17 struct machine *machine);
18
19int dsos__hit_all(struct perf_session *session);
20
21bool 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__cache_build_ids(struct perf_session *session);
24
25int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
26 const char *name, bool is_kallsyms, bool is_vdso);
27int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
28void disable_buildid_cache(void);
29
18#endif 30#endif
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index c84d3f8dcb75..64b377e591e4 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -77,7 +77,7 @@ int parse_callchain_record_opt(const char *arg)
77 ret = 0; 77 ret = 0;
78 } else 78 } else
79 pr_err("callchain: No more arguments " 79 pr_err("callchain: No more arguments "
80 "needed for -g fp\n"); 80 "needed for --call-graph fp\n");
81 break; 81 break;
82 82
83#ifdef HAVE_DWARF_UNWIND_SUPPORT 83#ifdef HAVE_DWARF_UNWIND_SUPPORT
@@ -149,6 +149,10 @@ static int parse_callchain_sort_key(const char *value)
149 callchain_param.key = CCKEY_ADDRESS; 149 callchain_param.key = CCKEY_ADDRESS;
150 return 0; 150 return 0;
151 } 151 }
152 if (!strncmp(value, "branch", strlen(value))) {
153 callchain_param.branch_callstack = 1;
154 return 0;
155 }
152 return -1; 156 return -1;
153} 157}
154 158
@@ -754,8 +758,8 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
754 758
755 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || 759 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
756 sort__has_parent) { 760 sort__has_parent) {
757 return machine__resolve_callchain(al->machine, evsel, al->thread, 761 return thread__resolve_callchain(al->thread, evsel, sample,
758 sample, parent, al, max_stack); 762 parent, al, max_stack);
759 } 763 }
760 return 0; 764 return 0;
761} 765}
@@ -808,3 +812,32 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
808out: 812out:
809 return 1; 813 return 1;
810} 814}
815
816char *callchain_list__sym_name(struct callchain_list *cl,
817 char *bf, size_t bfsize, bool show_dso)
818{
819 int printed;
820
821 if (cl->ms.sym) {
822 if (callchain_param.key == CCKEY_ADDRESS &&
823 cl->ms.map && !cl->srcline)
824 cl->srcline = get_srcline(cl->ms.map->dso,
825 map__rip_2objdump(cl->ms.map,
826 cl->ip),
827 cl->ms.sym, false);
828 if (cl->srcline)
829 printed = scnprintf(bf, bfsize, "%s %s",
830 cl->ms.sym->name, cl->srcline);
831 else
832 printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
833 } else
834 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
835
836 if (show_dso)
837 scnprintf(bf + printed, bfsize - printed, " %s",
838 cl->ms.map ?
839 cl->ms.map->dso->short_name :
840 "unknown");
841
842 return bf;
843}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 94cfefddf4db..dbc08cf5f970 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -63,6 +63,7 @@ struct callchain_param {
63 sort_chain_func_t sort; 63 sort_chain_func_t sort;
64 enum chain_order order; 64 enum chain_order order;
65 enum chain_key key; 65 enum chain_key key;
66 bool branch_callstack;
66}; 67};
67 68
68extern struct callchain_param callchain_param; 69extern struct callchain_param callchain_param;
@@ -70,6 +71,7 @@ extern struct callchain_param callchain_param;
70struct callchain_list { 71struct callchain_list {
71 u64 ip; 72 u64 ip;
72 struct map_symbol ms; 73 struct map_symbol ms;
74 char *srcline;
73 struct list_head list; 75 struct list_head list;
74}; 76};
75 77
@@ -184,15 +186,16 @@ static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
184} 186}
185 187
186#ifdef HAVE_SKIP_CALLCHAIN_IDX 188#ifdef HAVE_SKIP_CALLCHAIN_IDX
187extern int arch_skip_callchain_idx(struct machine *machine, 189extern int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain);
188 struct thread *thread, struct ip_callchain *chain);
189#else 190#else
190static inline int arch_skip_callchain_idx(struct machine *machine __maybe_unused, 191static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
191 struct thread *thread __maybe_unused,
192 struct ip_callchain *chain __maybe_unused) 192 struct ip_callchain *chain __maybe_unused)
193{ 193{
194 return -1; 194 return -1;
195} 195}
196#endif 196#endif
197 197
198char *callchain_list__sym_name(struct callchain_list *cl,
199 char *bf, size_t bfsize, bool show_dso);
200
198#endif /* __PERF_CALLCHAIN_H */ 201#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index 51c10ab257f8..71c9c39340d4 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -12,6 +12,10 @@ struct comm {
12 u64 start; 12 u64 start;
13 struct list_head list; 13 struct list_head list;
14 bool exec; 14 bool exec;
15 union { /* Tool specific area */
16 void *priv;
17 u64 db_id;
18 };
15}; 19};
16 20
17void comm__free(struct comm *comm); 21void comm__free(struct comm *comm);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 57ff826f150b..e18f653cd7db 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -522,7 +522,7 @@ static int buildid_dir_command_config(const char *var, const char *value,
522 const char *v; 522 const char *v;
523 523
524 /* same dir for all commands */ 524 /* same dir for all commands */
525 if (!prefixcmp(var, "buildid.") && !strcmp(var + 8, "dir")) { 525 if (!strcmp(var, "buildid.dir")) {
526 v = perf_config_dirname(var, value); 526 v = perf_config_dirname(var, value);
527 if (!v) 527 if (!v)
528 return -1; 528 return -1;
@@ -539,12 +539,14 @@ static void check_buildid_dir_config(void)
539 perf_config(buildid_dir_command_config, &c); 539 perf_config(buildid_dir_command_config, &c);
540} 540}
541 541
542void set_buildid_dir(void) 542void set_buildid_dir(const char *dir)
543{ 543{
544 buildid_dir[0] = '\0'; 544 if (dir)
545 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir);
545 546
546 /* try config file */ 547 /* try config file */
547 check_buildid_dir_config(); 548 if (buildid_dir[0] == '\0')
549 check_buildid_dir_config();
548 550
549 /* default to $HOME/.debug */ 551 /* default to $HOME/.debug */
550 if (buildid_dir[0] == '\0') { 552 if (buildid_dir[0] == '\0') {
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
new file mode 100644
index 000000000000..c81dae399763
--- /dev/null
+++ b/tools/perf/util/db-export.c
@@ -0,0 +1,428 @@
1/*
2 * db-export.c: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <errno.h>
17
18#include "evsel.h"
19#include "machine.h"
20#include "thread.h"
21#include "comm.h"
22#include "symbol.h"
23#include "event.h"
24#include "util.h"
25#include "thread-stack.h"
26#include "db-export.h"
27
28struct deferred_export {
29 struct list_head node;
30 struct comm *comm;
31};
32
33static int db_export__deferred(struct db_export *dbe)
34{
35 struct deferred_export *de;
36 int err;
37
38 while (!list_empty(&dbe->deferred)) {
39 de = list_entry(dbe->deferred.next, struct deferred_export,
40 node);
41 err = dbe->export_comm(dbe, de->comm);
42 list_del(&de->node);
43 free(de);
44 if (err)
45 return err;
46 }
47
48 return 0;
49}
50
51static void db_export__free_deferred(struct db_export *dbe)
52{
53 struct deferred_export *de;
54
55 while (!list_empty(&dbe->deferred)) {
56 de = list_entry(dbe->deferred.next, struct deferred_export,
57 node);
58 list_del(&de->node);
59 free(de);
60 }
61}
62
63static int db_export__defer_comm(struct db_export *dbe, struct comm *comm)
64{
65 struct deferred_export *de;
66
67 de = zalloc(sizeof(struct deferred_export));
68 if (!de)
69 return -ENOMEM;
70
71 de->comm = comm;
72 list_add_tail(&de->node, &dbe->deferred);
73
74 return 0;
75}
76
77int db_export__init(struct db_export *dbe)
78{
79 memset(dbe, 0, sizeof(struct db_export));
80 INIT_LIST_HEAD(&dbe->deferred);
81 return 0;
82}
83
84int db_export__flush(struct db_export *dbe)
85{
86 return db_export__deferred(dbe);
87}
88
89void db_export__exit(struct db_export *dbe)
90{
91 db_export__free_deferred(dbe);
92 call_return_processor__free(dbe->crp);
93 dbe->crp = NULL;
94}
95
96int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
97{
98 if (evsel->db_id)
99 return 0;
100
101 evsel->db_id = ++dbe->evsel_last_db_id;
102
103 if (dbe->export_evsel)
104 return dbe->export_evsel(dbe, evsel);
105
106 return 0;
107}
108
109int db_export__machine(struct db_export *dbe, struct machine *machine)
110{
111 if (machine->db_id)
112 return 0;
113
114 machine->db_id = ++dbe->machine_last_db_id;
115
116 if (dbe->export_machine)
117 return dbe->export_machine(dbe, machine);
118
119 return 0;
120}
121
122int db_export__thread(struct db_export *dbe, struct thread *thread,
123 struct machine *machine, struct comm *comm)
124{
125 u64 main_thread_db_id = 0;
126 int err;
127
128 if (thread->db_id)
129 return 0;
130
131 thread->db_id = ++dbe->thread_last_db_id;
132
133 if (thread->pid_ != -1) {
134 struct thread *main_thread;
135
136 if (thread->pid_ == thread->tid) {
137 main_thread = thread;
138 } else {
139 main_thread = machine__findnew_thread(machine,
140 thread->pid_,
141 thread->pid_);
142 if (!main_thread)
143 return -ENOMEM;
144 err = db_export__thread(dbe, main_thread, machine,
145 comm);
146 if (err)
147 return err;
148 if (comm) {
149 err = db_export__comm_thread(dbe, comm, thread);
150 if (err)
151 return err;
152 }
153 }
154 main_thread_db_id = main_thread->db_id;
155 }
156
157 if (dbe->export_thread)
158 return dbe->export_thread(dbe, thread, main_thread_db_id,
159 machine);
160
161 return 0;
162}
163
164int db_export__comm(struct db_export *dbe, struct comm *comm,
165 struct thread *main_thread)
166{
167 int err;
168
169 if (comm->db_id)
170 return 0;
171
172 comm->db_id = ++dbe->comm_last_db_id;
173
174 if (dbe->export_comm) {
175 if (main_thread->comm_set)
176 err = dbe->export_comm(dbe, comm);
177 else
178 err = db_export__defer_comm(dbe, comm);
179 if (err)
180 return err;
181 }
182
183 return db_export__comm_thread(dbe, comm, main_thread);
184}
185
186int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
187 struct thread *thread)
188{
189 u64 db_id;
190
191 db_id = ++dbe->comm_thread_last_db_id;
192
193 if (dbe->export_comm_thread)
194 return dbe->export_comm_thread(dbe, db_id, comm, thread);
195
196 return 0;
197}
198
199int db_export__dso(struct db_export *dbe, struct dso *dso,
200 struct machine *machine)
201{
202 if (dso->db_id)
203 return 0;
204
205 dso->db_id = ++dbe->dso_last_db_id;
206
207 if (dbe->export_dso)
208 return dbe->export_dso(dbe, dso, machine);
209
210 return 0;
211}
212
213int db_export__symbol(struct db_export *dbe, struct symbol *sym,
214 struct dso *dso)
215{
216 u64 *sym_db_id = symbol__priv(sym);
217
218 if (*sym_db_id)
219 return 0;
220
221 *sym_db_id = ++dbe->symbol_last_db_id;
222
223 if (dbe->export_symbol)
224 return dbe->export_symbol(dbe, sym, dso);
225
226 return 0;
227}
228
229static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
230{
231 if (thread->pid_ == thread->tid)
232 return thread;
233
234 if (thread->pid_ == -1)
235 return NULL;
236
237 return machine__find_thread(machine, thread->pid_, thread->pid_);
238}
239
240static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
241 u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
242{
243 int err;
244
245 if (al->map) {
246 struct dso *dso = al->map->dso;
247
248 err = db_export__dso(dbe, dso, al->machine);
249 if (err)
250 return err;
251 *dso_db_id = dso->db_id;
252
253 if (!al->sym) {
254 al->sym = symbol__new(al->addr, 0, 0, "unknown");
255 if (al->sym)
256 symbols__insert(&dso->symbols[al->map->type],
257 al->sym);
258 }
259
260 if (al->sym) {
261 u64 *db_id = symbol__priv(al->sym);
262
263 err = db_export__symbol(dbe, al->sym, dso);
264 if (err)
265 return err;
266 *sym_db_id = *db_id;
267 *offset = al->addr - al->sym->start;
268 }
269 }
270
271 return 0;
272}
273
274int db_export__branch_type(struct db_export *dbe, u32 branch_type,
275 const char *name)
276{
277 if (dbe->export_branch_type)
278 return dbe->export_branch_type(dbe, branch_type, name);
279
280 return 0;
281}
282
283int db_export__sample(struct db_export *dbe, union perf_event *event,
284 struct perf_sample *sample, struct perf_evsel *evsel,
285 struct thread *thread, struct addr_location *al)
286{
287 struct export_sample es = {
288 .event = event,
289 .sample = sample,
290 .evsel = evsel,
291 .thread = thread,
292 .al = al,
293 };
294 struct thread *main_thread;
295 struct comm *comm = NULL;
296 int err;
297
298 err = db_export__evsel(dbe, evsel);
299 if (err)
300 return err;
301
302 err = db_export__machine(dbe, al->machine);
303 if (err)
304 return err;
305
306 main_thread = get_main_thread(al->machine, thread);
307 if (main_thread)
308 comm = machine__thread_exec_comm(al->machine, main_thread);
309
310 err = db_export__thread(dbe, thread, al->machine, comm);
311 if (err)
312 return err;
313
314 if (comm) {
315 err = db_export__comm(dbe, comm, main_thread);
316 if (err)
317 return err;
318 es.comm_db_id = comm->db_id;
319 }
320
321 es.db_id = ++dbe->sample_last_db_id;
322
323 err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
324 if (err)
325 return err;
326
327 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
328 sample_addr_correlates_sym(&evsel->attr)) {
329 struct addr_location addr_al;
330
331 perf_event__preprocess_sample_addr(event, sample, thread, &addr_al);
332 err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
333 &es.addr_sym_db_id, &es.addr_offset);
334 if (err)
335 return err;
336 if (dbe->crp) {
337 err = thread_stack__process(thread, comm, sample, al,
338 &addr_al, es.db_id,
339 dbe->crp);
340 if (err)
341 return err;
342 }
343 }
344
345 if (dbe->export_sample)
346 return dbe->export_sample(dbe, &es);
347
348 return 0;
349}
350
351static struct {
352 u32 branch_type;
353 const char *name;
354} branch_types[] = {
355 {0, "no branch"},
356 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
357 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
358 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "conditional jump"},
359 {PERF_IP_FLAG_BRANCH, "unconditional jump"},
360 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT,
361 "software interrupt"},
362 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT,
363 "return from interrupt"},
364 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET,
365 "system call"},
366 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET,
367 "return from system call"},
368 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "asynchronous branch"},
369 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
370 PERF_IP_FLAG_INTERRUPT, "hardware interrupt"},
371 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"},
372 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"},
373 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"},
374 {0, NULL}
375};
376
377int db_export__branch_types(struct db_export *dbe)
378{
379 int i, err = 0;
380
381 for (i = 0; branch_types[i].name ; i++) {
382 err = db_export__branch_type(dbe, branch_types[i].branch_type,
383 branch_types[i].name);
384 if (err)
385 break;
386 }
387 return err;
388}
389
390int db_export__call_path(struct db_export *dbe, struct call_path *cp)
391{
392 int err;
393
394 if (cp->db_id)
395 return 0;
396
397 if (cp->parent) {
398 err = db_export__call_path(dbe, cp->parent);
399 if (err)
400 return err;
401 }
402
403 cp->db_id = ++dbe->call_path_last_db_id;
404
405 if (dbe->export_call_path)
406 return dbe->export_call_path(dbe, cp);
407
408 return 0;
409}
410
411int db_export__call_return(struct db_export *dbe, struct call_return *cr)
412{
413 int err;
414
415 if (cr->db_id)
416 return 0;
417
418 err = db_export__call_path(dbe, cr->cp);
419 if (err)
420 return err;
421
422 cr->db_id = ++dbe->call_return_last_db_id;
423
424 if (dbe->export_call_return)
425 return dbe->export_call_return(dbe, cr);
426
427 return 0;
428}
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
new file mode 100644
index 000000000000..adbd22d66798
--- /dev/null
+++ b/tools/perf/util/db-export.h
@@ -0,0 +1,107 @@
1/*
2 * db-export.h: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_DB_EXPORT_H
17#define __PERF_DB_EXPORT_H
18
19#include <linux/types.h>
20#include <linux/list.h>
21
22struct perf_evsel;
23struct machine;
24struct thread;
25struct comm;
26struct dso;
27struct perf_sample;
28struct addr_location;
29struct call_return_processor;
30struct call_path;
31struct call_return;
32
33struct export_sample {
34 union perf_event *event;
35 struct perf_sample *sample;
36 struct perf_evsel *evsel;
37 struct thread *thread;
38 struct addr_location *al;
39 u64 db_id;
40 u64 comm_db_id;
41 u64 dso_db_id;
42 u64 sym_db_id;
43 u64 offset; /* ip offset from symbol start */
44 u64 addr_dso_db_id;
45 u64 addr_sym_db_id;
46 u64 addr_offset; /* addr offset from symbol start */
47};
48
49struct db_export {
50 int (*export_evsel)(struct db_export *dbe, struct perf_evsel *evsel);
51 int (*export_machine)(struct db_export *dbe, struct machine *machine);
52 int (*export_thread)(struct db_export *dbe, struct thread *thread,
53 u64 main_thread_db_id, struct machine *machine);
54 int (*export_comm)(struct db_export *dbe, struct comm *comm);
55 int (*export_comm_thread)(struct db_export *dbe, u64 db_id,
56 struct comm *comm, struct thread *thread);
57 int (*export_dso)(struct db_export *dbe, struct dso *dso,
58 struct machine *machine);
59 int (*export_symbol)(struct db_export *dbe, struct symbol *sym,
60 struct dso *dso);
61 int (*export_branch_type)(struct db_export *dbe, u32 branch_type,
62 const char *name);
63 int (*export_sample)(struct db_export *dbe, struct export_sample *es);
64 int (*export_call_path)(struct db_export *dbe, struct call_path *cp);
65 int (*export_call_return)(struct db_export *dbe,
66 struct call_return *cr);
67 struct call_return_processor *crp;
68 u64 evsel_last_db_id;
69 u64 machine_last_db_id;
70 u64 thread_last_db_id;
71 u64 comm_last_db_id;
72 u64 comm_thread_last_db_id;
73 u64 dso_last_db_id;
74 u64 symbol_last_db_id;
75 u64 sample_last_db_id;
76 u64 call_path_last_db_id;
77 u64 call_return_last_db_id;
78 struct list_head deferred;
79};
80
81int db_export__init(struct db_export *dbe);
82int db_export__flush(struct db_export *dbe);
83void db_export__exit(struct db_export *dbe);
84int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel);
85int db_export__machine(struct db_export *dbe, struct machine *machine);
86int db_export__thread(struct db_export *dbe, struct thread *thread,
87 struct machine *machine, struct comm *comm);
88int db_export__comm(struct db_export *dbe, struct comm *comm,
89 struct thread *main_thread);
90int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
91 struct thread *thread);
92int db_export__dso(struct db_export *dbe, struct dso *dso,
93 struct machine *machine);
94int db_export__symbol(struct db_export *dbe, struct symbol *sym,
95 struct dso *dso);
96int db_export__branch_type(struct db_export *dbe, u32 branch_type,
97 const char *name);
98int db_export__sample(struct db_export *dbe, union perf_event *event,
99 struct perf_sample *sample, struct perf_evsel *evsel,
100 struct thread *thread, struct addr_location *al);
101
102int db_export__branch_types(struct db_export *dbe);
103
104int db_export__call_path(struct db_export *dbe, struct call_path *cp);
105int db_export__call_return(struct db_export *dbe, struct call_return *cr);
106
107#endif
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index ba357f3226c6..ad60b2f20258 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -19,13 +19,14 @@
19int verbose; 19int 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;
22 23
23static int _eprintf(int level, int var, const char *fmt, va_list args) 24static int _eprintf(int level, int var, const char *fmt, va_list args)
24{ 25{
25 int ret = 0; 26 int ret = 0;
26 27
27 if (var >= level) { 28 if (var >= level) {
28 if (use_browser >= 1) 29 if (use_browser >= 1 && !redirect_to_stderr)
29 ui_helpline__vshow(fmt, args); 30 ui_helpline__vshow(fmt, args);
30 else 31 else
31 ret = vfprintf(stderr, fmt, args); 32 ret = vfprintf(stderr, fmt, args);
@@ -145,6 +146,7 @@ static struct debug_variable {
145} debug_variables[] = { 146} debug_variables[] = {
146 { .name = "verbose", .ptr = &verbose }, 147 { .name = "verbose", .ptr = &verbose },
147 { .name = "ordered-events", .ptr = &debug_ordered_events}, 148 { .name = "ordered-events", .ptr = &debug_ordered_events},
149 { .name = "stderr", .ptr = &redirect_to_stderr},
148 { .name = NULL, } 150 { .name = NULL, }
149}; 151};
150 152
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 0247acfdfaca..45be944d450a 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso)
21 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', 21 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
22 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', 22 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
23 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', 23 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
24 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm',
24 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', 25 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
25 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', 26 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
27 [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M',
26 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', 28 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
27 }; 29 };
28 30
@@ -112,11 +114,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
112 break; 114 break;
113 115
114 case DSO_BINARY_TYPE__GUEST_KMODULE: 116 case DSO_BINARY_TYPE__GUEST_KMODULE:
117 case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
115 path__join3(filename, size, symbol_conf.symfs, 118 path__join3(filename, size, symbol_conf.symfs,
116 root_dir, dso->long_name); 119 root_dir, dso->long_name);
117 break; 120 break;
118 121
119 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 122 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
123 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
120 __symbol__join_symfs(filename, size, dso->long_name); 124 __symbol__join_symfs(filename, size, dso->long_name);
121 break; 125 break;
122 126
@@ -137,6 +141,73 @@ int dso__read_binary_type_filename(const struct dso *dso,
137 return ret; 141 return ret;
138} 142}
139 143
144static const struct {
145 const char *fmt;
146 int (*decompress)(const char *input, int output);
147} compressions[] = {
148#ifdef HAVE_ZLIB_SUPPORT
149 { "gz", gzip_decompress_to_file },
150#endif
151 { NULL, NULL },
152};
153
154bool is_supported_compression(const char *ext)
155{
156 unsigned i;
157
158 for (i = 0; compressions[i].fmt; i++) {
159 if (!strcmp(ext, compressions[i].fmt))
160 return true;
161 }
162 return false;
163}
164
165bool is_kmodule_extension(const char *ext)
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{
178 const char *ext = strrchr(pathname, '.');
179
180 if (ext == NULL)
181 return false;
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
190 return is_kmodule_extension(ext + 1);
191}
192
193bool decompress_to_file(const char *ext, const char *filename, int output_fd)
194{
195 unsigned i;
196
197 for (i = 0; compressions[i].fmt; i++) {
198 if (!strcmp(ext, compressions[i].fmt))
199 return !compressions[i].decompress(filename,
200 output_fd);
201 }
202 return false;
203}
204
205bool dso__needs_decompress(struct dso *dso)
206{
207 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
208 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
209}
210
140/* 211/*
141 * Global list of open DSOs and the counter. 212 * Global list of open DSOs and the counter.
142 */ 213 */
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index acb651acc7fd..3782c82c6e44 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -22,7 +22,9 @@ enum dso_binary_type {
22 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 22 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
23 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 23 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
24 DSO_BINARY_TYPE__GUEST_KMODULE, 24 DSO_BINARY_TYPE__GUEST_KMODULE,
25 DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
25 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 26 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
27 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
26 DSO_BINARY_TYPE__KCORE, 28 DSO_BINARY_TYPE__KCORE,
27 DSO_BINARY_TYPE__GUEST_KCORE, 29 DSO_BINARY_TYPE__GUEST_KCORE,
28 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 30 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
@@ -127,6 +129,7 @@ struct dso {
127 const char *long_name; 129 const char *long_name;
128 u16 long_name_len; 130 u16 long_name_len;
129 u16 short_name_len; 131 u16 short_name_len;
132 void *dwfl; /* DWARF debug info */
130 133
131 /* dso data file */ 134 /* dso data file */
132 struct { 135 struct {
@@ -138,6 +141,11 @@ struct dso {
138 struct list_head open_entry; 141 struct list_head open_entry;
139 } data; 142 } data;
140 143
144 union { /* Tool specific area */
145 void *priv;
146 u64 db_id;
147 };
148
141 char name[0]; 149 char name[0];
142}; 150};
143 151
@@ -179,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
179char dso__symtab_origin(const struct dso *dso); 187char dso__symtab_origin(const struct dso *dso);
180int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 188int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
181 char *root_dir, char *filename, size_t size); 189 char *root_dir, char *filename, size_t size);
190bool is_supported_compression(const char *ext);
191bool is_kmodule_extension(const char *ext);
192bool is_kernel_module(const char *pathname, bool *compressed);
193bool decompress_to_file(const char *ext, const char *filename, int output_fd);
194bool dso__needs_decompress(struct dso *dso);
182 195
183/* 196/*
184 * The dso__data_* external interface provides following functions: 197 * The dso__data_* external interface provides following functions:
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 4af6b279e34a..6c6d044e959a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -28,6 +28,7 @@ static const char *perf_event__names[] = {
28 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 28 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
29 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 29 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
30 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", 30 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND",
31 [PERF_RECORD_ID_INDEX] = "ID_INDEX",
31}; 32};
32 33
33const char *perf_event__name(unsigned int id) 34const char *perf_event__name(unsigned int id)
@@ -730,12 +731,12 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
730 return machine__process_event(machine, event, sample); 731 return machine__process_event(machine, event, sample);
731} 732}
732 733
733void thread__find_addr_map(struct thread *thread, 734void thread__find_addr_map(struct thread *thread, u8 cpumode,
734 struct machine *machine, u8 cpumode,
735 enum map_type type, u64 addr, 735 enum map_type type, u64 addr,
736 struct addr_location *al) 736 struct addr_location *al)
737{ 737{
738 struct map_groups *mg = thread->mg; 738 struct map_groups *mg = thread->mg;
739 struct machine *machine = mg->machine;
739 bool load_map = false; 740 bool load_map = false;
740 741
741 al->machine = machine; 742 al->machine = machine;
@@ -806,14 +807,14 @@ try_again:
806 } 807 }
807} 808}
808 809
809void thread__find_addr_location(struct thread *thread, struct machine *machine, 810void thread__find_addr_location(struct thread *thread,
810 u8 cpumode, enum map_type type, u64 addr, 811 u8 cpumode, enum map_type type, u64 addr,
811 struct addr_location *al) 812 struct addr_location *al)
812{ 813{
813 thread__find_addr_map(thread, machine, cpumode, type, addr, al); 814 thread__find_addr_map(thread, cpumode, type, addr, al);
814 if (al->map != NULL) 815 if (al->map != NULL)
815 al->sym = map__find_symbol(al->map, al->addr, 816 al->sym = map__find_symbol(al->map, al->addr,
816 machine->symbol_filter); 817 thread->mg->machine->symbol_filter);
817 else 818 else
818 al->sym = NULL; 819 al->sym = NULL;
819} 820}
@@ -842,8 +843,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
842 machine->vmlinux_maps[MAP__FUNCTION] == NULL) 843 machine->vmlinux_maps[MAP__FUNCTION] == NULL)
843 machine__create_kernel_maps(machine); 844 machine__create_kernel_maps(machine);
844 845
845 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 846 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
846 sample->ip, al);
847 dump_printf(" ...... dso: %s\n", 847 dump_printf(" ...... dso: %s\n",
848 al->map ? al->map->dso->long_name : 848 al->map ? al->map->dso->long_name :
849 al->level == 'H' ? "[hypervisor]" : "<not found>"); 849 al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -902,16 +902,14 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr)
902 902
903void perf_event__preprocess_sample_addr(union perf_event *event, 903void perf_event__preprocess_sample_addr(union perf_event *event,
904 struct perf_sample *sample, 904 struct perf_sample *sample,
905 struct machine *machine,
906 struct thread *thread, 905 struct thread *thread,
907 struct addr_location *al) 906 struct addr_location *al)
908{ 907{
909 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 908 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
910 909
911 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 910 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al);
912 sample->addr, al);
913 if (!al->map) 911 if (!al->map)
914 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, 912 thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
915 sample->addr, al); 913 sample->addr, al);
916 914
917 al->cpu = sample->cpu; 915 al->cpu = sample->cpu;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 5699e7e2a790..c4ffe2bd0738 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -143,6 +143,32 @@ struct branch_stack {
143 struct branch_entry entries[0]; 143 struct branch_entry entries[0];
144}; 144};
145 145
146enum {
147 PERF_IP_FLAG_BRANCH = 1ULL << 0,
148 PERF_IP_FLAG_CALL = 1ULL << 1,
149 PERF_IP_FLAG_RETURN = 1ULL << 2,
150 PERF_IP_FLAG_CONDITIONAL = 1ULL << 3,
151 PERF_IP_FLAG_SYSCALLRET = 1ULL << 4,
152 PERF_IP_FLAG_ASYNC = 1ULL << 5,
153 PERF_IP_FLAG_INTERRUPT = 1ULL << 6,
154 PERF_IP_FLAG_TX_ABORT = 1ULL << 7,
155 PERF_IP_FLAG_TRACE_BEGIN = 1ULL << 8,
156 PERF_IP_FLAG_TRACE_END = 1ULL << 9,
157 PERF_IP_FLAG_IN_TX = 1ULL << 10,
158};
159
160#define PERF_BRANCH_MASK (\
161 PERF_IP_FLAG_BRANCH |\
162 PERF_IP_FLAG_CALL |\
163 PERF_IP_FLAG_RETURN |\
164 PERF_IP_FLAG_CONDITIONAL |\
165 PERF_IP_FLAG_SYSCALLRET |\
166 PERF_IP_FLAG_ASYNC |\
167 PERF_IP_FLAG_INTERRUPT |\
168 PERF_IP_FLAG_TX_ABORT |\
169 PERF_IP_FLAG_TRACE_BEGIN |\
170 PERF_IP_FLAG_TRACE_END)
171
146struct perf_sample { 172struct perf_sample {
147 u64 ip; 173 u64 ip;
148 u32 pid, tid; 174 u32 pid, tid;
@@ -162,6 +188,7 @@ struct perf_sample {
162 struct ip_callchain *callchain; 188 struct ip_callchain *callchain;
163 struct branch_stack *branch_stack; 189 struct branch_stack *branch_stack;
164 struct regs_dump user_regs; 190 struct regs_dump user_regs;
191 struct regs_dump intr_regs;
165 struct stack_dump user_stack; 192 struct stack_dump user_stack;
166 struct sample_read read; 193 struct sample_read read;
167}; 194};
@@ -187,6 +214,7 @@ enum perf_user_event_type { /* above any possible kernel type */
187 PERF_RECORD_HEADER_TRACING_DATA = 66, 214 PERF_RECORD_HEADER_TRACING_DATA = 66,
188 PERF_RECORD_HEADER_BUILD_ID = 67, 215 PERF_RECORD_HEADER_BUILD_ID = 67,
189 PERF_RECORD_FINISHED_ROUND = 68, 216 PERF_RECORD_FINISHED_ROUND = 68,
217 PERF_RECORD_ID_INDEX = 69,
190 PERF_RECORD_HEADER_MAX 218 PERF_RECORD_HEADER_MAX
191}; 219};
192 220
@@ -214,6 +242,7 @@ struct events_stats {
214 u32 nr_invalid_chains; 242 u32 nr_invalid_chains;
215 u32 nr_unknown_id; 243 u32 nr_unknown_id;
216 u32 nr_unprocessable_samples; 244 u32 nr_unprocessable_samples;
245 u32 nr_unordered_events;
217}; 246};
218 247
219struct attr_event { 248struct attr_event {
@@ -239,6 +268,19 @@ struct tracing_data_event {
239 u32 size; 268 u32 size;
240}; 269};
241 270
271struct id_index_entry {
272 u64 id;
273 u64 idx;
274 u64 cpu;
275 u64 tid;
276};
277
278struct id_index_event {
279 struct perf_event_header header;
280 u64 nr;
281 struct id_index_entry entries[0];
282};
283
242union perf_event { 284union perf_event {
243 struct perf_event_header header; 285 struct perf_event_header header;
244 struct mmap_event mmap; 286 struct mmap_event mmap;
@@ -253,6 +295,7 @@ union perf_event {
253 struct event_type_event event_type; 295 struct event_type_event event_type;
254 struct tracing_data_event tracing_data; 296 struct tracing_data_event tracing_data;
255 struct build_id_event build_id; 297 struct build_id_event build_id;
298 struct id_index_event id_index;
256}; 299};
257 300
258void perf_event__print_totals(void); 301void perf_event__print_totals(void);
@@ -322,7 +365,6 @@ bool is_bts_event(struct perf_event_attr *attr);
322bool sample_addr_correlates_sym(struct perf_event_attr *attr); 365bool sample_addr_correlates_sym(struct perf_event_attr *attr);
323void perf_event__preprocess_sample_addr(union perf_event *event, 366void perf_event__preprocess_sample_addr(union perf_event *event,
324 struct perf_sample *sample, 367 struct perf_sample *sample,
325 struct machine *machine,
326 struct thread *thread, 368 struct thread *thread,
327 struct addr_location *al); 369 struct addr_location *al);
328 370
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3c9e77d6b4c2..cbab1fb77b1d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -8,6 +8,7 @@
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include <api/fs/debugfs.h> 10#include <api/fs/debugfs.h>
11#include <api/fs/fs.h>
11#include <poll.h> 12#include <poll.h>
12#include "cpumap.h" 13#include "cpumap.h"
13#include "thread_map.h" 14#include "thread_map.h"
@@ -24,6 +25,7 @@
24 25
25#include <linux/bitops.h> 26#include <linux/bitops.h>
26#include <linux/hash.h> 27#include <linux/hash.h>
28#include <linux/log2.h>
27 29
28static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); 30static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
29static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); 31static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
@@ -413,7 +415,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
413 int nfds = 0; 415 int nfds = 0;
414 struct perf_evsel *evsel; 416 struct perf_evsel *evsel;
415 417
416 list_for_each_entry(evsel, &evlist->entries, node) { 418 evlist__for_each(evlist, evsel) {
417 if (evsel->system_wide) 419 if (evsel->system_wide)
418 nfds += nr_cpus; 420 nfds += nr_cpus;
419 else 421 else
@@ -527,6 +529,22 @@ static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
527 return 0; 529 return 0;
528} 530}
529 531
532static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
533 struct perf_evsel *evsel, int idx, int cpu,
534 int thread)
535{
536 struct perf_sample_id *sid = SID(evsel, cpu, thread);
537 sid->idx = idx;
538 if (evlist->cpus && cpu >= 0)
539 sid->cpu = evlist->cpus->map[cpu];
540 else
541 sid->cpu = -1;
542 if (!evsel->system_wide && evlist->threads && thread >= 0)
543 sid->tid = evlist->threads->map[thread];
544 else
545 sid->tid = -1;
546}
547
530struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) 548struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
531{ 549{
532 struct hlist_head *head; 550 struct hlist_head *head;
@@ -800,14 +818,26 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
800 perf_evlist__mmap_get(evlist, idx); 818 perf_evlist__mmap_get(evlist, idx);
801 } 819 }
802 820
803 if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) { 821 /*
822 * The system_wide flag causes a selected event to be opened
823 * always without a pid. Consequently it will never get a
824 * POLLHUP, but it is used for tracking in combination with
825 * other events, so it should not need to be polled anyway.
826 * Therefore don't add it for polling.
827 */
828 if (!evsel->system_wide &&
829 __perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
804 perf_evlist__mmap_put(evlist, idx); 830 perf_evlist__mmap_put(evlist, idx);
805 return -1; 831 return -1;
806 } 832 }
807 833
808 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 834 if (evsel->attr.read_format & PERF_FORMAT_ID) {
809 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) 835 if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
810 return -1; 836 fd) < 0)
837 return -1;
838 perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
839 thread);
840 }
811 } 841 }
812 842
813 return 0; 843 return 0;
@@ -864,10 +894,24 @@ out_unmap:
864 894
865static size_t perf_evlist__mmap_size(unsigned long pages) 895static size_t perf_evlist__mmap_size(unsigned long pages)
866{ 896{
867 /* 512 kiB: default amount of unprivileged mlocked memory */ 897 if (pages == UINT_MAX) {
868 if (pages == UINT_MAX) 898 int max;
869 pages = (512 * 1024) / page_size; 899
870 else if (!is_power_of_2(pages)) 900 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
901 /*
902 * Pick a once upon a time good value, i.e. things look
903 * strange since we can't read a sysctl value, but lets not
904 * die yet...
905 */
906 max = 512;
907 } else {
908 max -= (page_size / 1024);
909 }
910
911 pages = (max * 1024) / page_size;
912 if (!is_power_of_2(pages))
913 pages = rounddown_pow_of_two(pages);
914 } else if (!is_power_of_2(pages))
871 return 0; 915 return 0;
872 916
873 return (pages + 1) * page_size; 917 return (pages + 1) * page_size;
@@ -904,7 +948,7 @@ static long parse_pages_arg(const char *str, unsigned long min,
904 /* leave number of pages at 0 */ 948 /* leave number of pages at 0 */
905 } else if (!is_power_of_2(pages)) { 949 } else if (!is_power_of_2(pages)) {
906 /* round pages up to next power of 2 */ 950 /* round pages up to next power of 2 */
907 pages = next_pow2_l(pages); 951 pages = roundup_pow_of_two(pages);
908 if (!pages) 952 if (!pages)
909 return -EINVAL; 953 return -EINVAL;
910 pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", 954 pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
@@ -1455,6 +1499,37 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1455 return 0; 1499 return 0;
1456} 1500}
1457 1501
1502int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
1503{
1504 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1505 int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
1506
1507 switch (err) {
1508 case EPERM:
1509 sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
1510 printed += scnprintf(buf + printed, size - printed,
1511 "Error:\t%s.\n"
1512 "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
1513 "Hint:\tTried using %zd kB.\n",
1514 emsg, pages_max_per_user, pages_attempted);
1515
1516 if (pages_attempted >= pages_max_per_user) {
1517 printed += scnprintf(buf + printed, size - printed,
1518 "Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n",
1519 pages_max_per_user + pages_attempted);
1520 }
1521
1522 printed += scnprintf(buf + printed, size - printed,
1523 "Hint:\tTry using a smaller -m/--mmap-pages value.");
1524 break;
1525 default:
1526 scnprintf(buf, size, "%s", emsg);
1527 break;
1528 }
1529
1530 return 0;
1531}
1532
1458void perf_evlist__to_front(struct perf_evlist *evlist, 1533void perf_evlist__to_front(struct perf_evlist *evlist,
1459 struct perf_evsel *move_evsel) 1534 struct perf_evsel *move_evsel)
1460{ 1535{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 649b0c597283..0ba93f67ab94 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -185,6 +185,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
185 185
186int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size); 186int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size);
187int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); 187int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
188int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
188 189
189static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) 190static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
190{ 191{
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2f9e68025ede..1e90c8557ede 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -658,9 +658,22 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
658 attr->mmap_data = track; 658 attr->mmap_data = track;
659 } 659 }
660 660
661 /*
662 * We don't allow user space callchains for function trace
663 * event, due to issues with page faults while tracing page
664 * fault handler and its overall trickiness nature.
665 */
666 if (perf_evsel__is_function_event(evsel))
667 evsel->attr.exclude_callchain_user = 1;
668
661 if (callchain_param.enabled && !evsel->no_aux_samples) 669 if (callchain_param.enabled && !evsel->no_aux_samples)
662 perf_evsel__config_callgraph(evsel); 670 perf_evsel__config_callgraph(evsel);
663 671
672 if (opts->sample_intr_regs) {
673 attr->sample_regs_intr = PERF_REGS_MASK;
674 perf_evsel__set_sample_bit(evsel, REGS_INTR);
675 }
676
664 if (target__has_cpu(&opts->target)) 677 if (target__has_cpu(&opts->target))
665 perf_evsel__set_sample_bit(evsel, CPU); 678 perf_evsel__set_sample_bit(evsel, CPU);
666 679
@@ -853,8 +866,6 @@ void perf_evsel__exit(struct perf_evsel *evsel)
853 perf_evsel__free_id(evsel); 866 perf_evsel__free_id(evsel);
854 close_cgroup(evsel->cgrp); 867 close_cgroup(evsel->cgrp);
855 zfree(&evsel->group_name); 868 zfree(&evsel->group_name);
856 if (evsel->tp_format)
857 pevent_free_format(evsel->tp_format);
858 zfree(&evsel->name); 869 zfree(&evsel->name);
859 perf_evsel__object.fini(evsel); 870 perf_evsel__object.fini(evsel);
860} 871}
@@ -865,9 +876,8 @@ void perf_evsel__delete(struct perf_evsel *evsel)
865 free(evsel); 876 free(evsel);
866} 877}
867 878
868static inline void compute_deltas(struct perf_evsel *evsel, 879void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
869 int cpu, 880 struct perf_counts_values *count)
870 struct perf_counts_values *count)
871{ 881{
872 struct perf_counts_values tmp; 882 struct perf_counts_values tmp;
873 883
@@ -887,81 +897,60 @@ static inline void compute_deltas(struct perf_evsel *evsel,
887 count->run = count->run - tmp.run; 897 count->run = count->run - tmp.run;
888} 898}
889 899
890int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 900void perf_counts_values__scale(struct perf_counts_values *count,
891 int cpu, int thread, bool scale) 901 bool scale, s8 *pscaled)
892{ 902{
893 struct perf_counts_values count; 903 s8 scaled = 0;
894 size_t nv = scale ? 3 : 1;
895
896 if (FD(evsel, cpu, thread) < 0)
897 return -EINVAL;
898
899 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
900 return -ENOMEM;
901
902 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
903 return -errno;
904
905 compute_deltas(evsel, cpu, &count);
906 904
907 if (scale) { 905 if (scale) {
908 if (count.run == 0) 906 if (count->run == 0) {
909 count.val = 0; 907 scaled = -1;
910 else if (count.run < count.ena) 908 count->val = 0;
911 count.val = (u64)((double)count.val * count.ena / count.run + 0.5); 909 } else if (count->run < count->ena) {
910 scaled = 1;
911 count->val = (u64)((double) count->val * count->ena / count->run + 0.5);
912 }
912 } else 913 } else
913 count.ena = count.run = 0; 914 count->ena = count->run = 0;
914 915
915 evsel->counts->cpu[cpu] = count; 916 if (pscaled)
916 return 0; 917 *pscaled = scaled;
917} 918}
918 919
919int __perf_evsel__read(struct perf_evsel *evsel, 920int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
920 int ncpus, int nthreads, bool scale) 921 perf_evsel__read_cb_t cb)
921{ 922{
922 size_t nv = scale ? 3 : 1; 923 struct perf_counts_values count;
923 int cpu, thread;
924 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
925 924
926 if (evsel->system_wide) 925 memset(&count, 0, sizeof(count));
927 nthreads = 1;
928 926
929 aggr->val = aggr->ena = aggr->run = 0; 927 if (FD(evsel, cpu, thread) < 0)
928 return -EINVAL;
930 929
931 for (cpu = 0; cpu < ncpus; cpu++) { 930 if (readn(FD(evsel, cpu, thread), &count, sizeof(count)) < 0)
932 for (thread = 0; thread < nthreads; thread++) { 931 return -errno;
933 if (FD(evsel, cpu, thread) < 0)
934 continue;
935 932
936 if (readn(FD(evsel, cpu, thread), 933 return cb(evsel, cpu, thread, &count);
937 &count, nv * sizeof(u64)) < 0) 934}
938 return -errno;
939 935
940 aggr->val += count.val; 936int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
941 if (scale) { 937 int cpu, int thread, bool scale)
942 aggr->ena += count.ena; 938{
943 aggr->run += count.run; 939 struct perf_counts_values count;
944 } 940 size_t nv = scale ? 3 : 1;
945 }
946 }
947 941
948 compute_deltas(evsel, -1, aggr); 942 if (FD(evsel, cpu, thread) < 0)
943 return -EINVAL;
949 944
950 evsel->counts->scaled = 0; 945 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
951 if (scale) { 946 return -ENOMEM;
952 if (aggr->run == 0) {
953 evsel->counts->scaled = -1;
954 aggr->val = 0;
955 return 0;
956 }
957 947
958 if (aggr->run < aggr->ena) { 948 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
959 evsel->counts->scaled = 1; 949 return -errno;
960 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
961 }
962 } else
963 aggr->ena = aggr->run = 0;
964 950
951 perf_evsel__compute_deltas(evsel, cpu, &count);
952 perf_counts_values__scale(&count, scale, NULL);
953 evsel->counts->cpu[cpu] = count;
965 return 0; 954 return 0;
966} 955}
967 956
@@ -1039,6 +1028,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
1039 ret += PRINT_ATTR_X64(branch_sample_type); 1028 ret += PRINT_ATTR_X64(branch_sample_type);
1040 ret += PRINT_ATTR_X64(sample_regs_user); 1029 ret += PRINT_ATTR_X64(sample_regs_user);
1041 ret += PRINT_ATTR_U32(sample_stack_user); 1030 ret += PRINT_ATTR_U32(sample_stack_user);
1031 ret += PRINT_ATTR_X64(sample_regs_intr);
1042 1032
1043 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1033 ret += fprintf(fp, "%.60s\n", graph_dotted_line);
1044 1034
@@ -1538,6 +1528,23 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1538 array++; 1528 array++;
1539 } 1529 }
1540 1530
1531 data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE;
1532 if (type & PERF_SAMPLE_REGS_INTR) {
1533 OVERFLOW_CHECK_u64(array);
1534 data->intr_regs.abi = *array;
1535 array++;
1536
1537 if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
1538 u64 mask = evsel->attr.sample_regs_intr;
1539
1540 sz = hweight_long(mask) * sizeof(u64);
1541 OVERFLOW_CHECK(array, sz, max_size);
1542 data->intr_regs.mask = mask;
1543 data->intr_regs.regs = (u64 *)array;
1544 array = (void *)array + sz;
1545 }
1546 }
1547
1541 return 0; 1548 return 0;
1542} 1549}
1543 1550
@@ -1633,6 +1640,16 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1633 if (type & PERF_SAMPLE_TRANSACTION) 1640 if (type & PERF_SAMPLE_TRANSACTION)
1634 result += sizeof(u64); 1641 result += sizeof(u64);
1635 1642
1643 if (type & PERF_SAMPLE_REGS_INTR) {
1644 if (sample->intr_regs.abi) {
1645 result += sizeof(u64);
1646 sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
1647 result += sz;
1648 } else {
1649 result += sizeof(u64);
1650 }
1651 }
1652
1636 return result; 1653 return result;
1637} 1654}
1638 1655
@@ -1811,6 +1828,17 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
1811 array++; 1828 array++;
1812 } 1829 }
1813 1830
1831 if (type & PERF_SAMPLE_REGS_INTR) {
1832 if (sample->intr_regs.abi) {
1833 *array++ = sample->intr_regs.abi;
1834 sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
1835 memcpy(array, sample->intr_regs.regs, sz);
1836 array = (void *)array + sz;
1837 } else {
1838 *array++ = 0;
1839 }
1840 }
1841
1814 return 0; 1842 return 0;
1815} 1843}
1816 1844
@@ -1940,7 +1968,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
1940 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), 1968 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1941 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1969 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1942 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1970 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1943 bit_name(IDENTIFIER), 1971 bit_name(IDENTIFIER), bit_name(REGS_INTR),
1944 { .name = NULL, } 1972 { .name = NULL, }
1945 }; 1973 };
1946#undef bit_name 1974#undef bit_name
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 163c5604e5d1..38622747d130 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -36,6 +36,9 @@ struct perf_sample_id {
36 struct hlist_node node; 36 struct hlist_node node;
37 u64 id; 37 u64 id;
38 struct perf_evsel *evsel; 38 struct perf_evsel *evsel;
39 int idx;
40 int cpu;
41 pid_t tid;
39 42
40 /* Holds total ID period value for PERF_SAMPLE_READ processing. */ 43 /* Holds total ID period value for PERF_SAMPLE_READ processing. */
41 u64 period; 44 u64 period;
@@ -54,6 +57,7 @@ struct cgroup_sel;
54 * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or 57 * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or
55 * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all 58 * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all
56 * is used there is an id sample appended to non-sample events 59 * is used there is an id sample appended to non-sample events
60 * @priv: And what is in its containing unnamed union are tool specific
57 */ 61 */
58struct perf_evsel { 62struct perf_evsel {
59 struct list_head node; 63 struct list_head node;
@@ -69,10 +73,12 @@ struct perf_evsel {
69 char *name; 73 char *name;
70 double scale; 74 double scale;
71 const char *unit; 75 const char *unit;
76 bool snapshot;
72 struct event_format *tp_format; 77 struct event_format *tp_format;
73 union { 78 union {
74 void *priv; 79 void *priv;
75 off_t id_offset; 80 off_t id_offset;
81 u64 db_id;
76 }; 82 };
77 struct cgroup_sel *cgrp; 83 struct cgroup_sel *cgrp;
78 void *handler; 84 void *handler;
@@ -86,6 +92,8 @@ struct perf_evsel {
86 bool immediate; 92 bool immediate;
87 bool system_wide; 93 bool system_wide;
88 bool tracking; 94 bool tracking;
95 bool per_pkg;
96 unsigned long *per_pkg_mask;
89 /* parse modifier helper */ 97 /* parse modifier helper */
90 int exclude_GH; 98 int exclude_GH;
91 int nr_members; 99 int nr_members;
@@ -105,6 +113,12 @@ struct thread_map;
105struct perf_evlist; 113struct perf_evlist;
106struct record_opts; 114struct record_opts;
107 115
116void perf_counts_values__scale(struct perf_counts_values *count,
117 bool scale, s8 *pscaled);
118
119void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
120 struct perf_counts_values *count);
121
108int perf_evsel__object_config(size_t object_size, 122int perf_evsel__object_config(size_t object_size,
109 int (*init)(struct perf_evsel *evsel), 123 int (*init)(struct perf_evsel *evsel),
110 void (*fini)(struct perf_evsel *evsel)); 124 void (*fini)(struct perf_evsel *evsel));
@@ -222,6 +236,13 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
222 (a)->attr.type == (b)->attr.type && \ 236 (a)->attr.type == (b)->attr.type && \
223 (a)->attr.config == (b)->attr.config) 237 (a)->attr.config == (b)->attr.config)
224 238
239typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel,
240 int cpu, int thread,
241 struct perf_counts_values *count);
242
243int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
244 perf_evsel__read_cb_t cb);
245
225int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 246int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
226 int cpu, int thread, bool scale); 247 int cpu, int thread, bool scale);
227 248
@@ -251,35 +272,6 @@ static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
251 return __perf_evsel__read_on_cpu(evsel, cpu, thread, true); 272 return __perf_evsel__read_on_cpu(evsel, cpu, thread, true);
252} 273}
253 274
254int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads,
255 bool scale);
256
257/**
258 * perf_evsel__read - Read the aggregate results on all CPUs
259 *
260 * @evsel - event selector to read value
261 * @ncpus - Number of cpus affected, from zero
262 * @nthreads - Number of threads affected, from zero
263 */
264static inline int perf_evsel__read(struct perf_evsel *evsel,
265 int ncpus, int nthreads)
266{
267 return __perf_evsel__read(evsel, ncpus, nthreads, false);
268}
269
270/**
271 * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled
272 *
273 * @evsel - event selector to read value
274 * @ncpus - Number of cpus affected, from zero
275 * @nthreads - Number of threads affected, from zero
276 */
277static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
278 int ncpus, int nthreads)
279{
280 return __perf_evsel__read(evsel, ncpus, nthreads, true);
281}
282
283int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, 275int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
284 struct perf_sample *sample); 276 struct perf_sample *sample);
285 277
diff --git a/tools/perf/util/find-vdso-map.c b/tools/perf/util/find-vdso-map.c
new file mode 100644
index 000000000000..95ef1cffc056
--- /dev/null
+++ b/tools/perf/util/find-vdso-map.c
@@ -0,0 +1,30 @@
1static int find_vdso_map(void **start, void **end)
2{
3 FILE *maps;
4 char line[128];
5 int found = 0;
6
7 maps = fopen("/proc/self/maps", "r");
8 if (!maps) {
9 fprintf(stderr, "vdso: cannot open maps\n");
10 return -1;
11 }
12
13 while (!found && fgets(line, sizeof(line), maps)) {
14 int m = -1;
15
16 /* We care only about private r-x mappings. */
17 if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
18 start, end, &m))
19 continue;
20 if (m < 0)
21 continue;
22
23 if (!strncmp(&line[m], VDSO__MAP_NAME,
24 sizeof(VDSO__MAP_NAME) - 1))
25 found = 1;
26 }
27
28 fclose(maps);
29 return !found;
30}
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 26f5b2fe5dc8..b20e40c74468 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -24,8 +24,6 @@
24#include "build-id.h" 24#include "build-id.h"
25#include "data.h" 25#include "data.h"
26 26
27static bool no_buildid_cache = false;
28
29static u32 header_argc; 27static u32 header_argc;
30static const char **header_argv; 28static const char **header_argv;
31 29
@@ -79,10 +77,7 @@ static int do_write(int fd, const void *buf, size_t size)
79 return 0; 77 return 0;
80} 78}
81 79
82#define NAME_ALIGN 64 80int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
83
84static int write_padded(int fd, const void *bf, size_t count,
85 size_t count_aligned)
86{ 81{
87 static const char zero_buf[NAME_ALIGN]; 82 static const char zero_buf[NAME_ALIGN];
88 int err = do_write(fd, bf, count); 83 int err = do_write(fd, bf, count);
@@ -171,340 +166,6 @@ perf_header__set_cmdline(int argc, const char **argv)
171 return 0; 166 return 0;
172} 167}
173 168
174#define dsos__for_each_with_build_id(pos, head) \
175 list_for_each_entry(pos, head, node) \
176 if (!pos->has_build_id) \
177 continue; \
178 else
179
180static int write_buildid(const char *name, size_t name_len, u8 *build_id,
181 pid_t pid, u16 misc, int fd)
182{
183 int err;
184 struct build_id_event b;
185 size_t len;
186
187 len = name_len + 1;
188 len = PERF_ALIGN(len, NAME_ALIGN);
189
190 memset(&b, 0, sizeof(b));
191 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
192 b.pid = pid;
193 b.header.misc = misc;
194 b.header.size = sizeof(b) + len;
195
196 err = do_write(fd, &b, sizeof(b));
197 if (err < 0)
198 return err;
199
200 return write_padded(fd, name, name_len + 1, len);
201}
202
203static int __dsos__hit_all(struct list_head *head)
204{
205 struct dso *pos;
206
207 list_for_each_entry(pos, head, node)
208 pos->hit = true;
209
210 return 0;
211}
212
213static int machine__hit_all_dsos(struct machine *machine)
214{
215 int err;
216
217 err = __dsos__hit_all(&machine->kernel_dsos.head);
218 if (err)
219 return err;
220
221 return __dsos__hit_all(&machine->user_dsos.head);
222}
223
224int dsos__hit_all(struct perf_session *session)
225{
226 struct rb_node *nd;
227 int err;
228
229 err = machine__hit_all_dsos(&session->machines.host);
230 if (err)
231 return err;
232
233 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
234 struct machine *pos = rb_entry(nd, struct machine, rb_node);
235
236 err = machine__hit_all_dsos(pos);
237 if (err)
238 return err;
239 }
240
241 return 0;
242}
243
244static int __dsos__write_buildid_table(struct list_head *head,
245 struct machine *machine,
246 pid_t pid, u16 misc, int fd)
247{
248 char nm[PATH_MAX];
249 struct dso *pos;
250
251 dsos__for_each_with_build_id(pos, head) {
252 int err;
253 const char *name;
254 size_t name_len;
255
256 if (!pos->hit)
257 continue;
258
259 if (dso__is_vdso(pos)) {
260 name = pos->short_name;
261 name_len = pos->short_name_len + 1;
262 } else if (dso__is_kcore(pos)) {
263 machine__mmap_name(machine, nm, sizeof(nm));
264 name = nm;
265 name_len = strlen(nm) + 1;
266 } else {
267 name = pos->long_name;
268 name_len = pos->long_name_len + 1;
269 }
270
271 err = write_buildid(name, name_len, pos->build_id,
272 pid, misc, fd);
273 if (err)
274 return err;
275 }
276
277 return 0;
278}
279
280static int machine__write_buildid_table(struct machine *machine, int fd)
281{
282 int err;
283 u16 kmisc = PERF_RECORD_MISC_KERNEL,
284 umisc = PERF_RECORD_MISC_USER;
285
286 if (!machine__is_host(machine)) {
287 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 }
290
291 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
292 machine->pid, kmisc, fd);
293 if (err == 0)
294 err = __dsos__write_buildid_table(&machine->user_dsos.head,
295 machine, machine->pid, umisc,
296 fd);
297 return err;
298}
299
300static int dsos__write_buildid_table(struct perf_header *header, int fd)
301{
302 struct perf_session *session = container_of(header,
303 struct perf_session, header);
304 struct rb_node *nd;
305 int err = machine__write_buildid_table(&session->machines.host, fd);
306
307 if (err)
308 return err;
309
310 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
311 struct machine *pos = rb_entry(nd, struct machine, rb_node);
312 err = machine__write_buildid_table(pos, fd);
313 if (err)
314 break;
315 }
316 return err;
317}
318
319int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
320 const char *name, bool is_kallsyms, bool is_vdso)
321{
322 const size_t size = PATH_MAX;
323 char *realname, *filename = zalloc(size),
324 *linkname = zalloc(size), *targetname;
325 int len, err = -1;
326 bool slash = is_kallsyms || is_vdso;
327
328 if (is_kallsyms) {
329 if (symbol_conf.kptr_restrict) {
330 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
331 err = 0;
332 goto out_free;
333 }
334 realname = (char *) name;
335 } else
336 realname = realpath(name, NULL);
337
338 if (realname == NULL || filename == NULL || linkname == NULL)
339 goto out_free;
340
341 len = scnprintf(filename, size, "%s%s%s",
342 debugdir, slash ? "/" : "",
343 is_vdso ? DSO__NAME_VDSO : realname);
344 if (mkdir_p(filename, 0755))
345 goto out_free;
346
347 snprintf(filename + len, size - len, "/%s", sbuild_id);
348
349 if (access(filename, F_OK)) {
350 if (is_kallsyms) {
351 if (copyfile("/proc/kallsyms", filename))
352 goto out_free;
353 } else if (link(realname, filename) && copyfile(name, filename))
354 goto out_free;
355 }
356
357 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
358 debugdir, sbuild_id);
359
360 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
361 goto out_free;
362
363 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
364 targetname = filename + strlen(debugdir) - 5;
365 memcpy(targetname, "../..", 5);
366
367 if (symlink(targetname, linkname) == 0)
368 err = 0;
369out_free:
370 if (!is_kallsyms)
371 free(realname);
372 free(filename);
373 free(linkname);
374 return err;
375}
376
377static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
378 const char *name, const char *debugdir,
379 bool is_kallsyms, bool is_vdso)
380{
381 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
382
383 build_id__sprintf(build_id, build_id_size, sbuild_id);
384
385 return build_id_cache__add_s(sbuild_id, debugdir, name,
386 is_kallsyms, is_vdso);
387}
388
389int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
390{
391 const size_t size = PATH_MAX;
392 char *filename = zalloc(size),
393 *linkname = zalloc(size);
394 int err = -1;
395
396 if (filename == NULL || linkname == NULL)
397 goto out_free;
398
399 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
400 debugdir, sbuild_id, sbuild_id + 2);
401
402 if (access(linkname, F_OK))
403 goto out_free;
404
405 if (readlink(linkname, filename, size - 1) < 0)
406 goto out_free;
407
408 if (unlink(linkname))
409 goto out_free;
410
411 /*
412 * Since the link is relative, we must make it absolute:
413 */
414 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
415 debugdir, sbuild_id, filename);
416
417 if (unlink(linkname))
418 goto out_free;
419
420 err = 0;
421out_free:
422 free(filename);
423 free(linkname);
424 return err;
425}
426
427static int dso__cache_build_id(struct dso *dso, struct machine *machine,
428 const char *debugdir)
429{
430 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
431 bool is_vdso = dso__is_vdso(dso);
432 const char *name = dso->long_name;
433 char nm[PATH_MAX];
434
435 if (dso__is_kcore(dso)) {
436 is_kallsyms = true;
437 machine__mmap_name(machine, nm, sizeof(nm));
438 name = nm;
439 }
440 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
441 debugdir, is_kallsyms, is_vdso);
442}
443
444static int __dsos__cache_build_ids(struct list_head *head,
445 struct machine *machine, const char *debugdir)
446{
447 struct dso *pos;
448 int err = 0;
449
450 dsos__for_each_with_build_id(pos, head)
451 if (dso__cache_build_id(pos, machine, debugdir))
452 err = -1;
453
454 return err;
455}
456
457static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
458{
459 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
460 debugdir);
461 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
462 debugdir);
463 return ret;
464}
465
466static int perf_session__cache_build_ids(struct perf_session *session)
467{
468 struct rb_node *nd;
469 int ret;
470 char debugdir[PATH_MAX];
471
472 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
473
474 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
475 return -1;
476
477 ret = machine__cache_build_ids(&session->machines.host, debugdir);
478
479 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
480 struct machine *pos = rb_entry(nd, struct machine, rb_node);
481 ret |= machine__cache_build_ids(pos, debugdir);
482 }
483 return ret ? -1 : 0;
484}
485
486static bool machine__read_build_ids(struct machine *machine, bool with_hits)
487{
488 bool ret;
489
490 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
491 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
492 return ret;
493}
494
495static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
496{
497 struct rb_node *nd;
498 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
499
500 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
501 struct machine *pos = rb_entry(nd, struct machine, rb_node);
502 ret |= machine__read_build_ids(pos, with_hits);
503 }
504
505 return ret;
506}
507
508static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, 169static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
509 struct perf_evlist *evlist) 170 struct perf_evlist *evlist)
510{ 171{
@@ -523,13 +184,12 @@ static int write_build_id(int fd, struct perf_header *h,
523 if (!perf_session__read_build_ids(session, true)) 184 if (!perf_session__read_build_ids(session, true))
524 return -1; 185 return -1;
525 186
526 err = dsos__write_buildid_table(h, fd); 187 err = perf_session__write_buildid_table(session, fd);
527 if (err < 0) { 188 if (err < 0) {
528 pr_debug("failed to write buildid table\n"); 189 pr_debug("failed to write buildid table\n");
529 return err; 190 return err;
530 } 191 }
531 if (!no_buildid_cache) 192 perf_session__cache_build_ids(session);
532 perf_session__cache_build_ids(session);
533 193
534 return 0; 194 return 0;
535} 195}
@@ -601,8 +261,10 @@ static int __write_cpudesc(int fd, const char *cpuinfo_proc)
601 break; 261 break;
602 } 262 }
603 263
604 if (ret) 264 if (ret) {
265 ret = -1;
605 goto done; 266 goto done;
267 }
606 268
607 s = buf; 269 s = buf;
608 270
@@ -965,7 +627,8 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
965 n = sscanf(buf, "%*s %"PRIu64, &mem); 627 n = sscanf(buf, "%*s %"PRIu64, &mem);
966 if (n == 1) 628 if (n == 1)
967 ret = do_write(fd, &mem, sizeof(mem)); 629 ret = do_write(fd, &mem, sizeof(mem));
968 } 630 } else
631 ret = -1;
969 free(buf); 632 free(buf);
970 fclose(fp); 633 fclose(fp);
971 return ret; 634 return ret;
@@ -1603,7 +1266,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1603 1266
1604 dso__set_build_id(dso, &bev->build_id); 1267 dso__set_build_id(dso, &bev->build_id);
1605 1268
1606 if (filename[0] == '[') 1269 if (!is_kernel_module(filename, NULL))
1607 dso->kernel = dso_type; 1270 dso->kernel = dso_type;
1608 1271
1609 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
@@ -2477,6 +2140,7 @@ static const int attr_file_abi_sizes[] = {
2477 [1] = PERF_ATTR_SIZE_VER1, 2140 [1] = PERF_ATTR_SIZE_VER1,
2478 [2] = PERF_ATTR_SIZE_VER2, 2141 [2] = PERF_ATTR_SIZE_VER2,
2479 [3] = PERF_ATTR_SIZE_VER3, 2142 [3] = PERF_ATTR_SIZE_VER3,
2143 [4] = PERF_ATTR_SIZE_VER4,
2480 0, 2144 0,
2481}; 2145};
2482 2146
@@ -3124,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
3124 session); 2788 session);
3125 return 0; 2789 return 0;
3126} 2790}
3127
3128void disable_buildid_cache(void)
3129{
3130 no_buildid_cache = true;
3131}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 8f5cbaea64a5..3bb90ac172a1 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -122,10 +122,6 @@ int perf_header__process_sections(struct perf_header *header, int fd,
122 122
123int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); 123int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
124 124
125int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
126 const char *name, bool is_kallsyms, bool is_vdso);
127int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
128
129int perf_event__synthesize_attr(struct perf_tool *tool, 125int perf_event__synthesize_attr(struct perf_tool *tool,
130 struct perf_event_attr *attr, u32 ids, u64 *id, 126 struct perf_event_attr *attr, u32 ids, u64 *id,
131 perf_event__handler_t process); 127 perf_event__handler_t process);
@@ -151,7 +147,9 @@ int perf_event__process_build_id(struct perf_tool *tool,
151 struct perf_session *session); 147 struct perf_session *session);
152bool is_perf_magic(u64 magic); 148bool is_perf_magic(u64 magic);
153 149
154int dsos__hit_all(struct perf_session *session); 150#define NAME_ALIGN 64
151
152int write_padded(int fd, const void *bf, size_t count, size_t count_aligned);
155 153
156/* 154/*
157 * arch specific callback 155 * arch specific callback
diff --git a/tools/perf/util/include/asm/hash.h b/tools/perf/util/include/asm/hash.h
deleted file mode 100644
index d82b170bb216..000000000000
--- a/tools/perf/util/include/asm/hash.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef __ASM_GENERIC_HASH_H
2#define __ASM_GENERIC_HASH_H
3
4/* Stub */
5
6#endif /* __ASM_GENERIC_HASH_H */
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
index 01ffd12dc791..40bd21488032 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -46,4 +46,21 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
46 __bitmap_or(dst, src1, src2, nbits); 46 __bitmap_or(dst, src1, src2, nbits);
47} 47}
48 48
49/**
50 * test_and_set_bit - Set a bit and return its old value
51 * @nr: Bit to set
52 * @addr: Address to count from
53 */
54static inline int test_and_set_bit(int nr, unsigned long *addr)
55{
56 unsigned long mask = BIT_MASK(nr);
57 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
58 unsigned long old;
59
60 old = *p;
61 *p = old | mask;
62
63 return (old & mask) != 0;
64}
65
49#endif /* _PERF_BITOPS_H */ 66#endif /* _PERF_BITOPS_H */
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
deleted file mode 100644
index dadfa7e54287..000000000000
--- a/tools/perf/util/include/linux/bitops.h
+++ /dev/null
@@ -1,160 +0,0 @@
1#ifndef _PERF_LINUX_BITOPS_H_
2#define _PERF_LINUX_BITOPS_H_
3
4#include <linux/kernel.h>
5#include <linux/compiler.h>
6#include <asm/hweight.h>
7
8#ifndef __WORDSIZE
9#define __WORDSIZE (__SIZEOF_LONG__ * 8)
10#endif
11
12#define BITS_PER_LONG __WORDSIZE
13#define BITS_PER_BYTE 8
14#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
15#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
16#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
17#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
18
19#define for_each_set_bit(bit, addr, size) \
20 for ((bit) = find_first_bit((addr), (size)); \
21 (bit) < (size); \
22 (bit) = find_next_bit((addr), (size), (bit) + 1))
23
24/* same as for_each_set_bit() but use bit as value to start with */
25#define for_each_set_bit_from(bit, addr, size) \
26 for ((bit) = find_next_bit((addr), (size), (bit)); \
27 (bit) < (size); \
28 (bit) = find_next_bit((addr), (size), (bit) + 1))
29
30static inline void set_bit(int nr, unsigned long *addr)
31{
32 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
33}
34
35static inline void clear_bit(int nr, unsigned long *addr)
36{
37 addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
38}
39
40static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
41{
42 return ((1UL << (nr % BITS_PER_LONG)) &
43 (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
44}
45
46static inline unsigned long hweight_long(unsigned long w)
47{
48 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
49}
50
51#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
52
53/**
54 * __ffs - find first bit in word.
55 * @word: The word to search
56 *
57 * Undefined if no bit exists, so code should check against 0 first.
58 */
59static __always_inline unsigned long __ffs(unsigned long word)
60{
61 int num = 0;
62
63#if BITS_PER_LONG == 64
64 if ((word & 0xffffffff) == 0) {
65 num += 32;
66 word >>= 32;
67 }
68#endif
69 if ((word & 0xffff) == 0) {
70 num += 16;
71 word >>= 16;
72 }
73 if ((word & 0xff) == 0) {
74 num += 8;
75 word >>= 8;
76 }
77 if ((word & 0xf) == 0) {
78 num += 4;
79 word >>= 4;
80 }
81 if ((word & 0x3) == 0) {
82 num += 2;
83 word >>= 2;
84 }
85 if ((word & 0x1) == 0)
86 num += 1;
87 return num;
88}
89
90typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
91
92/*
93 * Find the first set bit in a memory region.
94 */
95static inline unsigned long
96find_first_bit(const unsigned long *addr, unsigned long size)
97{
98 long_alias_t *p = (long_alias_t *) addr;
99 unsigned long result = 0;
100 unsigned long tmp;
101
102 while (size & ~(BITS_PER_LONG-1)) {
103 if ((tmp = *(p++)))
104 goto found;
105 result += BITS_PER_LONG;
106 size -= BITS_PER_LONG;
107 }
108 if (!size)
109 return result;
110
111 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
112 if (tmp == 0UL) /* Are any bits set? */
113 return result + size; /* Nope. */
114found:
115 return result + __ffs(tmp);
116}
117
118/*
119 * Find the next set bit in a memory region.
120 */
121static inline unsigned long
122find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
123{
124 const unsigned long *p = addr + BITOP_WORD(offset);
125 unsigned long result = offset & ~(BITS_PER_LONG-1);
126 unsigned long tmp;
127
128 if (offset >= size)
129 return size;
130 size -= result;
131 offset %= BITS_PER_LONG;
132 if (offset) {
133 tmp = *(p++);
134 tmp &= (~0UL << offset);
135 if (size < BITS_PER_LONG)
136 goto found_first;
137 if (tmp)
138 goto found_middle;
139 size -= BITS_PER_LONG;
140 result += BITS_PER_LONG;
141 }
142 while (size & ~(BITS_PER_LONG-1)) {
143 if ((tmp = *(p++)))
144 goto found_middle;
145 result += BITS_PER_LONG;
146 size -= BITS_PER_LONG;
147 }
148 if (!size)
149 return result;
150 tmp = *p;
151
152found_first:
153 tmp &= (~0UL >> (BITS_PER_LONG - size));
154 if (tmp == 0UL) /* Are any bits set? */
155 return result + size; /* Nope. */
156found_middle:
157 return result + __ffs(tmp);
158}
159
160#endif
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 34fc7c8672e4..94de3e48b490 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -12,6 +12,7 @@
12#include <stdbool.h> 12#include <stdbool.h>
13#include <symbol/kallsyms.h> 13#include <symbol/kallsyms.h>
14#include "unwind.h" 14#include "unwind.h"
15#include "linux/hash.h"
15 16
16static void dsos__init(struct dsos *dsos) 17static void dsos__init(struct dsos *dsos)
17{ 18{
@@ -21,7 +22,7 @@ static void dsos__init(struct dsos *dsos)
21 22
22int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 23int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
23{ 24{
24 map_groups__init(&machine->kmaps); 25 map_groups__init(&machine->kmaps, machine);
25 RB_CLEAR_NODE(&machine->rb_node); 26 RB_CLEAR_NODE(&machine->rb_node);
26 dsos__init(&machine->user_dsos); 27 dsos__init(&machine->user_dsos);
27 dsos__init(&machine->kernel_dsos); 28 dsos__init(&machine->kernel_dsos);
@@ -32,7 +33,6 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
32 33
33 machine->vdso_info = NULL; 34 machine->vdso_info = NULL;
34 35
35 machine->kmaps.machine = machine;
36 machine->pid = pid; 36 machine->pid = pid;
37 37
38 machine->symbol_filter = NULL; 38 machine->symbol_filter = NULL;
@@ -319,7 +319,7 @@ static void machine__update_thread_pid(struct machine *machine,
319 goto out_err; 319 goto out_err;
320 320
321 if (!leader->mg) 321 if (!leader->mg)
322 leader->mg = map_groups__new(); 322 leader->mg = map_groups__new(machine);
323 323
324 if (!leader->mg) 324 if (!leader->mg)
325 goto out_err; 325 goto out_err;
@@ -465,6 +465,7 @@ struct map *machine__new_module(struct machine *machine, u64 start,
465{ 465{
466 struct map *map; 466 struct map *map;
467 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 467 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
468 bool compressed;
468 469
469 if (dso == NULL) 470 if (dso == NULL)
470 return NULL; 471 return NULL;
@@ -477,6 +478,11 @@ struct map *machine__new_module(struct machine *machine, u64 start,
477 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 478 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
478 else 479 else
479 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; 480 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
481
482 /* _KMODULE_COMP should be next to _KMODULE */
483 if (is_kernel_module(filename, &compressed) && compressed)
484 dso->symtab_type++;
485
480 map_groups__insert(&machine->kmaps, map); 486 map_groups__insert(&machine->kmaps, map);
481 return map; 487 return map;
482} 488}
@@ -862,8 +868,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
862 struct map *map; 868 struct map *map;
863 char *long_name; 869 char *long_name;
864 870
865 if (dot == NULL || strcmp(dot, ".ko")) 871 if (dot == NULL)
866 continue; 872 continue;
873
874 /* On some system, modules are compressed like .ko.gz */
875 if (is_supported_compression(dot + 1) &&
876 is_kmodule_extension(dot - 2))
877 dot -= 3;
878
867 snprintf(dso_name, sizeof(dso_name), "[%.*s]", 879 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
868 (int)(dot - dent->d_name), dent->d_name); 880 (int)(dot - dent->d_name), dent->d_name);
869 881
@@ -1045,6 +1057,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1045 dot = strrchr(name, '.'); 1057 dot = strrchr(name, '.');
1046 if (dot == NULL) 1058 if (dot == NULL)
1047 goto out_problem; 1059 goto out_problem;
1060 /* On some system, modules are compressed like .ko.gz */
1061 if (is_supported_compression(dot + 1))
1062 dot -= 3;
1063 if (!is_kmodule_extension(dot + 1))
1064 goto out_problem;
1048 snprintf(short_module_name, sizeof(short_module_name), 1065 snprintf(short_module_name, sizeof(short_module_name),
1049 "[%.*s]", (int)(dot - name), name); 1066 "[%.*s]", (int)(dot - name), name);
1050 strxfrchar(short_module_name, '-', '_'); 1067 strxfrchar(short_module_name, '-', '_');
@@ -1069,8 +1086,20 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1069 * Should be there already, from the build-id table in 1086 * Should be there already, from the build-id table in
1070 * the header. 1087 * the header.
1071 */ 1088 */
1072 struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, 1089 struct dso *kernel = NULL;
1073 kmmap_prefix); 1090 struct dso *dso;
1091
1092 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
1093 if (is_kernel_module(dso->long_name, NULL))
1094 continue;
1095
1096 kernel = dso;
1097 break;
1098 }
1099
1100 if (kernel == NULL)
1101 kernel = __dsos__findnew(&machine->kernel_dsos,
1102 kmmap_prefix);
1074 if (kernel == NULL) 1103 if (kernel == NULL)
1075 goto out_problem; 1104 goto out_problem;
1076 1105
@@ -1078,6 +1107,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1078 if (__machine__create_kernel_maps(machine, kernel) < 0) 1107 if (__machine__create_kernel_maps(machine, kernel) < 0)
1079 goto out_problem; 1108 goto out_problem;
1080 1109
1110 if (strstr(kernel->long_name, "vmlinux"))
1111 dso__set_short_name(kernel, "[kernel.vmlinux]", false);
1112
1081 machine__set_kernel_mmap_len(machine, event); 1113 machine__set_kernel_mmap_len(machine, event);
1082 1114
1083 /* 1115 /*
@@ -1290,7 +1322,7 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
1290 return 0; 1322 return 0;
1291} 1323}
1292 1324
1293static void ip__resolve_ams(struct machine *machine, struct thread *thread, 1325static void ip__resolve_ams(struct thread *thread,
1294 struct addr_map_symbol *ams, 1326 struct addr_map_symbol *ams,
1295 u64 ip) 1327 u64 ip)
1296{ 1328{
@@ -1304,7 +1336,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1304 * Thus, we have to try consecutively until we find a match 1336 * Thus, we have to try consecutively until we find a match
1305 * or else, the symbol is unknown 1337 * or else, the symbol is unknown
1306 */ 1338 */
1307 thread__find_cpumode_addr_location(thread, machine, MAP__FUNCTION, ip, &al); 1339 thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al);
1308 1340
1309 ams->addr = ip; 1341 ams->addr = ip;
1310 ams->al_addr = al.addr; 1342 ams->al_addr = al.addr;
@@ -1312,23 +1344,21 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1312 ams->map = al.map; 1344 ams->map = al.map;
1313} 1345}
1314 1346
1315static void ip__resolve_data(struct machine *machine, struct thread *thread, 1347static void ip__resolve_data(struct thread *thread,
1316 u8 m, struct addr_map_symbol *ams, u64 addr) 1348 u8 m, struct addr_map_symbol *ams, u64 addr)
1317{ 1349{
1318 struct addr_location al; 1350 struct addr_location al;
1319 1351
1320 memset(&al, 0, sizeof(al)); 1352 memset(&al, 0, sizeof(al));
1321 1353
1322 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, 1354 thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al);
1323 &al);
1324 if (al.map == NULL) { 1355 if (al.map == NULL) {
1325 /* 1356 /*
1326 * some shared data regions have execute bit set which puts 1357 * some shared data regions have execute bit set which puts
1327 * their mapping in the MAP__FUNCTION type array. 1358 * their mapping in the MAP__FUNCTION type array.
1328 * Check there as a fallback option before dropping the sample. 1359 * Check there as a fallback option before dropping the sample.
1329 */ 1360 */
1330 thread__find_addr_location(thread, machine, m, MAP__FUNCTION, addr, 1361 thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al);
1331 &al);
1332 } 1362 }
1333 1363
1334 ams->addr = addr; 1364 ams->addr = addr;
@@ -1345,14 +1375,72 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1345 if (!mi) 1375 if (!mi)
1346 return NULL; 1376 return NULL;
1347 1377
1348 ip__resolve_ams(al->machine, al->thread, &mi->iaddr, sample->ip); 1378 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip);
1349 ip__resolve_data(al->machine, al->thread, al->cpumode, 1379 ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr);
1350 &mi->daddr, sample->addr);
1351 mi->data_src.val = sample->data_src; 1380 mi->data_src.val = sample->data_src;
1352 1381
1353 return mi; 1382 return mi;
1354} 1383}
1355 1384
1385static int add_callchain_ip(struct thread *thread,
1386 struct symbol **parent,
1387 struct addr_location *root_al,
1388 bool branch_history,
1389 u64 ip)
1390{
1391 struct addr_location al;
1392
1393 al.filtered = 0;
1394 al.sym = NULL;
1395 if (branch_history)
1396 thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
1397 ip, &al);
1398 else {
1399 u8 cpumode = PERF_RECORD_MISC_USER;
1400
1401 if (ip >= PERF_CONTEXT_MAX) {
1402 switch (ip) {
1403 case PERF_CONTEXT_HV:
1404 cpumode = PERF_RECORD_MISC_HYPERVISOR;
1405 break;
1406 case PERF_CONTEXT_KERNEL:
1407 cpumode = PERF_RECORD_MISC_KERNEL;
1408 break;
1409 case PERF_CONTEXT_USER:
1410 cpumode = PERF_RECORD_MISC_USER;
1411 break;
1412 default:
1413 pr_debug("invalid callchain context: "
1414 "%"PRId64"\n", (s64) ip);
1415 /*
1416 * It seems the callchain is corrupted.
1417 * Discard all.
1418 */
1419 callchain_cursor_reset(&callchain_cursor);
1420 return 1;
1421 }
1422 return 0;
1423 }
1424 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
1425 ip, &al);
1426 }
1427
1428 if (al.sym != NULL) {
1429 if (sort__has_parent && !*parent &&
1430 symbol__match_regex(al.sym, &parent_regex))
1431 *parent = al.sym;
1432 else if (have_ignore_callees && root_al &&
1433 symbol__match_regex(al.sym, &ignore_callees_regex)) {
1434 /* Treat this symbol as the root,
1435 forgetting its callees. */
1436 *root_al = al;
1437 callchain_cursor_reset(&callchain_cursor);
1438 }
1439 }
1440
1441 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym);
1442}
1443
1356struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1444struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1357 struct addr_location *al) 1445 struct addr_location *al)
1358{ 1446{
@@ -1364,43 +1452,140 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1364 return NULL; 1452 return NULL;
1365 1453
1366 for (i = 0; i < bs->nr; i++) { 1454 for (i = 0; i < bs->nr; i++) {
1367 ip__resolve_ams(al->machine, al->thread, &bi[i].to, bs->entries[i].to); 1455 ip__resolve_ams(al->thread, &bi[i].to, bs->entries[i].to);
1368 ip__resolve_ams(al->machine, al->thread, &bi[i].from, bs->entries[i].from); 1456 ip__resolve_ams(al->thread, &bi[i].from, bs->entries[i].from);
1369 bi[i].flags = bs->entries[i].flags; 1457 bi[i].flags = bs->entries[i].flags;
1370 } 1458 }
1371 return bi; 1459 return bi;
1372} 1460}
1373 1461
1374static int machine__resolve_callchain_sample(struct machine *machine, 1462#define CHASHSZ 127
1375 struct thread *thread, 1463#define CHASHBITS 7
1464#define NO_ENTRY 0xff
1465
1466#define PERF_MAX_BRANCH_DEPTH 127
1467
1468/* Remove loops. */
1469static int remove_loops(struct branch_entry *l, int nr)
1470{
1471 int i, j, off;
1472 unsigned char chash[CHASHSZ];
1473
1474 memset(chash, NO_ENTRY, sizeof(chash));
1475
1476 BUG_ON(PERF_MAX_BRANCH_DEPTH > 255);
1477
1478 for (i = 0; i < nr; i++) {
1479 int h = hash_64(l[i].from, CHASHBITS) % CHASHSZ;
1480
1481 /* no collision handling for now */
1482 if (chash[h] == NO_ENTRY) {
1483 chash[h] = i;
1484 } else if (l[chash[h]].from == l[i].from) {
1485 bool is_loop = true;
1486 /* check if it is a real loop */
1487 off = 0;
1488 for (j = chash[h]; j < i && i + off < nr; j++, off++)
1489 if (l[j].from != l[i + off].from) {
1490 is_loop = false;
1491 break;
1492 }
1493 if (is_loop) {
1494 memmove(l + i, l + i + off,
1495 (nr - (i + off)) * sizeof(*l));
1496 nr -= off;
1497 }
1498 }
1499 }
1500 return nr;
1501}
1502
1503static int thread__resolve_callchain_sample(struct thread *thread,
1376 struct ip_callchain *chain, 1504 struct ip_callchain *chain,
1505 struct branch_stack *branch,
1377 struct symbol **parent, 1506 struct symbol **parent,
1378 struct addr_location *root_al, 1507 struct addr_location *root_al,
1379 int max_stack) 1508 int max_stack)
1380{ 1509{
1381 u8 cpumode = PERF_RECORD_MISC_USER;
1382 int chain_nr = min(max_stack, (int)chain->nr); 1510 int chain_nr = min(max_stack, (int)chain->nr);
1383 int i; 1511 int i, j, err;
1384 int j; 1512 int skip_idx = -1;
1385 int err; 1513 int first_call = 0;
1386 int skip_idx __maybe_unused; 1514
1515 /*
1516 * Based on DWARF debug information, some architectures skip
1517 * a callchain entry saved by the kernel.
1518 */
1519 if (chain->nr < PERF_MAX_STACK_DEPTH)
1520 skip_idx = arch_skip_callchain_idx(thread, chain);
1387 1521
1388 callchain_cursor_reset(&callchain_cursor); 1522 callchain_cursor_reset(&callchain_cursor);
1389 1523
1524 /*
1525 * Add branches to call stack for easier browsing. This gives
1526 * more context for a sample than just the callers.
1527 *
1528 * This uses individual histograms of paths compared to the
1529 * aggregated histograms the normal LBR mode uses.
1530 *
1531 * Limitations for now:
1532 * - No extra filters
1533 * - No annotations (should annotate somehow)
1534 */
1535
1536 if (branch && callchain_param.branch_callstack) {
1537 int nr = min(max_stack, (int)branch->nr);
1538 struct branch_entry be[nr];
1539
1540 if (branch->nr > PERF_MAX_BRANCH_DEPTH) {
1541 pr_warning("corrupted branch chain. skipping...\n");
1542 goto check_calls;
1543 }
1544
1545 for (i = 0; i < nr; i++) {
1546 if (callchain_param.order == ORDER_CALLEE) {
1547 be[i] = branch->entries[i];
1548 /*
1549 * Check for overlap into the callchain.
1550 * The return address is one off compared to
1551 * the branch entry. To adjust for this
1552 * assume the calling instruction is not longer
1553 * than 8 bytes.
1554 */
1555 if (i == skip_idx ||
1556 chain->ips[first_call] >= PERF_CONTEXT_MAX)
1557 first_call++;
1558 else if (be[i].from < chain->ips[first_call] &&
1559 be[i].from >= chain->ips[first_call] - 8)
1560 first_call++;
1561 } else
1562 be[i] = branch->entries[branch->nr - i - 1];
1563 }
1564
1565 nr = remove_loops(be, nr);
1566
1567 for (i = 0; i < nr; i++) {
1568 err = add_callchain_ip(thread, parent, root_al,
1569 true, be[i].to);
1570 if (!err)
1571 err = add_callchain_ip(thread, parent, root_al,
1572 true, be[i].from);
1573 if (err == -EINVAL)
1574 break;
1575 if (err)
1576 return err;
1577 }
1578 chain_nr -= nr;
1579 }
1580
1581check_calls:
1390 if (chain->nr > PERF_MAX_STACK_DEPTH) { 1582 if (chain->nr > PERF_MAX_STACK_DEPTH) {
1391 pr_warning("corrupted callchain. skipping...\n"); 1583 pr_warning("corrupted callchain. skipping...\n");
1392 return 0; 1584 return 0;
1393 } 1585 }
1394 1586
1395 /* 1587 for (i = first_call; i < chain_nr; i++) {
1396 * Based on DWARF debug information, some architectures skip
1397 * a callchain entry saved by the kernel.
1398 */
1399 skip_idx = arch_skip_callchain_idx(machine, thread, chain);
1400
1401 for (i = 0; i < chain_nr; i++) {
1402 u64 ip; 1588 u64 ip;
1403 struct addr_location al;
1404 1589
1405 if (callchain_param.order == ORDER_CALLEE) 1590 if (callchain_param.order == ORDER_CALLEE)
1406 j = i; 1591 j = i;
@@ -1413,50 +1598,10 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1413#endif 1598#endif
1414 ip = chain->ips[j]; 1599 ip = chain->ips[j];
1415 1600
1416 if (ip >= PERF_CONTEXT_MAX) { 1601 err = add_callchain_ip(thread, parent, root_al, false, ip);
1417 switch (ip) {
1418 case PERF_CONTEXT_HV:
1419 cpumode = PERF_RECORD_MISC_HYPERVISOR;
1420 break;
1421 case PERF_CONTEXT_KERNEL:
1422 cpumode = PERF_RECORD_MISC_KERNEL;
1423 break;
1424 case PERF_CONTEXT_USER:
1425 cpumode = PERF_RECORD_MISC_USER;
1426 break;
1427 default:
1428 pr_debug("invalid callchain context: "
1429 "%"PRId64"\n", (s64) ip);
1430 /*
1431 * It seems the callchain is corrupted.
1432 * Discard all.
1433 */
1434 callchain_cursor_reset(&callchain_cursor);
1435 return 0;
1436 }
1437 continue;
1438 }
1439 1602
1440 al.filtered = 0;
1441 thread__find_addr_location(thread, machine, cpumode,
1442 MAP__FUNCTION, ip, &al);
1443 if (al.sym != NULL) {
1444 if (sort__has_parent && !*parent &&
1445 symbol__match_regex(al.sym, &parent_regex))
1446 *parent = al.sym;
1447 else if (have_ignore_callees && root_al &&
1448 symbol__match_regex(al.sym, &ignore_callees_regex)) {
1449 /* Treat this symbol as the root,
1450 forgetting its callees. */
1451 *root_al = al;
1452 callchain_cursor_reset(&callchain_cursor);
1453 }
1454 }
1455
1456 err = callchain_cursor_append(&callchain_cursor,
1457 ip, al.map, al.sym);
1458 if (err) 1603 if (err)
1459 return err; 1604 return (err < 0) ? err : 0;
1460 } 1605 }
1461 1606
1462 return 0; 1607 return 0;
@@ -1469,19 +1614,16 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
1469 entry->map, entry->sym); 1614 entry->map, entry->sym);
1470} 1615}
1471 1616
1472int machine__resolve_callchain(struct machine *machine, 1617int thread__resolve_callchain(struct thread *thread,
1473 struct perf_evsel *evsel, 1618 struct perf_evsel *evsel,
1474 struct thread *thread, 1619 struct perf_sample *sample,
1475 struct perf_sample *sample, 1620 struct symbol **parent,
1476 struct symbol **parent, 1621 struct addr_location *root_al,
1477 struct addr_location *root_al, 1622 int max_stack)
1478 int max_stack)
1479{ 1623{
1480 int ret; 1624 int ret = thread__resolve_callchain_sample(thread, sample->callchain,
1481 1625 sample->branch_stack,
1482 ret = machine__resolve_callchain_sample(machine, thread, 1626 parent, root_al, max_stack);
1483 sample->callchain, parent,
1484 root_al, max_stack);
1485 if (ret) 1627 if (ret)
1486 return ret; 1628 return ret;
1487 1629
@@ -1495,7 +1637,7 @@ int machine__resolve_callchain(struct machine *machine,
1495 (!sample->user_stack.size)) 1637 (!sample->user_stack.size))
1496 return 0; 1638 return 0;
1497 1639
1498 return unwind__get_entries(unwind_entry, &callchain_cursor, machine, 1640 return unwind__get_entries(unwind_entry, &callchain_cursor,
1499 thread, sample, max_stack); 1641 thread, sample, max_stack);
1500 1642
1501} 1643}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 2b651a7f5d0d..e8b7779a0a3f 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -40,6 +40,10 @@ struct machine {
40 u64 kernel_start; 40 u64 kernel_start;
41 symbol_filter_t symbol_filter; 41 symbol_filter_t symbol_filter;
42 pid_t *current_tid; 42 pid_t *current_tid;
43 union { /* Tool specific area */
44 void *priv;
45 u64 db_id;
46 };
43}; 47};
44 48
45static inline 49static inline
@@ -122,13 +126,12 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
122 struct addr_location *al); 126 struct addr_location *al);
123struct mem_info *sample__resolve_mem(struct perf_sample *sample, 127struct mem_info *sample__resolve_mem(struct perf_sample *sample,
124 struct addr_location *al); 128 struct addr_location *al);
125int machine__resolve_callchain(struct machine *machine, 129int thread__resolve_callchain(struct thread *thread,
126 struct perf_evsel *evsel, 130 struct perf_evsel *evsel,
127 struct thread *thread, 131 struct perf_sample *sample,
128 struct perf_sample *sample, 132 struct symbol **parent,
129 struct symbol **parent, 133 struct addr_location *root_al,
130 struct addr_location *root_al, 134 int max_stack);
131 int max_stack);
132 135
133/* 136/*
134 * Default guest kernel is defined by parameter --guestkallsyms 137 * Default guest kernel is defined by parameter --guestkallsyms
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 2137c4596ec7..62ca9f2607d5 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -360,7 +360,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
360 360
361 if (map && map->dso) { 361 if (map && map->dso) {
362 srcline = get_srcline(map->dso, 362 srcline = get_srcline(map->dso,
363 map__rip_2objdump(map, addr)); 363 map__rip_2objdump(map, addr), NULL, true);
364 if (srcline != SRCLINE_UNKNOWN) 364 if (srcline != SRCLINE_UNKNOWN)
365 ret = fprintf(fp, "%s%s", prefix, srcline); 365 ret = fprintf(fp, "%s%s", prefix, srcline);
366 free_srcline(srcline); 366 free_srcline(srcline);
@@ -413,14 +413,14 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
413 return ip + map->reloc; 413 return ip + map->reloc;
414} 414}
415 415
416void map_groups__init(struct map_groups *mg) 416void map_groups__init(struct map_groups *mg, struct machine *machine)
417{ 417{
418 int i; 418 int i;
419 for (i = 0; i < MAP__NR_TYPES; ++i) { 419 for (i = 0; i < MAP__NR_TYPES; ++i) {
420 mg->maps[i] = RB_ROOT; 420 mg->maps[i] = RB_ROOT;
421 INIT_LIST_HEAD(&mg->removed_maps[i]); 421 INIT_LIST_HEAD(&mg->removed_maps[i]);
422 } 422 }
423 mg->machine = NULL; 423 mg->machine = machine;
424 mg->refcnt = 1; 424 mg->refcnt = 1;
425} 425}
426 426
@@ -471,12 +471,12 @@ bool map_groups__empty(struct map_groups *mg)
471 return true; 471 return true;
472} 472}
473 473
474struct map_groups *map_groups__new(void) 474struct map_groups *map_groups__new(struct machine *machine)
475{ 475{
476 struct map_groups *mg = malloc(sizeof(*mg)); 476 struct map_groups *mg = malloc(sizeof(*mg));
477 477
478 if (mg != NULL) 478 if (mg != NULL)
479 map_groups__init(mg); 479 map_groups__init(mg, machine);
480 480
481 return mg; 481 return mg;
482} 482}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2f83954af050..6951a9d42339 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -64,7 +64,7 @@ struct map_groups {
64 int refcnt; 64 int refcnt;
65}; 65};
66 66
67struct map_groups *map_groups__new(void); 67struct map_groups *map_groups__new(struct machine *machine);
68void map_groups__delete(struct map_groups *mg); 68void map_groups__delete(struct map_groups *mg);
69bool map_groups__empty(struct map_groups *mg); 69bool map_groups__empty(struct map_groups *mg);
70 70
@@ -150,7 +150,7 @@ void maps__remove(struct rb_root *maps, struct map *map);
150struct map *maps__find(struct rb_root *maps, u64 addr); 150struct map *maps__find(struct rb_root *maps, u64 addr);
151struct map *maps__first(struct rb_root *maps); 151struct map *maps__first(struct rb_root *maps);
152struct map *maps__next(struct map *map); 152struct map *maps__next(struct map *map);
153void map_groups__init(struct map_groups *mg); 153void map_groups__init(struct map_groups *mg, struct machine *machine);
154void map_groups__exit(struct map_groups *mg); 154void map_groups__exit(struct map_groups *mg);
155int map_groups__clone(struct map_groups *mg, 155int map_groups__clone(struct map_groups *mg,
156 struct map_groups *parent, enum map_type type); 156 struct map_groups *parent, enum map_type type);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index c659a3ca1283..77b43fe43d55 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -681,6 +681,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
681 if (evsel) { 681 if (evsel) {
682 evsel->unit = info.unit; 682 evsel->unit = info.unit;
683 evsel->scale = info.scale; 683 evsel->scale = info.scale;
684 evsel->per_pkg = info.per_pkg;
685 evsel->snapshot = info.snapshot;
684 } 686 }
685 687
686 return evsel ? 0 : -ENOMEM; 688 return evsel ? 0 : -ENOMEM;
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index bf48092983c6..f62dee7bd924 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -42,7 +42,26 @@ static int get_value(struct parse_opt_ctx_t *p,
42 return opterror(opt, "takes no value", flags); 42 return opterror(opt, "takes no value", flags);
43 if (unset && (opt->flags & PARSE_OPT_NONEG)) 43 if (unset && (opt->flags & PARSE_OPT_NONEG))
44 return opterror(opt, "isn't available", flags); 44 return opterror(opt, "isn't available", flags);
45 45 if (opt->flags & PARSE_OPT_DISABLED)
46 return opterror(opt, "is not usable", flags);
47
48 if (opt->flags & PARSE_OPT_EXCLUSIVE) {
49 if (p->excl_opt) {
50 char msg[128];
51
52 if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
53 p->excl_opt->long_name == NULL) {
54 scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
55 p->excl_opt->short_name);
56 } else {
57 scnprintf(msg, sizeof(msg), "cannot be used with %s",
58 p->excl_opt->long_name);
59 }
60 opterror(opt, msg, flags);
61 return -3;
62 }
63 p->excl_opt = opt;
64 }
46 if (!(flags & OPT_SHORT) && p->opt) { 65 if (!(flags & OPT_SHORT) && p->opt) {
47 switch (opt->type) { 66 switch (opt->type) {
48 case OPTION_CALLBACK: 67 case OPTION_CALLBACK:
@@ -343,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
343 const char * const usagestr[]) 362 const char * const usagestr[])
344{ 363{
345 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); 364 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
365 int excl_short_opt = 1;
366 const char *arg;
346 367
347 /* we must reset ->opt, unknown short option leave it dangling */ 368 /* we must reset ->opt, unknown short option leave it dangling */
348 ctx->opt = NULL; 369 ctx->opt = NULL;
349 370
350 for (; ctx->argc; ctx->argc--, ctx->argv++) { 371 for (; ctx->argc; ctx->argc--, ctx->argv++) {
351 const char *arg = ctx->argv[0]; 372 arg = ctx->argv[0];
352
353 if (*arg != '-' || !arg[1]) { 373 if (*arg != '-' || !arg[1]) {
354 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) 374 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
355 break; 375 break;
@@ -358,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
358 } 378 }
359 379
360 if (arg[1] != '-') { 380 if (arg[1] != '-') {
361 ctx->opt = arg + 1; 381 ctx->opt = ++arg;
362 if (internal_help && *ctx->opt == 'h') 382 if (internal_help && *ctx->opt == 'h')
363 return usage_with_options_internal(usagestr, options, 0); 383 return usage_with_options_internal(usagestr, options, 0);
364 switch (parse_short_opt(ctx, options)) { 384 switch (parse_short_opt(ctx, options)) {
365 case -1: 385 case -1:
366 return parse_options_usage(usagestr, options, arg + 1, 1); 386 return parse_options_usage(usagestr, options, arg, 1);
367 case -2: 387 case -2:
368 goto unknown; 388 goto unknown;
389 case -3:
390 goto exclusive;
369 default: 391 default:
370 break; 392 break;
371 } 393 }
372 if (ctx->opt) 394 if (ctx->opt)
373 check_typos(arg + 1, options); 395 check_typos(arg, options);
374 while (ctx->opt) { 396 while (ctx->opt) {
375 if (internal_help && *ctx->opt == 'h') 397 if (internal_help && *ctx->opt == 'h')
376 return usage_with_options_internal(usagestr, options, 0); 398 return usage_with_options_internal(usagestr, options, 0);
@@ -387,6 +409,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
387 ctx->argv[0] = strdup(ctx->opt - 1); 409 ctx->argv[0] = strdup(ctx->opt - 1);
388 *(char *)ctx->argv[0] = '-'; 410 *(char *)ctx->argv[0] = '-';
389 goto unknown; 411 goto unknown;
412 case -3:
413 goto exclusive;
390 default: 414 default:
391 break; 415 break;
392 } 416 }
@@ -402,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
402 break; 426 break;
403 } 427 }
404 428
405 if (internal_help && !strcmp(arg + 2, "help-all")) 429 arg += 2;
430 if (internal_help && !strcmp(arg, "help-all"))
406 return usage_with_options_internal(usagestr, options, 1); 431 return usage_with_options_internal(usagestr, options, 1);
407 if (internal_help && !strcmp(arg + 2, "help")) 432 if (internal_help && !strcmp(arg, "help"))
408 return usage_with_options_internal(usagestr, options, 0); 433 return usage_with_options_internal(usagestr, options, 0);
409 if (!strcmp(arg + 2, "list-opts")) 434 if (!strcmp(arg, "list-opts"))
410 return PARSE_OPT_LIST_OPTS; 435 return PARSE_OPT_LIST_OPTS;
411 if (!strcmp(arg + 2, "list-cmds")) 436 if (!strcmp(arg, "list-cmds"))
412 return PARSE_OPT_LIST_SUBCMDS; 437 return PARSE_OPT_LIST_SUBCMDS;
413 switch (parse_long_opt(ctx, arg + 2, options)) { 438 switch (parse_long_opt(ctx, arg, options)) {
414 case -1: 439 case -1:
415 return parse_options_usage(usagestr, options, arg + 2, 0); 440 return parse_options_usage(usagestr, options, arg, 0);
416 case -2: 441 case -2:
417 goto unknown; 442 goto unknown;
443 case -3:
444 excl_short_opt = 0;
445 goto exclusive;
418 default: 446 default:
419 break; 447 break;
420 } 448 }
@@ -426,6 +454,17 @@ unknown:
426 ctx->opt = NULL; 454 ctx->opt = NULL;
427 } 455 }
428 return PARSE_OPT_DONE; 456 return PARSE_OPT_DONE;
457
458exclusive:
459 parse_options_usage(usagestr, options, arg, excl_short_opt);
460 if ((excl_short_opt && ctx->excl_opt->short_name) ||
461 ctx->excl_opt->long_name == NULL) {
462 char opt = ctx->excl_opt->short_name;
463 parse_options_usage(NULL, options, &opt, 1);
464 } else {
465 parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
466 }
467 return PARSE_OPT_HELP;
429} 468}
430 469
431int parse_options_end(struct parse_opt_ctx_t *ctx) 470int parse_options_end(struct parse_opt_ctx_t *ctx)
@@ -509,6 +548,8 @@ static void print_option_help(const struct option *opts, int full)
509 } 548 }
510 if (!full && (opts->flags & PARSE_OPT_HIDDEN)) 549 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
511 return; 550 return;
551 if (opts->flags & PARSE_OPT_DISABLED)
552 return;
512 553
513 pos = fprintf(stderr, " "); 554 pos = fprintf(stderr, " ");
514 if (opts->short_name) 555 if (opts->short_name)
@@ -679,3 +720,16 @@ int parse_opt_verbosity_cb(const struct option *opt,
679 } 720 }
680 return 0; 721 return 0;
681} 722}
723
724void set_option_flag(struct option *opts, int shortopt, const char *longopt,
725 int flag)
726{
727 for (; opts->type != OPTION_END; opts++) {
728 if ((shortopt && opts->short_name == shortopt) ||
729 (opts->long_name && longopt &&
730 !strcmp(opts->long_name, longopt))) {
731 opts->flags |= flag;
732 break;
733 }
734 }
735}
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index b59ba858e73d..97b153fb4999 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -38,6 +38,8 @@ enum parse_opt_option_flags {
38 PARSE_OPT_NONEG = 4, 38 PARSE_OPT_NONEG = 4,
39 PARSE_OPT_HIDDEN = 8, 39 PARSE_OPT_HIDDEN = 8,
40 PARSE_OPT_LASTARG_DEFAULT = 16, 40 PARSE_OPT_LASTARG_DEFAULT = 16,
41 PARSE_OPT_DISABLED = 32,
42 PARSE_OPT_EXCLUSIVE = 64,
41}; 43};
42 44
43struct option; 45struct option;
@@ -173,6 +175,7 @@ struct parse_opt_ctx_t {
173 const char **out; 175 const char **out;
174 int argc, cpidx; 176 int argc, cpidx;
175 const char *opt; 177 const char *opt;
178 const struct option *excl_opt;
176 int flags; 179 int flags;
177}; 180};
178 181
@@ -211,4 +214,5 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
211 214
212extern const char *parse_options_fix_filename(const char *prefix, const char *file); 215extern const char *parse_options_fix_filename(const char *prefix, const char *file);
213 216
217void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
214#endif /* __PERF_PARSE_OPTIONS_H */ 218#endif /* __PERF_PARSE_OPTIONS_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index e243ad962a4d..5c9c4947cfb4 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -163,6 +163,41 @@ error:
163 return -1; 163 return -1;
164} 164}
165 165
166static int
167perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
168{
169 char path[PATH_MAX];
170 int fd;
171
172 snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
173
174 fd = open(path, O_RDONLY);
175 if (fd == -1)
176 return -1;
177
178 close(fd);
179
180 alias->per_pkg = true;
181 return 0;
182}
183
184static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
185 char *dir, char *name)
186{
187 char path[PATH_MAX];
188 int fd;
189
190 snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
191
192 fd = open(path, O_RDONLY);
193 if (fd == -1)
194 return -1;
195
196 alias->snapshot = true;
197 close(fd);
198 return 0;
199}
200
166static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) 201static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
167{ 202{
168 struct perf_pmu_alias *alias; 203 struct perf_pmu_alias *alias;
@@ -181,6 +216,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
181 INIT_LIST_HEAD(&alias->terms); 216 INIT_LIST_HEAD(&alias->terms);
182 alias->scale = 1.0; 217 alias->scale = 1.0;
183 alias->unit[0] = '\0'; 218 alias->unit[0] = '\0';
219 alias->per_pkg = false;
184 220
185 ret = parse_events_terms(&alias->terms, buf); 221 ret = parse_events_terms(&alias->terms, buf);
186 if (ret) { 222 if (ret) {
@@ -194,6 +230,8 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
194 */ 230 */
195 perf_pmu__parse_unit(alias, dir, name); 231 perf_pmu__parse_unit(alias, dir, name);
196 perf_pmu__parse_scale(alias, dir, name); 232 perf_pmu__parse_scale(alias, dir, name);
233 perf_pmu__parse_per_pkg(alias, dir, name);
234 perf_pmu__parse_snapshot(alias, dir, name);
197 235
198 list_add_tail(&alias->list, list); 236 list_add_tail(&alias->list, list);
199 237
@@ -209,6 +247,10 @@ static inline bool pmu_alias_info_file(char *name)
209 return true; 247 return true;
210 if (len > 6 && !strcmp(name + len - 6, ".scale")) 248 if (len > 6 && !strcmp(name + len - 6, ".scale"))
211 return true; 249 return true;
250 if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
251 return true;
252 if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
253 return true;
212 254
213 return false; 255 return false;
214} 256}
@@ -617,23 +659,27 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
617} 659}
618 660
619 661
620static int check_unit_scale(struct perf_pmu_alias *alias, 662static int check_info_data(struct perf_pmu_alias *alias,
621 const char **unit, double *scale) 663 struct perf_pmu_info *info)
622{ 664{
623 /* 665 /*
624 * Only one term in event definition can 666 * Only one term in event definition can
625 * define unit and scale, fail if there's 667 * define unit, scale and snapshot, fail
626 * more than one. 668 * if there's more than one.
627 */ 669 */
628 if ((*unit && alias->unit) || 670 if ((info->unit && alias->unit) ||
629 (*scale && alias->scale)) 671 (info->scale && alias->scale) ||
672 (info->snapshot && alias->snapshot))
630 return -EINVAL; 673 return -EINVAL;
631 674
632 if (alias->unit) 675 if (alias->unit)
633 *unit = alias->unit; 676 info->unit = alias->unit;
634 677
635 if (alias->scale) 678 if (alias->scale)
636 *scale = alias->scale; 679 info->scale = alias->scale;
680
681 if (alias->snapshot)
682 info->snapshot = alias->snapshot;
637 683
638 return 0; 684 return 0;
639} 685}
@@ -649,12 +695,15 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
649 struct perf_pmu_alias *alias; 695 struct perf_pmu_alias *alias;
650 int ret; 696 int ret;
651 697
698 info->per_pkg = false;
699
652 /* 700 /*
653 * Mark unit and scale as not set 701 * Mark unit and scale as not set
654 * (different from default values, see below) 702 * (different from default values, see below)
655 */ 703 */
656 info->unit = NULL; 704 info->unit = NULL;
657 info->scale = 0.0; 705 info->scale = 0.0;
706 info->snapshot = false;
658 707
659 list_for_each_entry_safe(term, h, head_terms, list) { 708 list_for_each_entry_safe(term, h, head_terms, list) {
660 alias = pmu_find_alias(pmu, term); 709 alias = pmu_find_alias(pmu, term);
@@ -664,10 +713,13 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
664 if (ret) 713 if (ret)
665 return ret; 714 return ret;
666 715
667 ret = check_unit_scale(alias, &info->unit, &info->scale); 716 ret = check_info_data(alias, info);
668 if (ret) 717 if (ret)
669 return ret; 718 return ret;
670 719
720 if (alias->per_pkg)
721 info->per_pkg = true;
722
671 list_del(&term->list); 723 list_del(&term->list);
672 free(term); 724 free(term);
673 } 725 }
@@ -747,15 +799,18 @@ void print_pmu_events(const char *event_glob, bool name_only)
747 799
748 pmu = NULL; 800 pmu = NULL;
749 len = 0; 801 len = 0;
750 while ((pmu = perf_pmu__scan(pmu)) != NULL) 802 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
751 list_for_each_entry(alias, &pmu->aliases, list) 803 list_for_each_entry(alias, &pmu->aliases, list)
752 len++; 804 len++;
753 aliases = malloc(sizeof(char *) * len); 805 if (pmu->selectable)
806 len++;
807 }
808 aliases = zalloc(sizeof(char *) * len);
754 if (!aliases) 809 if (!aliases)
755 return; 810 goto out_enomem;
756 pmu = NULL; 811 pmu = NULL;
757 j = 0; 812 j = 0;
758 while ((pmu = perf_pmu__scan(pmu)) != NULL) 813 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
759 list_for_each_entry(alias, &pmu->aliases, list) { 814 list_for_each_entry(alias, &pmu->aliases, list) {
760 char *name = format_alias(buf, sizeof(buf), pmu, alias); 815 char *name = format_alias(buf, sizeof(buf), pmu, alias);
761 bool is_cpu = !strcmp(pmu->name, "cpu"); 816 bool is_cpu = !strcmp(pmu->name, "cpu");
@@ -765,13 +820,23 @@ void print_pmu_events(const char *event_glob, bool name_only)
765 (!is_cpu && strglobmatch(alias->name, 820 (!is_cpu && strglobmatch(alias->name,
766 event_glob)))) 821 event_glob))))
767 continue; 822 continue;
768 aliases[j] = name; 823
769 if (is_cpu && !name_only) 824 if (is_cpu && !name_only)
770 aliases[j] = format_alias_or(buf, sizeof(buf), 825 name = format_alias_or(buf, sizeof(buf), pmu, alias);
771 pmu, alias); 826
772 aliases[j] = strdup(aliases[j]); 827 aliases[j] = strdup(name);
828 if (aliases[j] == NULL)
829 goto out_enomem;
773 j++; 830 j++;
774 } 831 }
832 if (pmu->selectable) {
833 char *s;
834 if (asprintf(&s, "%s//", pmu->name) < 0)
835 goto out_enomem;
836 aliases[j] = s;
837 j++;
838 }
839 }
775 len = j; 840 len = j;
776 qsort(aliases, len, sizeof(char *), cmp_string); 841 qsort(aliases, len, sizeof(char *), cmp_string);
777 for (j = 0; j < len; j++) { 842 for (j = 0; j < len; j++) {
@@ -780,12 +845,20 @@ void print_pmu_events(const char *event_glob, bool name_only)
780 continue; 845 continue;
781 } 846 }
782 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 847 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
783 zfree(&aliases[j]);
784 printed++; 848 printed++;
785 } 849 }
786 if (printed) 850 if (printed)
787 printf("\n"); 851 printf("\n");
788 free(aliases); 852out_free:
853 for (j = 0; j < len; j++)
854 zfree(&aliases[j]);
855 zfree(&aliases);
856 return;
857
858out_enomem:
859 printf("FATAL: not enough memory to print PMU events\n");
860 if (aliases)
861 goto out_free;
789} 862}
790 863
791bool pmu_have_event(const char *pname, const char *name) 864bool pmu_have_event(const char *pname, const char *name)
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index fe9dfbee8eed..6b1249fbdb5f 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -18,6 +18,7 @@ struct perf_event_attr;
18struct perf_pmu { 18struct perf_pmu {
19 char *name; 19 char *name;
20 __u32 type; 20 __u32 type;
21 bool selectable;
21 struct perf_event_attr *default_config; 22 struct perf_event_attr *default_config;
22 struct cpu_map *cpus; 23 struct cpu_map *cpus;
23 struct list_head format; /* HEAD struct perf_pmu_format -> list */ 24 struct list_head format; /* HEAD struct perf_pmu_format -> list */
@@ -28,6 +29,8 @@ struct perf_pmu {
28struct perf_pmu_info { 29struct perf_pmu_info {
29 const char *unit; 30 const char *unit;
30 double scale; 31 double scale;
32 bool per_pkg;
33 bool snapshot;
31}; 34};
32 35
33#define UNIT_MAX_LEN 31 /* max length for event unit name */ 36#define UNIT_MAX_LEN 31 /* max length for event unit name */
@@ -38,6 +41,8 @@ struct perf_pmu_alias {
38 struct list_head list; /* ELEM */ 41 struct list_head list; /* ELEM */
39 char unit[UNIT_MAX_LEN+1]; 42 char unit[UNIT_MAX_LEN+1];
40 double scale; 43 double scale;
44 bool per_pkg;
45 bool snapshot;
41}; 46};
42 47
43struct perf_pmu *perf_pmu__find(const char *name); 48struct perf_pmu *perf_pmu__find(const char *name);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index c150ca4343eb..28eb1417cb2a 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1910,21 +1910,21 @@ static int show_perf_probe_event(struct perf_probe_event *pev,
1910 if (ret < 0) 1910 if (ret < 0)
1911 return ret; 1911 return ret;
1912 1912
1913 printf(" %-20s (on %s", buf, place); 1913 pr_info(" %-20s (on %s", buf, place);
1914 if (module) 1914 if (module)
1915 printf(" in %s", module); 1915 pr_info(" in %s", module);
1916 1916
1917 if (pev->nargs > 0) { 1917 if (pev->nargs > 0) {
1918 printf(" with"); 1918 pr_info(" with");
1919 for (i = 0; i < pev->nargs; i++) { 1919 for (i = 0; i < pev->nargs; i++) {
1920 ret = synthesize_perf_probe_arg(&pev->args[i], 1920 ret = synthesize_perf_probe_arg(&pev->args[i],
1921 buf, 128); 1921 buf, 128);
1922 if (ret < 0) 1922 if (ret < 0)
1923 break; 1923 break;
1924 printf(" %s", buf); 1924 pr_info(" %s", buf);
1925 } 1925 }
1926 } 1926 }
1927 printf(")\n"); 1927 pr_info(")\n");
1928 free(place); 1928 free(place);
1929 return ret; 1929 return ret;
1930} 1930}
@@ -2124,7 +2124,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2124 } 2124 }
2125 2125
2126 ret = 0; 2126 ret = 0;
2127 printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2127 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2128 for (i = 0; i < ntevs; i++) { 2128 for (i = 0; i < ntevs; i++) {
2129 tev = &tevs[i]; 2129 tev = &tevs[i];
2130 if (pev->event) 2130 if (pev->event)
@@ -2179,8 +2179,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2179 2179
2180 if (ret >= 0) { 2180 if (ret >= 0) {
2181 /* Show how to use the event. */ 2181 /* Show how to use the event. */
2182 printf("\nYou can now use it in all perf tools, such as:\n\n"); 2182 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2183 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2183 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
2184 tev->event); 2184 tev->event);
2185 } 2185 }
2186 2186
@@ -2444,7 +2444,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
2444 goto error; 2444 goto error;
2445 } 2445 }
2446 2446
2447 printf("Removed event: %s\n", ent->s); 2447 pr_info("Removed event: %s\n", ent->s);
2448 return 0; 2448 return 0;
2449error: 2449error:
2450 pr_warning("Failed to delete event: %s\n", 2450 pr_warning("Failed to delete event: %s\n",
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index cf69325b985f..8acd0df88b5c 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -137,16 +137,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
137 137
138static int get_max_rate(unsigned int *rate) 138static int get_max_rate(unsigned int *rate)
139{ 139{
140 char path[PATH_MAX]; 140 return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate);
141 const char *procfs = procfs__mountpoint();
142
143 if (!procfs)
144 return -1;
145
146 snprintf(path, PATH_MAX,
147 "%s/sys/kernel/perf_event_max_sample_rate", procfs);
148
149 return filename__read_int(path, (int *) rate);
150} 141}
151 142
152static int record_opts__config_freq(struct record_opts *opts) 143static int record_opts__config_freq(struct record_opts *opts)
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 0a01bac4ce02..22ebc46226e7 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -24,6 +24,7 @@
24#include <string.h> 24#include <string.h>
25#include <ctype.h> 25#include <ctype.h>
26#include <errno.h> 26#include <errno.h>
27#include <linux/bitmap.h>
27 28
28#include "../util.h" 29#include "../util.h"
29#include <EXTERN.h> 30#include <EXTERN.h>
@@ -57,7 +58,7 @@ INTERP my_perl;
57#define FTRACE_MAX_EVENT \ 58#define FTRACE_MAX_EVENT \
58 ((1 << (sizeof(unsigned short) * 8)) - 1) 59 ((1 << (sizeof(unsigned short) * 8)) - 1)
59 60
60struct event_format *events[FTRACE_MAX_EVENT]; 61static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
61 62
62extern struct scripting_context *scripting_context; 63extern struct scripting_context *scripting_context;
63 64
@@ -238,35 +239,15 @@ static void define_event_symbols(struct event_format *event,
238 define_event_symbols(event, ev_name, args->next); 239 define_event_symbols(event, ev_name, args->next);
239} 240}
240 241
241static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
242{
243 static char ev_name[256];
244 struct event_format *event;
245 int type = evsel->attr.config;
246
247 if (events[type])
248 return events[type];
249
250 events[type] = event = evsel->tp_format;
251 if (!event)
252 return NULL;
253
254 sprintf(ev_name, "%s::%s", event->system, event->name);
255
256 define_event_symbols(event, ev_name, event->print_fmt.args);
257
258 return event;
259}
260
261static void perl_process_tracepoint(struct perf_sample *sample, 242static void perl_process_tracepoint(struct perf_sample *sample,
262 struct perf_evsel *evsel, 243 struct perf_evsel *evsel,
263 struct thread *thread) 244 struct thread *thread)
264{ 245{
246 struct event_format *event = evsel->tp_format;
265 struct format_field *field; 247 struct format_field *field;
266 static char handler[256]; 248 static char handler[256];
267 unsigned long long val; 249 unsigned long long val;
268 unsigned long s, ns; 250 unsigned long s, ns;
269 struct event_format *event;
270 int pid; 251 int pid;
271 int cpu = sample->cpu; 252 int cpu = sample->cpu;
272 void *data = sample->raw_data; 253 void *data = sample->raw_data;
@@ -278,7 +259,6 @@ static void perl_process_tracepoint(struct perf_sample *sample,
278 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 259 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
279 return; 260 return;
280 261
281 event = find_cache_event(evsel);
282 if (!event) 262 if (!event)
283 die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); 263 die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
284 264
@@ -286,6 +266,9 @@ static void perl_process_tracepoint(struct perf_sample *sample,
286 266
287 sprintf(handler, "%s::%s", event->system, event->name); 267 sprintf(handler, "%s::%s", event->system, event->name);
288 268
269 if (!test_and_set_bit(event->id, events_defined))
270 define_event_symbols(event, handler, event->print_fmt.args);
271
289 s = nsecs / NSECS_PER_SEC; 272 s = nsecs / NSECS_PER_SEC;
290 ns = nsecs - s * NSECS_PER_SEC; 273 ns = nsecs - s * NSECS_PER_SEC;
291 274
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 496f21cadd97..d808a328f4dc 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -24,7 +24,9 @@
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <string.h> 26#include <string.h>
27#include <stdbool.h>
27#include <errno.h> 28#include <errno.h>
29#include <linux/bitmap.h>
28 30
29#include "../../perf.h" 31#include "../../perf.h"
30#include "../debug.h" 32#include "../debug.h"
@@ -33,6 +35,10 @@
33#include "../util.h" 35#include "../util.h"
34#include "../event.h" 36#include "../event.h"
35#include "../thread.h" 37#include "../thread.h"
38#include "../comm.h"
39#include "../machine.h"
40#include "../db-export.h"
41#include "../thread-stack.h"
36#include "../trace-event.h" 42#include "../trace-event.h"
37#include "../machine.h" 43#include "../machine.h"
38 44
@@ -41,7 +47,7 @@ PyMODINIT_FUNC initperf_trace_context(void);
41#define FTRACE_MAX_EVENT \ 47#define FTRACE_MAX_EVENT \
42 ((1 << (sizeof(unsigned short) * 8)) - 1) 48 ((1 << (sizeof(unsigned short) * 8)) - 1)
43 49
44struct event_format *events[FTRACE_MAX_EVENT]; 50static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
45 51
46#define MAX_FIELDS 64 52#define MAX_FIELDS 64
47#define N_COMMON_FIELDS 7 53#define N_COMMON_FIELDS 7
@@ -53,6 +59,24 @@ static int zero_flag_atom;
53 59
54static PyObject *main_module, *main_dict; 60static PyObject *main_module, *main_dict;
55 61
62struct tables {
63 struct db_export dbe;
64 PyObject *evsel_handler;
65 PyObject *machine_handler;
66 PyObject *thread_handler;
67 PyObject *comm_handler;
68 PyObject *comm_thread_handler;
69 PyObject *dso_handler;
70 PyObject *symbol_handler;
71 PyObject *branch_type_handler;
72 PyObject *sample_handler;
73 PyObject *call_path_handler;
74 PyObject *call_return_handler;
75 bool db_export_mode;
76};
77
78static struct tables tables_global;
79
56static void handler_call_die(const char *handler_name) NORETURN; 80static void handler_call_die(const char *handler_name) NORETURN;
57static void handler_call_die(const char *handler_name) 81static void handler_call_die(const char *handler_name)
58{ 82{
@@ -232,31 +256,6 @@ static void define_event_symbols(struct event_format *event,
232 define_event_symbols(event, ev_name, args->next); 256 define_event_symbols(event, ev_name, args->next);
233} 257}
234 258
235static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
236{
237 static char ev_name[256];
238 struct event_format *event;
239 int type = evsel->attr.config;
240
241 /*
242 * XXX: Do we really need to cache this since now we have evsel->tp_format
243 * cached already? Need to re-read this "cache" routine that as well calls
244 * define_event_symbols() :-\
245 */
246 if (events[type])
247 return events[type];
248
249 events[type] = event = evsel->tp_format;
250 if (!event)
251 return NULL;
252
253 sprintf(ev_name, "%s__%s", event->system, event->name);
254
255 define_event_symbols(event, ev_name, event->print_fmt.args);
256
257 return event;
258}
259
260static PyObject *get_field_numeric_entry(struct event_format *event, 259static PyObject *get_field_numeric_entry(struct event_format *event,
261 struct format_field *field, void *data) 260 struct format_field *field, void *data)
262{ 261{
@@ -312,9 +311,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
312 if (!symbol_conf.use_callchain || !sample->callchain) 311 if (!symbol_conf.use_callchain || !sample->callchain)
313 goto exit; 312 goto exit;
314 313
315 if (machine__resolve_callchain(al->machine, evsel, al->thread, 314 if (thread__resolve_callchain(al->thread, evsel,
316 sample, NULL, NULL, 315 sample, NULL, NULL,
317 PERF_MAX_STACK_DEPTH) != 0) { 316 PERF_MAX_STACK_DEPTH) != 0) {
318 pr_err("Failed to resolve callchain. Skipping\n"); 317 pr_err("Failed to resolve callchain. Skipping\n");
319 goto exit; 318 goto exit;
320 } 319 }
@@ -380,12 +379,12 @@ static void python_process_tracepoint(struct perf_sample *sample,
380 struct thread *thread, 379 struct thread *thread,
381 struct addr_location *al) 380 struct addr_location *al)
382{ 381{
382 struct event_format *event = evsel->tp_format;
383 PyObject *handler, *context, *t, *obj, *callchain; 383 PyObject *handler, *context, *t, *obj, *callchain;
384 PyObject *dict = NULL; 384 PyObject *dict = NULL;
385 static char handler_name[256]; 385 static char handler_name[256];
386 struct format_field *field; 386 struct format_field *field;
387 unsigned long s, ns; 387 unsigned long s, ns;
388 struct event_format *event;
389 unsigned n = 0; 388 unsigned n = 0;
390 int pid; 389 int pid;
391 int cpu = sample->cpu; 390 int cpu = sample->cpu;
@@ -397,7 +396,6 @@ static void python_process_tracepoint(struct perf_sample *sample,
397 if (!t) 396 if (!t)
398 Py_FatalError("couldn't create Python tuple"); 397 Py_FatalError("couldn't create Python tuple");
399 398
400 event = find_cache_event(evsel);
401 if (!event) 399 if (!event)
402 die("ug! no event found for type %d", (int)evsel->attr.config); 400 die("ug! no event found for type %d", (int)evsel->attr.config);
403 401
@@ -405,6 +403,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
405 403
406 sprintf(handler_name, "%s__%s", event->system, event->name); 404 sprintf(handler_name, "%s__%s", event->system, event->name);
407 405
406 if (!test_and_set_bit(event->id, events_defined))
407 define_event_symbols(event, handler_name, event->print_fmt.args);
408
408 handler = get_handler(handler_name); 409 handler = get_handler(handler_name);
409 if (!handler) { 410 if (!handler) {
410 dict = PyDict_New(); 411 dict = PyDict_New();
@@ -475,6 +476,289 @@ static void python_process_tracepoint(struct perf_sample *sample,
475 Py_DECREF(t); 476 Py_DECREF(t);
476} 477}
477 478
479static PyObject *tuple_new(unsigned int sz)
480{
481 PyObject *t;
482
483 t = PyTuple_New(sz);
484 if (!t)
485 Py_FatalError("couldn't create Python tuple");
486 return t;
487}
488
489static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
490{
491#if BITS_PER_LONG == 64
492 return PyTuple_SetItem(t, pos, PyInt_FromLong(val));
493#endif
494#if BITS_PER_LONG == 32
495 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val));
496#endif
497}
498
499static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
500{
501 return PyTuple_SetItem(t, pos, PyInt_FromLong(val));
502}
503
504static int tuple_set_string(PyObject *t, unsigned int pos, const char *s)
505{
506 return PyTuple_SetItem(t, pos, PyString_FromString(s));
507}
508
509static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel)
510{
511 struct tables *tables = container_of(dbe, struct tables, dbe);
512 PyObject *t;
513
514 t = tuple_new(2);
515
516 tuple_set_u64(t, 0, evsel->db_id);
517 tuple_set_string(t, 1, perf_evsel__name(evsel));
518
519 call_object(tables->evsel_handler, t, "evsel_table");
520
521 Py_DECREF(t);
522
523 return 0;
524}
525
526static int python_export_machine(struct db_export *dbe,
527 struct machine *machine)
528{
529 struct tables *tables = container_of(dbe, struct tables, dbe);
530 PyObject *t;
531
532 t = tuple_new(3);
533
534 tuple_set_u64(t, 0, machine->db_id);
535 tuple_set_s32(t, 1, machine->pid);
536 tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : "");
537
538 call_object(tables->machine_handler, t, "machine_table");
539
540 Py_DECREF(t);
541
542 return 0;
543}
544
545static int python_export_thread(struct db_export *dbe, struct thread *thread,
546 u64 main_thread_db_id, struct machine *machine)
547{
548 struct tables *tables = container_of(dbe, struct tables, dbe);
549 PyObject *t;
550
551 t = tuple_new(5);
552
553 tuple_set_u64(t, 0, thread->db_id);
554 tuple_set_u64(t, 1, machine->db_id);
555 tuple_set_u64(t, 2, main_thread_db_id);
556 tuple_set_s32(t, 3, thread->pid_);
557 tuple_set_s32(t, 4, thread->tid);
558
559 call_object(tables->thread_handler, t, "thread_table");
560
561 Py_DECREF(t);
562
563 return 0;
564}
565
566static int python_export_comm(struct db_export *dbe, struct comm *comm)
567{
568 struct tables *tables = container_of(dbe, struct tables, dbe);
569 PyObject *t;
570
571 t = tuple_new(2);
572
573 tuple_set_u64(t, 0, comm->db_id);
574 tuple_set_string(t, 1, comm__str(comm));
575
576 call_object(tables->comm_handler, t, "comm_table");
577
578 Py_DECREF(t);
579
580 return 0;
581}
582
583static int python_export_comm_thread(struct db_export *dbe, u64 db_id,
584 struct comm *comm, struct thread *thread)
585{
586 struct tables *tables = container_of(dbe, struct tables, dbe);
587 PyObject *t;
588
589 t = tuple_new(3);
590
591 tuple_set_u64(t, 0, db_id);
592 tuple_set_u64(t, 1, comm->db_id);
593 tuple_set_u64(t, 2, thread->db_id);
594
595 call_object(tables->comm_thread_handler, t, "comm_thread_table");
596
597 Py_DECREF(t);
598
599 return 0;
600}
601
602static int python_export_dso(struct db_export *dbe, struct dso *dso,
603 struct machine *machine)
604{
605 struct tables *tables = container_of(dbe, struct tables, dbe);
606 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
607 PyObject *t;
608
609 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
610
611 t = tuple_new(5);
612
613 tuple_set_u64(t, 0, dso->db_id);
614 tuple_set_u64(t, 1, machine->db_id);
615 tuple_set_string(t, 2, dso->short_name);
616 tuple_set_string(t, 3, dso->long_name);
617 tuple_set_string(t, 4, sbuild_id);
618
619 call_object(tables->dso_handler, t, "dso_table");
620
621 Py_DECREF(t);
622
623 return 0;
624}
625
626static int python_export_symbol(struct db_export *dbe, struct symbol *sym,
627 struct dso *dso)
628{
629 struct tables *tables = container_of(dbe, struct tables, dbe);
630 u64 *sym_db_id = symbol__priv(sym);
631 PyObject *t;
632
633 t = tuple_new(6);
634
635 tuple_set_u64(t, 0, *sym_db_id);
636 tuple_set_u64(t, 1, dso->db_id);
637 tuple_set_u64(t, 2, sym->start);
638 tuple_set_u64(t, 3, sym->end);
639 tuple_set_s32(t, 4, sym->binding);
640 tuple_set_string(t, 5, sym->name);
641
642 call_object(tables->symbol_handler, t, "symbol_table");
643
644 Py_DECREF(t);
645
646 return 0;
647}
648
649static int python_export_branch_type(struct db_export *dbe, u32 branch_type,
650 const char *name)
651{
652 struct tables *tables = container_of(dbe, struct tables, dbe);
653 PyObject *t;
654
655 t = tuple_new(2);
656
657 tuple_set_s32(t, 0, branch_type);
658 tuple_set_string(t, 1, name);
659
660 call_object(tables->branch_type_handler, t, "branch_type_table");
661
662 Py_DECREF(t);
663
664 return 0;
665}
666
667static int python_export_sample(struct db_export *dbe,
668 struct export_sample *es)
669{
670 struct tables *tables = container_of(dbe, struct tables, dbe);
671 PyObject *t;
672
673 t = tuple_new(21);
674
675 tuple_set_u64(t, 0, es->db_id);
676 tuple_set_u64(t, 1, es->evsel->db_id);
677 tuple_set_u64(t, 2, es->al->machine->db_id);
678 tuple_set_u64(t, 3, es->thread->db_id);
679 tuple_set_u64(t, 4, es->comm_db_id);
680 tuple_set_u64(t, 5, es->dso_db_id);
681 tuple_set_u64(t, 6, es->sym_db_id);
682 tuple_set_u64(t, 7, es->offset);
683 tuple_set_u64(t, 8, es->sample->ip);
684 tuple_set_u64(t, 9, es->sample->time);
685 tuple_set_s32(t, 10, es->sample->cpu);
686 tuple_set_u64(t, 11, es->addr_dso_db_id);
687 tuple_set_u64(t, 12, es->addr_sym_db_id);
688 tuple_set_u64(t, 13, es->addr_offset);
689 tuple_set_u64(t, 14, es->sample->addr);
690 tuple_set_u64(t, 15, es->sample->period);
691 tuple_set_u64(t, 16, es->sample->weight);
692 tuple_set_u64(t, 17, es->sample->transaction);
693 tuple_set_u64(t, 18, es->sample->data_src);
694 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
695 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
696
697 call_object(tables->sample_handler, t, "sample_table");
698
699 Py_DECREF(t);
700
701 return 0;
702}
703
704static int python_export_call_path(struct db_export *dbe, struct call_path *cp)
705{
706 struct tables *tables = container_of(dbe, struct tables, dbe);
707 PyObject *t;
708 u64 parent_db_id, sym_db_id;
709
710 parent_db_id = cp->parent ? cp->parent->db_id : 0;
711 sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0;
712
713 t = tuple_new(4);
714
715 tuple_set_u64(t, 0, cp->db_id);
716 tuple_set_u64(t, 1, parent_db_id);
717 tuple_set_u64(t, 2, sym_db_id);
718 tuple_set_u64(t, 3, cp->ip);
719
720 call_object(tables->call_path_handler, t, "call_path_table");
721
722 Py_DECREF(t);
723
724 return 0;
725}
726
727static int python_export_call_return(struct db_export *dbe,
728 struct call_return *cr)
729{
730 struct tables *tables = container_of(dbe, struct tables, dbe);
731 u64 comm_db_id = cr->comm ? cr->comm->db_id : 0;
732 PyObject *t;
733
734 t = tuple_new(11);
735
736 tuple_set_u64(t, 0, cr->db_id);
737 tuple_set_u64(t, 1, cr->thread->db_id);
738 tuple_set_u64(t, 2, comm_db_id);
739 tuple_set_u64(t, 3, cr->cp->db_id);
740 tuple_set_u64(t, 4, cr->call_time);
741 tuple_set_u64(t, 5, cr->return_time);
742 tuple_set_u64(t, 6, cr->branch_count);
743 tuple_set_u64(t, 7, cr->call_ref);
744 tuple_set_u64(t, 8, cr->return_ref);
745 tuple_set_u64(t, 9, cr->cp->parent->db_id);
746 tuple_set_s32(t, 10, cr->flags);
747
748 call_object(tables->call_return_handler, t, "call_return_table");
749
750 Py_DECREF(t);
751
752 return 0;
753}
754
755static int python_process_call_return(struct call_return *cr, void *data)
756{
757 struct db_export *dbe = data;
758
759 return db_export__call_return(dbe, cr);
760}
761
478static void python_process_general_event(struct perf_sample *sample, 762static void python_process_general_event(struct perf_sample *sample,
479 struct perf_evsel *evsel, 763 struct perf_evsel *evsel,
480 struct thread *thread, 764 struct thread *thread,
@@ -551,19 +835,25 @@ exit:
551 Py_DECREF(t); 835 Py_DECREF(t);
552} 836}
553 837
554static void python_process_event(union perf_event *event __maybe_unused, 838static void python_process_event(union perf_event *event,
555 struct perf_sample *sample, 839 struct perf_sample *sample,
556 struct perf_evsel *evsel, 840 struct perf_evsel *evsel,
557 struct thread *thread, 841 struct thread *thread,
558 struct addr_location *al) 842 struct addr_location *al)
559{ 843{
844 struct tables *tables = &tables_global;
845
560 switch (evsel->attr.type) { 846 switch (evsel->attr.type) {
561 case PERF_TYPE_TRACEPOINT: 847 case PERF_TYPE_TRACEPOINT:
562 python_process_tracepoint(sample, evsel, thread, al); 848 python_process_tracepoint(sample, evsel, thread, al);
563 break; 849 break;
564 /* Reserve for future process_hw/sw/raw APIs */ 850 /* Reserve for future process_hw/sw/raw APIs */
565 default: 851 default:
566 python_process_general_event(sample, evsel, thread, al); 852 if (tables->db_export_mode)
853 db_export__sample(&tables->dbe, event, sample, evsel,
854 thread, al);
855 else
856 python_process_general_event(sample, evsel, thread, al);
567 } 857 }
568} 858}
569 859
@@ -589,11 +879,79 @@ error:
589 return -1; 879 return -1;
590} 880}
591 881
882#define SET_TABLE_HANDLER_(name, handler_name, table_name) do { \
883 tables->handler_name = get_handler(#table_name); \
884 if (tables->handler_name) \
885 tables->dbe.export_ ## name = python_export_ ## name; \
886} while (0)
887
888#define SET_TABLE_HANDLER(name) \
889 SET_TABLE_HANDLER_(name, name ## _handler, name ## _table)
890
891static void set_table_handlers(struct tables *tables)
892{
893 const char *perf_db_export_mode = "perf_db_export_mode";
894 const char *perf_db_export_calls = "perf_db_export_calls";
895 PyObject *db_export_mode, *db_export_calls;
896 bool export_calls = false;
897 int ret;
898
899 memset(tables, 0, sizeof(struct tables));
900 if (db_export__init(&tables->dbe))
901 Py_FatalError("failed to initialize export");
902
903 db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode);
904 if (!db_export_mode)
905 return;
906
907 ret = PyObject_IsTrue(db_export_mode);
908 if (ret == -1)
909 handler_call_die(perf_db_export_mode);
910 if (!ret)
911 return;
912
913 tables->dbe.crp = NULL;
914 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
915 if (db_export_calls) {
916 ret = PyObject_IsTrue(db_export_calls);
917 if (ret == -1)
918 handler_call_die(perf_db_export_calls);
919 export_calls = !!ret;
920 }
921
922 if (export_calls) {
923 tables->dbe.crp =
924 call_return_processor__new(python_process_call_return,
925 &tables->dbe);
926 if (!tables->dbe.crp)
927 Py_FatalError("failed to create calls processor");
928 }
929
930 tables->db_export_mode = true;
931 /*
932 * Reserve per symbol space for symbol->db_id via symbol__priv()
933 */
934 symbol_conf.priv_size = sizeof(u64);
935
936 SET_TABLE_HANDLER(evsel);
937 SET_TABLE_HANDLER(machine);
938 SET_TABLE_HANDLER(thread);
939 SET_TABLE_HANDLER(comm);
940 SET_TABLE_HANDLER(comm_thread);
941 SET_TABLE_HANDLER(dso);
942 SET_TABLE_HANDLER(symbol);
943 SET_TABLE_HANDLER(branch_type);
944 SET_TABLE_HANDLER(sample);
945 SET_TABLE_HANDLER(call_path);
946 SET_TABLE_HANDLER(call_return);
947}
948
592/* 949/*
593 * Start trace script 950 * Start trace script
594 */ 951 */
595static int python_start_script(const char *script, int argc, const char **argv) 952static int python_start_script(const char *script, int argc, const char **argv)
596{ 953{
954 struct tables *tables = &tables_global;
597 const char **command_line; 955 const char **command_line;
598 char buf[PATH_MAX]; 956 char buf[PATH_MAX];
599 int i, err = 0; 957 int i, err = 0;
@@ -632,6 +990,14 @@ static int python_start_script(const char *script, int argc, const char **argv)
632 990
633 free(command_line); 991 free(command_line);
634 992
993 set_table_handlers(tables);
994
995 if (tables->db_export_mode) {
996 err = db_export__branch_types(&tables->dbe);
997 if (err)
998 goto error;
999 }
1000
635 return err; 1001 return err;
636error: 1002error:
637 Py_Finalize(); 1003 Py_Finalize();
@@ -642,7 +1008,9 @@ error:
642 1008
643static int python_flush_script(void) 1009static int python_flush_script(void)
644{ 1010{
645 return 0; 1011 struct tables *tables = &tables_global;
1012
1013 return db_export__flush(&tables->dbe);
646} 1014}
647 1015
648/* 1016/*
@@ -650,8 +1018,12 @@ static int python_flush_script(void)
650 */ 1018 */
651static int python_stop_script(void) 1019static int python_stop_script(void)
652{ 1020{
1021 struct tables *tables = &tables_global;
1022
653 try_call_object("trace_end", NULL); 1023 try_call_object("trace_end", NULL);
654 1024
1025 db_export__exit(&tables->dbe);
1026
655 Py_XDECREF(main_dict); 1027 Py_XDECREF(main_dict);
656 Py_XDECREF(main_module); 1028 Py_XDECREF(main_module);
657 Py_Finalize(); 1029 Py_Finalize();
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 6702ac28754b..5f0e05a76c05 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -228,6 +228,15 @@ static int process_finished_round(struct perf_tool *tool,
228 union perf_event *event, 228 union perf_event *event,
229 struct perf_session *session); 229 struct perf_session *session);
230 230
231static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
232 union perf_event *event __maybe_unused,
233 struct perf_session *perf_session
234 __maybe_unused)
235{
236 dump_printf(": unhandled!\n");
237 return 0;
238}
239
231void perf_tool__fill_defaults(struct perf_tool *tool) 240void perf_tool__fill_defaults(struct perf_tool *tool)
232{ 241{
233 if (tool->sample == NULL) 242 if (tool->sample == NULL)
@@ -262,6 +271,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
262 else 271 else
263 tool->finished_round = process_finished_round_stub; 272 tool->finished_round = process_finished_round_stub;
264 } 273 }
274 if (tool->id_index == NULL)
275 tool->id_index = process_id_index_stub;
265} 276}
266 277
267static void swap_sample_id_all(union perf_event *event, void *data) 278static void swap_sample_id_all(union perf_event *event, void *data)
@@ -460,6 +471,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
460 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 471 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
461 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, 472 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
462 [PERF_RECORD_HEADER_BUILD_ID] = NULL, 473 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
474 [PERF_RECORD_ID_INDEX] = perf_event__all64_swap,
463 [PERF_RECORD_HEADER_MAX] = NULL, 475 [PERF_RECORD_HEADER_MAX] = NULL,
464}; 476};
465 477
@@ -521,15 +533,11 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
521 return -ETIME; 533 return -ETIME;
522 534
523 if (timestamp < oe->last_flush) { 535 if (timestamp < oe->last_flush) {
524 WARN_ONCE(1, "Timestamp below last timeslice flush\n"); 536 pr_oe_time(timestamp, "out of order event\n");
525
526 pr_oe_time(timestamp, "out of order event");
527 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n", 537 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
528 oe->last_flush_type); 538 oe->last_flush_type);
529 539
530 /* We could get out of order messages after forced flush. */ 540 s->stats.nr_unordered_events++;
531 if (oe->last_flush_type != OE_FLUSH__HALF)
532 return -EINVAL;
533 } 541 }
534 542
535 new = ordered_events__new(oe, timestamp, event); 543 new = ordered_events__new(oe, timestamp, event);
@@ -580,15 +588,46 @@ static void regs_dump__printf(u64 mask, u64 *regs)
580 } 588 }
581} 589}
582 590
591static const char *regs_abi[] = {
592 [PERF_SAMPLE_REGS_ABI_NONE] = "none",
593 [PERF_SAMPLE_REGS_ABI_32] = "32-bit",
594 [PERF_SAMPLE_REGS_ABI_64] = "64-bit",
595};
596
597static inline const char *regs_dump_abi(struct regs_dump *d)
598{
599 if (d->abi > PERF_SAMPLE_REGS_ABI_64)
600 return "unknown";
601
602 return regs_abi[d->abi];
603}
604
605static void regs__printf(const char *type, struct regs_dump *regs)
606{
607 u64 mask = regs->mask;
608
609 printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n",
610 type,
611 mask,
612 regs_dump_abi(regs));
613
614 regs_dump__printf(mask, regs->regs);
615}
616
583static void regs_user__printf(struct perf_sample *sample) 617static void regs_user__printf(struct perf_sample *sample)
584{ 618{
585 struct regs_dump *user_regs = &sample->user_regs; 619 struct regs_dump *user_regs = &sample->user_regs;
586 620
587 if (user_regs->regs) { 621 if (user_regs->regs)
588 u64 mask = user_regs->mask; 622 regs__printf("user", user_regs);
589 printf("... user regs: mask 0x%" PRIx64 "\n", mask); 623}
590 regs_dump__printf(mask, user_regs->regs); 624
591 } 625static void regs_intr__printf(struct perf_sample *sample)
626{
627 struct regs_dump *intr_regs = &sample->intr_regs;
628
629 if (intr_regs->regs)
630 regs__printf("intr", intr_regs);
592} 631}
593 632
594static void stack_user__printf(struct stack_dump *dump) 633static void stack_user__printf(struct stack_dump *dump)
@@ -687,6 +726,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
687 if (sample_type & PERF_SAMPLE_REGS_USER) 726 if (sample_type & PERF_SAMPLE_REGS_USER)
688 regs_user__printf(sample); 727 regs_user__printf(sample);
689 728
729 if (sample_type & PERF_SAMPLE_REGS_INTR)
730 regs_intr__printf(sample);
731
690 if (sample_type & PERF_SAMPLE_STACK_USER) 732 if (sample_type & PERF_SAMPLE_STACK_USER)
691 stack_user__printf(&sample->user_stack); 733 stack_user__printf(&sample->user_stack);
692 734
@@ -888,11 +930,26 @@ static s64 perf_session__process_user_event(struct perf_session *session,
888 return tool->build_id(tool, event, session); 930 return tool->build_id(tool, event, session);
889 case PERF_RECORD_FINISHED_ROUND: 931 case PERF_RECORD_FINISHED_ROUND:
890 return tool->finished_round(tool, event, session); 932 return tool->finished_round(tool, event, session);
933 case PERF_RECORD_ID_INDEX:
934 return tool->id_index(tool, event, session);
891 default: 935 default:
892 return -EINVAL; 936 return -EINVAL;
893 } 937 }
894} 938}
895 939
940int perf_session__deliver_synth_event(struct perf_session *session,
941 union perf_event *event,
942 struct perf_sample *sample,
943 struct perf_tool *tool)
944{
945 events_stats__inc(&session->stats, event->header.type);
946
947 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
948 return perf_session__process_user_event(session, event, tool, 0);
949
950 return perf_session__deliver_event(session, event, sample, tool, 0);
951}
952
896static void event_swap(union perf_event *event, bool sample_id_all) 953static void event_swap(union perf_event *event, bool sample_id_all)
897{ 954{
898 perf_event__swap_op swap; 955 perf_event__swap_op swap;
@@ -1057,6 +1114,9 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
1057 "Do you have a KVM guest running and not using 'perf kvm'?\n", 1114 "Do you have a KVM guest running and not using 'perf kvm'?\n",
1058 session->stats.nr_unprocessable_samples); 1115 session->stats.nr_unprocessable_samples);
1059 } 1116 }
1117
1118 if (session->stats.nr_unordered_events != 0)
1119 ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events);
1060} 1120}
1061 1121
1062volatile int session_done; 1122volatile int session_done;
@@ -1417,9 +1477,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1417 if (symbol_conf.use_callchain && sample->callchain) { 1477 if (symbol_conf.use_callchain && sample->callchain) {
1418 struct addr_location node_al; 1478 struct addr_location node_al;
1419 1479
1420 if (machine__resolve_callchain(al->machine, evsel, al->thread, 1480 if (thread__resolve_callchain(al->thread, evsel,
1421 sample, NULL, NULL, 1481 sample, NULL, NULL,
1422 PERF_MAX_STACK_DEPTH) != 0) { 1482 PERF_MAX_STACK_DEPTH) != 0) {
1423 if (verbose) 1483 if (verbose)
1424 error("Failed to resolve callchain. Skipping\n"); 1484 error("Failed to resolve callchain. Skipping\n");
1425 return; 1485 return;
@@ -1594,3 +1654,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1594out: 1654out:
1595 return err; 1655 return err;
1596} 1656}
1657
1658int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
1659 union perf_event *event,
1660 struct perf_session *session)
1661{
1662 struct perf_evlist *evlist = session->evlist;
1663 struct id_index_event *ie = &event->id_index;
1664 size_t i, nr, max_nr;
1665
1666 max_nr = (ie->header.size - sizeof(struct id_index_event)) /
1667 sizeof(struct id_index_entry);
1668 nr = ie->nr;
1669 if (nr > max_nr)
1670 return -EINVAL;
1671
1672 if (dump_trace)
1673 fprintf(stdout, " nr: %zu\n", nr);
1674
1675 for (i = 0; i < nr; i++) {
1676 struct id_index_entry *e = &ie->entries[i];
1677 struct perf_sample_id *sid;
1678
1679 if (dump_trace) {
1680 fprintf(stdout, " ... id: %"PRIu64, e->id);
1681 fprintf(stdout, " idx: %"PRIu64, e->idx);
1682 fprintf(stdout, " cpu: %"PRId64, e->cpu);
1683 fprintf(stdout, " tid: %"PRId64"\n", e->tid);
1684 }
1685
1686 sid = perf_evlist__id2sid(evlist, e->id);
1687 if (!sid)
1688 return -ENOENT;
1689 sid->idx = e->idx;
1690 sid->cpu = e->cpu;
1691 sid->tid = e->tid;
1692 }
1693 return 0;
1694}
1695
1696int perf_event__synthesize_id_index(struct perf_tool *tool,
1697 perf_event__handler_t process,
1698 struct perf_evlist *evlist,
1699 struct machine *machine)
1700{
1701 union perf_event *ev;
1702 struct perf_evsel *evsel;
1703 size_t nr = 0, i = 0, sz, max_nr, n;
1704 int err;
1705
1706 pr_debug2("Synthesizing id index\n");
1707
1708 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
1709 sizeof(struct id_index_entry);
1710
1711 evlist__for_each(evlist, evsel)
1712 nr += evsel->ids;
1713
1714 n = nr > max_nr ? max_nr : nr;
1715 sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
1716 ev = zalloc(sz);
1717 if (!ev)
1718 return -ENOMEM;
1719
1720 ev->id_index.header.type = PERF_RECORD_ID_INDEX;
1721 ev->id_index.header.size = sz;
1722 ev->id_index.nr = n;
1723
1724 evlist__for_each(evlist, evsel) {
1725 u32 j;
1726
1727 for (j = 0; j < evsel->ids; j++) {
1728 struct id_index_entry *e;
1729 struct perf_sample_id *sid;
1730
1731 if (i >= n) {
1732 err = process(tool, ev, NULL, machine);
1733 if (err)
1734 goto out_err;
1735 nr -= n;
1736 i = 0;
1737 }
1738
1739 e = &ev->id_index.entries[i++];
1740
1741 e->id = evsel->id[j];
1742
1743 sid = perf_evlist__id2sid(evlist, e->id);
1744 if (!sid) {
1745 free(ev);
1746 return -ENOENT;
1747 }
1748
1749 e->idx = sid->idx;
1750 e->cpu = sid->cpu;
1751 e->tid = sid->tid;
1752 }
1753 }
1754
1755 sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
1756 ev->id_index.header.size = sz;
1757 ev->id_index.nr = nr;
1758
1759 err = process(tool, ev, NULL, machine);
1760out_err:
1761 free(ev);
1762
1763 return err;
1764}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index a4be851f1a90..dc26ebf60fe4 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -126,4 +126,19 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
126extern volatile int session_done; 126extern volatile int session_done;
127 127
128#define session_done() ACCESS_ONCE(session_done) 128#define session_done() ACCESS_ONCE(session_done)
129
130int perf_session__deliver_synth_event(struct perf_session *session,
131 union perf_event *event,
132 struct perf_sample *sample,
133 struct perf_tool *tool);
134
135int perf_event__process_id_index(struct perf_tool *tool,
136 union perf_event *event,
137 struct perf_session *session);
138
139int perf_event__synthesize_id_index(struct perf_tool *tool,
140 perf_event__handler_t process,
141 struct perf_evlist *evlist,
142 struct machine *machine);
143
129#endif /* __PERF_SESSION_H */ 144#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 9402885a77f3..9139dda9f9a3 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -291,7 +291,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
291 else { 291 else {
292 struct map *map = left->ms.map; 292 struct map *map = left->ms.map;
293 left->srcline = get_srcline(map->dso, 293 left->srcline = get_srcline(map->dso,
294 map__rip_2objdump(map, left->ip)); 294 map__rip_2objdump(map, left->ip),
295 left->ms.sym, true);
295 } 296 }
296 } 297 }
297 if (!right->srcline) { 298 if (!right->srcline) {
@@ -300,7 +301,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
300 else { 301 else {
301 struct map *map = right->ms.map; 302 struct map *map = right->ms.map;
302 right->srcline = get_srcline(map->dso, 303 right->srcline = get_srcline(map->dso,
303 map__rip_2objdump(map, right->ip)); 304 map__rip_2objdump(map, right->ip),
305 right->ms.sym, true);
304 } 306 }
305 } 307 }
306 return strcmp(right->srcline, left->srcline); 308 return strcmp(right->srcline, left->srcline);
@@ -309,7 +311,7 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
309static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, 311static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
310 size_t size, unsigned int width) 312 size_t size, unsigned int width)
311{ 313{
312 return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline); 314 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
313} 315}
314 316
315struct sort_entry sort_srcline = { 317struct sort_entry sort_srcline = {
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index f3e4bc5fe5d2..c93fb0c5bd0b 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -8,6 +8,8 @@
8#include "util/util.h" 8#include "util/util.h"
9#include "util/debug.h" 9#include "util/debug.h"
10 10
11#include "symbol.h"
12
11#ifdef HAVE_LIBBFD_SUPPORT 13#ifdef HAVE_LIBBFD_SUPPORT
12 14
13/* 15/*
@@ -18,7 +20,7 @@
18 20
19struct a2l_data { 21struct a2l_data {
20 const char *input; 22 const char *input;
21 unsigned long addr; 23 u64 addr;
22 24
23 bool found; 25 bool found;
24 const char *filename; 26 const char *filename;
@@ -145,7 +147,7 @@ static void addr2line_cleanup(struct a2l_data *a2l)
145 free(a2l); 147 free(a2l);
146} 148}
147 149
148static int addr2line(const char *dso_name, unsigned long addr, 150static int addr2line(const char *dso_name, u64 addr,
149 char **file, unsigned int *line, struct dso *dso) 151 char **file, unsigned int *line, struct dso *dso)
150{ 152{
151 int ret = 0; 153 int ret = 0;
@@ -191,7 +193,7 @@ void dso__free_a2l(struct dso *dso)
191 193
192#else /* HAVE_LIBBFD_SUPPORT */ 194#else /* HAVE_LIBBFD_SUPPORT */
193 195
194static int addr2line(const char *dso_name, unsigned long addr, 196static int addr2line(const char *dso_name, u64 addr,
195 char **file, unsigned int *line_nr, 197 char **file, unsigned int *line_nr,
196 struct dso *dso __maybe_unused) 198 struct dso *dso __maybe_unused)
197{ 199{
@@ -250,7 +252,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
250 */ 252 */
251#define A2L_FAIL_LIMIT 123 253#define A2L_FAIL_LIMIT 123
252 254
253char *get_srcline(struct dso *dso, unsigned long addr) 255char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
256 bool show_sym)
254{ 257{
255 char *file = NULL; 258 char *file = NULL;
256 unsigned line = 0; 259 unsigned line = 0;
@@ -258,7 +261,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
258 const char *dso_name; 261 const char *dso_name;
259 262
260 if (!dso->has_srcline) 263 if (!dso->has_srcline)
261 return SRCLINE_UNKNOWN; 264 goto out;
262 265
263 if (dso->symsrc_filename) 266 if (dso->symsrc_filename)
264 dso_name = dso->symsrc_filename; 267 dso_name = dso->symsrc_filename;
@@ -274,7 +277,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
274 if (!addr2line(dso_name, addr, &file, &line, dso)) 277 if (!addr2line(dso_name, addr, &file, &line, dso))
275 goto out; 278 goto out;
276 279
277 if (asprintf(&srcline, "%s:%u", file, line) < 0) { 280 if (asprintf(&srcline, "%s:%u", basename(file), line) < 0) {
278 free(file); 281 free(file);
279 goto out; 282 goto out;
280 } 283 }
@@ -289,7 +292,13 @@ out:
289 dso->has_srcline = 0; 292 dso->has_srcline = 0;
290 dso__free_a2l(dso); 293 dso__free_a2l(dso);
291 } 294 }
292 return SRCLINE_UNKNOWN; 295 if (sym) {
296 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
297 addr - sym->start) < 0)
298 return SRCLINE_UNKNOWN;
299 } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0)
300 return SRCLINE_UNKNOWN;
301 return srcline;
293} 302}
294 303
295void free_srcline(char *srcline) 304void free_srcline(char *srcline)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 1e23a5bfb044..06fcd1bf98b6 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -11,6 +11,27 @@
11#include <symbol/kallsyms.h> 11#include <symbol/kallsyms.h>
12#include "debug.h" 12#include "debug.h"
13 13
14#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
15extern char *cplus_demangle(const char *, int);
16
17static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
18{
19 return cplus_demangle(c, i);
20}
21#else
22#ifdef NO_DEMANGLE
23static inline char *bfd_demangle(void __maybe_unused *v,
24 const char __maybe_unused *c,
25 int __maybe_unused i)
26{
27 return NULL;
28}
29#else
30#define PACKAGE 'perf'
31#include <bfd.h>
32#endif
33#endif
34
14#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT 35#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
15static int elf_getphdrnum(Elf *elf, size_t *dst) 36static int elf_getphdrnum(Elf *elf, size_t *dst)
16{ 37{
@@ -546,6 +567,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
546 return 0; 567 return 0;
547} 568}
548 569
570static int decompress_kmodule(struct dso *dso, const char *name,
571 enum dso_binary_type type)
572{
573 int fd;
574 const char *ext = strrchr(name, '.');
575 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
576
577 if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
578 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) ||
579 type != dso->symtab_type)
580 return -1;
581
582 if (!ext || !is_supported_compression(ext + 1))
583 return -1;
584
585 fd = mkstemp(tmpbuf);
586 if (fd < 0)
587 return -1;
588
589 if (!decompress_to_file(ext + 1, name, fd)) {
590 close(fd);
591 fd = -1;
592 }
593
594 unlink(tmpbuf);
595
596 return fd;
597}
598
549bool symsrc__possibly_runtime(struct symsrc *ss) 599bool symsrc__possibly_runtime(struct symsrc *ss)
550{ 600{
551 return ss->dynsym || ss->opdsec; 601 return ss->dynsym || ss->opdsec;
@@ -571,7 +621,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
571 Elf *elf; 621 Elf *elf;
572 int fd; 622 int fd;
573 623
574 fd = open(name, O_RDONLY); 624 if (dso__needs_decompress(dso))
625 fd = decompress_kmodule(dso, name, type);
626 else
627 fd = open(name, O_RDONLY);
628
575 if (fd < 0) 629 if (fd < 0)
576 return -1; 630 return -1;
577 631
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index c9541fea9514..d7efb03b3f9a 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -129,6 +129,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
129 129
130 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { 130 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
131 void *tmp; 131 void *tmp;
132 long offset;
132 133
133 if (need_swap) { 134 if (need_swap) {
134 phdr->p_type = bswap_32(phdr->p_type); 135 phdr->p_type = bswap_32(phdr->p_type);
@@ -140,12 +141,13 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
140 continue; 141 continue;
141 142
142 buf_size = phdr->p_filesz; 143 buf_size = phdr->p_filesz;
144 offset = phdr->p_offset;
143 tmp = realloc(buf, buf_size); 145 tmp = realloc(buf, buf_size);
144 if (tmp == NULL) 146 if (tmp == NULL)
145 goto out_free; 147 goto out_free;
146 148
147 buf = tmp; 149 buf = tmp;
148 fseek(fp, phdr->p_offset, SEEK_SET); 150 fseek(fp, offset, SEEK_SET);
149 if (fread(buf, buf_size, 1, fp) != 1) 151 if (fread(buf, buf_size, 1, fp) != 1)
150 goto out_free; 152 goto out_free;
151 153
@@ -178,6 +180,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
178 180
179 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { 181 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
180 void *tmp; 182 void *tmp;
183 long offset;
181 184
182 if (need_swap) { 185 if (need_swap) {
183 phdr->p_type = bswap_32(phdr->p_type); 186 phdr->p_type = bswap_32(phdr->p_type);
@@ -189,12 +192,13 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
189 continue; 192 continue;
190 193
191 buf_size = phdr->p_filesz; 194 buf_size = phdr->p_filesz;
195 offset = phdr->p_offset;
192 tmp = realloc(buf, buf_size); 196 tmp = realloc(buf, buf_size);
193 if (tmp == NULL) 197 if (tmp == NULL)
194 goto out_free; 198 goto out_free;
195 199
196 buf = tmp; 200 buf = tmp;
197 fseek(fp, phdr->p_offset, SEEK_SET); 201 fseek(fp, offset, SEEK_SET);
198 if (fread(buf, buf_size, 1, fp) != 1) 202 if (fread(buf, buf_size, 1, fp) != 1)
199 goto out_free; 203 goto out_free;
200 204
@@ -341,7 +345,6 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
341 345
342 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { 346 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
343 dso__set_build_id(dso, build_id); 347 dso__set_build_id(dso, build_id);
344 return 1;
345 } 348 }
346 return 0; 349 return 0;
347} 350}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 078331140d8c..c24c5b83156c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -51,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = {
51 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 51 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
52 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 52 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
53 DSO_BINARY_TYPE__GUEST_KMODULE, 53 DSO_BINARY_TYPE__GUEST_KMODULE,
54 DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
54 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 55 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
56 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
55 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 57 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
56 DSO_BINARY_TYPE__NOT_FOUND, 58 DSO_BINARY_TYPE__NOT_FOUND,
57}; 59};
@@ -1300,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1300 return dso->kernel == DSO_TYPE_GUEST_KERNEL; 1302 return dso->kernel == DSO_TYPE_GUEST_KERNEL;
1301 1303
1302 case DSO_BINARY_TYPE__GUEST_KMODULE: 1304 case DSO_BINARY_TYPE__GUEST_KMODULE:
1305 case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
1303 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 1306 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1307 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
1304 /* 1308 /*
1305 * kernel modules know their symtab type - it's set when 1309 * kernel modules know their symtab type - it's set when
1306 * creating a module dso in machine__new_module(). 1310 * creating a module dso in machine__new_module().
@@ -1368,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1368 return -1; 1372 return -1;
1369 1373
1370 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || 1374 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1371 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE; 1375 dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
1376 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE ||
1377 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
1372 1378
1373 /* 1379 /*
1374 * Iterate over candidate debug images. 1380 * Iterate over candidate debug images.
@@ -1505,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1505 symbol_filter_t filter) 1511 symbol_filter_t filter)
1506{ 1512{
1507 int i, err = 0; 1513 int i, err = 0;
1508 char *filename; 1514 char *filename = NULL;
1509 1515
1510 pr_debug("Looking at the vmlinux_path (%d entries long)\n", 1516 if (!symbol_conf.ignore_vmlinux_buildid)
1511 vmlinux_path__nr_entries + 1); 1517 filename = dso__build_id_filename(dso, NULL, 0);
1512
1513 filename = dso__build_id_filename(dso, NULL, 0);
1514 if (filename != NULL) { 1518 if (filename != NULL) {
1515 err = dso__load_vmlinux(dso, map, filename, true, filter); 1519 err = dso__load_vmlinux(dso, map, filename, true, filter);
1516 if (err > 0) 1520 if (err > 0)
@@ -1518,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1518 free(filename); 1522 free(filename);
1519 } 1523 }
1520 1524
1525 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1526 vmlinux_path__nr_entries + 1);
1527
1521 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1528 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1522 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); 1529 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
1523 if (err > 0) 1530 if (err > 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index eb2c19bf8d90..9d602e9c6f59 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -23,27 +23,6 @@
23 23
24#include "dso.h" 24#include "dso.h"
25 25
26#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
27extern char *cplus_demangle(const char *, int);
28
29static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
30{
31 return cplus_demangle(c, i);
32}
33#else
34#ifdef NO_DEMANGLE
35static inline char *bfd_demangle(void __maybe_unused *v,
36 const char __maybe_unused *c,
37 int __maybe_unused i)
38{
39 return NULL;
40}
41#else
42#define PACKAGE 'perf'
43#include <bfd.h>
44#endif
45#endif
46
47/* 26/*
48 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 27 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
49 * for newer versions we can use mmap to reduce memory usage: 28 * for newer versions we can use mmap to reduce memory usage:
@@ -105,6 +84,7 @@ struct symbol_conf {
105 unsigned short nr_events; 84 unsigned short nr_events;
106 bool try_vmlinux_path, 85 bool try_vmlinux_path,
107 ignore_vmlinux, 86 ignore_vmlinux,
87 ignore_vmlinux_buildid,
108 show_kernel_path, 88 show_kernel_path,
109 use_modules, 89 use_modules,
110 sort_by_name, 90 sort_by_name,
@@ -122,7 +102,8 @@ struct symbol_conf {
122 demangle, 102 demangle,
123 demangle_kernel, 103 demangle_kernel,
124 filter_relative, 104 filter_relative,
125 show_hist_headers; 105 show_hist_headers,
106 branch_callstack;
126 const char *vmlinux_name, 107 const char *vmlinux_name,
127 *kallsyms_name, 108 *kallsyms_name,
128 *source_prefix, 109 *source_prefix,
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
new file mode 100644
index 000000000000..9ed59a452d1f
--- /dev/null
+++ b/tools/perf/util/thread-stack.c
@@ -0,0 +1,747 @@
1/*
2 * thread-stack.c: Synthesize a thread's stack using call / return events
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <linux/rbtree.h>
17#include <linux/list.h>
18#include "thread.h"
19#include "event.h"
20#include "machine.h"
21#include "util.h"
22#include "debug.h"
23#include "symbol.h"
24#include "comm.h"
25#include "thread-stack.h"
26
27#define CALL_PATH_BLOCK_SHIFT 8
28#define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT)
29#define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1)
30
31struct call_path_block {
32 struct call_path cp[CALL_PATH_BLOCK_SIZE];
33 struct list_head node;
34};
35
36/**
37 * struct call_path_root - root of all call paths.
38 * @call_path: root call path
39 * @blocks: list of blocks to store call paths
40 * @next: next free space
41 * @sz: number of spaces
42 */
43struct call_path_root {
44 struct call_path call_path;
45 struct list_head blocks;
46 size_t next;
47 size_t sz;
48};
49
50/**
51 * struct call_return_processor - provides a call-back to consume call-return
52 * information.
53 * @cpr: call path root
54 * @process: call-back that accepts call/return information
55 * @data: anonymous data for call-back
56 */
57struct call_return_processor {
58 struct call_path_root *cpr;
59 int (*process)(struct call_return *cr, void *data);
60 void *data;
61};
62
63#define STACK_GROWTH 2048
64
65/**
66 * struct thread_stack_entry - thread stack entry.
67 * @ret_addr: return address
68 * @timestamp: timestamp (if known)
69 * @ref: external reference (e.g. db_id of sample)
70 * @branch_count: the branch count when the entry was created
71 * @cp: call path
72 * @no_call: a 'call' was not seen
73 */
74struct thread_stack_entry {
75 u64 ret_addr;
76 u64 timestamp;
77 u64 ref;
78 u64 branch_count;
79 struct call_path *cp;
80 bool no_call;
81};
82
83/**
84 * struct thread_stack - thread stack constructed from 'call' and 'return'
85 * branch samples.
86 * @stack: array that holds the stack
87 * @cnt: number of entries in the stack
88 * @sz: current maximum stack size
89 * @trace_nr: current trace number
90 * @branch_count: running branch count
91 * @kernel_start: kernel start address
92 * @last_time: last timestamp
93 * @crp: call/return processor
94 * @comm: current comm
95 */
96struct thread_stack {
97 struct thread_stack_entry *stack;
98 size_t cnt;
99 size_t sz;
100 u64 trace_nr;
101 u64 branch_count;
102 u64 kernel_start;
103 u64 last_time;
104 struct call_return_processor *crp;
105 struct comm *comm;
106};
107
108static int thread_stack__grow(struct thread_stack *ts)
109{
110 struct thread_stack_entry *new_stack;
111 size_t sz, new_sz;
112
113 new_sz = ts->sz + STACK_GROWTH;
114 sz = new_sz * sizeof(struct thread_stack_entry);
115
116 new_stack = realloc(ts->stack, sz);
117 if (!new_stack)
118 return -ENOMEM;
119
120 ts->stack = new_stack;
121 ts->sz = new_sz;
122
123 return 0;
124}
125
126static struct thread_stack *thread_stack__new(struct thread *thread,
127 struct call_return_processor *crp)
128{
129 struct thread_stack *ts;
130
131 ts = zalloc(sizeof(struct thread_stack));
132 if (!ts)
133 return NULL;
134
135 if (thread_stack__grow(ts)) {
136 free(ts);
137 return NULL;
138 }
139
140 if (thread->mg && thread->mg->machine)
141 ts->kernel_start = machine__kernel_start(thread->mg->machine);
142 else
143 ts->kernel_start = 1ULL << 63;
144 ts->crp = crp;
145
146 return ts;
147}
148
149static int thread_stack__push(struct thread_stack *ts, u64 ret_addr)
150{
151 int err = 0;
152
153 if (ts->cnt == ts->sz) {
154 err = thread_stack__grow(ts);
155 if (err) {
156 pr_warning("Out of memory: discarding thread stack\n");
157 ts->cnt = 0;
158 }
159 }
160
161 ts->stack[ts->cnt++].ret_addr = ret_addr;
162
163 return err;
164}
165
166static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr)
167{
168 size_t i;
169
170 /*
171 * In some cases there may be functions which are not seen to return.
172 * For example when setjmp / longjmp has been used. Or the perf context
173 * switch in the kernel which doesn't stop and start tracing in exactly
174 * the same code path. When that happens the return address will be
175 * further down the stack. If the return address is not found at all,
176 * we assume the opposite (i.e. this is a return for a call that wasn't
177 * seen for some reason) and leave the stack alone.
178 */
179 for (i = ts->cnt; i; ) {
180 if (ts->stack[--i].ret_addr == ret_addr) {
181 ts->cnt = i;
182 return;
183 }
184 }
185}
186
187static bool thread_stack__in_kernel(struct thread_stack *ts)
188{
189 if (!ts->cnt)
190 return false;
191
192 return ts->stack[ts->cnt - 1].cp->in_kernel;
193}
194
195static int thread_stack__call_return(struct thread *thread,
196 struct thread_stack *ts, size_t idx,
197 u64 timestamp, u64 ref, bool no_return)
198{
199 struct call_return_processor *crp = ts->crp;
200 struct thread_stack_entry *tse;
201 struct call_return cr = {
202 .thread = thread,
203 .comm = ts->comm,
204 .db_id = 0,
205 };
206
207 tse = &ts->stack[idx];
208 cr.cp = tse->cp;
209 cr.call_time = tse->timestamp;
210 cr.return_time = timestamp;
211 cr.branch_count = ts->branch_count - tse->branch_count;
212 cr.call_ref = tse->ref;
213 cr.return_ref = ref;
214 if (tse->no_call)
215 cr.flags |= CALL_RETURN_NO_CALL;
216 if (no_return)
217 cr.flags |= CALL_RETURN_NO_RETURN;
218
219 return crp->process(&cr, crp->data);
220}
221
222static int thread_stack__flush(struct thread *thread, struct thread_stack *ts)
223{
224 struct call_return_processor *crp = ts->crp;
225 int err;
226
227 if (!crp) {
228 ts->cnt = 0;
229 return 0;
230 }
231
232 while (ts->cnt) {
233 err = thread_stack__call_return(thread, ts, --ts->cnt,
234 ts->last_time, 0, true);
235 if (err) {
236 pr_err("Error flushing thread stack!\n");
237 ts->cnt = 0;
238 return err;
239 }
240 }
241
242 return 0;
243}
244
245int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
246 u64 to_ip, u16 insn_len, u64 trace_nr)
247{
248 if (!thread)
249 return -EINVAL;
250
251 if (!thread->ts) {
252 thread->ts = thread_stack__new(thread, NULL);
253 if (!thread->ts) {
254 pr_warning("Out of memory: no thread stack\n");
255 return -ENOMEM;
256 }
257 thread->ts->trace_nr = trace_nr;
258 }
259
260 /*
261 * When the trace is discontinuous, the trace_nr changes. In that case
262 * the stack might be completely invalid. Better to report nothing than
263 * to report something misleading, so flush the stack.
264 */
265 if (trace_nr != thread->ts->trace_nr) {
266 if (thread->ts->trace_nr)
267 thread_stack__flush(thread, thread->ts);
268 thread->ts->trace_nr = trace_nr;
269 }
270
271 /* Stop here if thread_stack__process() is in use */
272 if (thread->ts->crp)
273 return 0;
274
275 if (flags & PERF_IP_FLAG_CALL) {
276 u64 ret_addr;
277
278 if (!to_ip)
279 return 0;
280 ret_addr = from_ip + insn_len;
281 if (ret_addr == to_ip)
282 return 0; /* Zero-length calls are excluded */
283 return thread_stack__push(thread->ts, ret_addr);
284 } else if (flags & PERF_IP_FLAG_RETURN) {
285 if (!from_ip)
286 return 0;
287 thread_stack__pop(thread->ts, to_ip);
288 }
289
290 return 0;
291}
292
293void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
294{
295 if (!thread || !thread->ts)
296 return;
297
298 if (trace_nr != thread->ts->trace_nr) {
299 if (thread->ts->trace_nr)
300 thread_stack__flush(thread, thread->ts);
301 thread->ts->trace_nr = trace_nr;
302 }
303}
304
305void thread_stack__free(struct thread *thread)
306{
307 if (thread->ts) {
308 thread_stack__flush(thread, thread->ts);
309 zfree(&thread->ts->stack);
310 zfree(&thread->ts);
311 }
312}
313
314void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
315 size_t sz, u64 ip)
316{
317 size_t i;
318
319 if (!thread || !thread->ts)
320 chain->nr = 1;
321 else
322 chain->nr = min(sz, thread->ts->cnt + 1);
323
324 chain->ips[0] = ip;
325
326 for (i = 1; i < chain->nr; i++)
327 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;
328}
329
330static void call_path__init(struct call_path *cp, struct call_path *parent,
331 struct symbol *sym, u64 ip, bool in_kernel)
332{
333 cp->parent = parent;
334 cp->sym = sym;
335 cp->ip = sym ? 0 : ip;
336 cp->db_id = 0;
337 cp->in_kernel = in_kernel;
338 RB_CLEAR_NODE(&cp->rb_node);
339 cp->children = RB_ROOT;
340}
341
342static struct call_path_root *call_path_root__new(void)
343{
344 struct call_path_root *cpr;
345
346 cpr = zalloc(sizeof(struct call_path_root));
347 if (!cpr)
348 return NULL;
349 call_path__init(&cpr->call_path, NULL, NULL, 0, false);
350 INIT_LIST_HEAD(&cpr->blocks);
351 return cpr;
352}
353
354static void call_path_root__free(struct call_path_root *cpr)
355{
356 struct call_path_block *pos, *n;
357
358 list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
359 list_del(&pos->node);
360 free(pos);
361 }
362 free(cpr);
363}
364
365static struct call_path *call_path__new(struct call_path_root *cpr,
366 struct call_path *parent,
367 struct symbol *sym, u64 ip,
368 bool in_kernel)
369{
370 struct call_path_block *cpb;
371 struct call_path *cp;
372 size_t n;
373
374 if (cpr->next < cpr->sz) {
375 cpb = list_last_entry(&cpr->blocks, struct call_path_block,
376 node);
377 } else {
378 cpb = zalloc(sizeof(struct call_path_block));
379 if (!cpb)
380 return NULL;
381 list_add_tail(&cpb->node, &cpr->blocks);
382 cpr->sz += CALL_PATH_BLOCK_SIZE;
383 }
384
385 n = cpr->next++ & CALL_PATH_BLOCK_MASK;
386 cp = &cpb->cp[n];
387
388 call_path__init(cp, parent, sym, ip, in_kernel);
389
390 return cp;
391}
392
393static struct call_path *call_path__findnew(struct call_path_root *cpr,
394 struct call_path *parent,
395 struct symbol *sym, u64 ip, u64 ks)
396{
397 struct rb_node **p;
398 struct rb_node *node_parent = NULL;
399 struct call_path *cp;
400 bool in_kernel = ip >= ks;
401
402 if (sym)
403 ip = 0;
404
405 if (!parent)
406 return call_path__new(cpr, parent, sym, ip, in_kernel);
407
408 p = &parent->children.rb_node;
409 while (*p != NULL) {
410 node_parent = *p;
411 cp = rb_entry(node_parent, struct call_path, rb_node);
412
413 if (cp->sym == sym && cp->ip == ip)
414 return cp;
415
416 if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
417 p = &(*p)->rb_left;
418 else
419 p = &(*p)->rb_right;
420 }
421
422 cp = call_path__new(cpr, parent, sym, ip, in_kernel);
423 if (!cp)
424 return NULL;
425
426 rb_link_node(&cp->rb_node, node_parent, p);
427 rb_insert_color(&cp->rb_node, &parent->children);
428
429 return cp;
430}
431
432struct call_return_processor *
433call_return_processor__new(int (*process)(struct call_return *cr, void *data),
434 void *data)
435{
436 struct call_return_processor *crp;
437
438 crp = zalloc(sizeof(struct call_return_processor));
439 if (!crp)
440 return NULL;
441 crp->cpr = call_path_root__new();
442 if (!crp->cpr)
443 goto out_free;
444 crp->process = process;
445 crp->data = data;
446 return crp;
447
448out_free:
449 free(crp);
450 return NULL;
451}
452
453void call_return_processor__free(struct call_return_processor *crp)
454{
455 if (crp) {
456 call_path_root__free(crp->cpr);
457 free(crp);
458 }
459}
460
461static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
462 u64 timestamp, u64 ref, struct call_path *cp,
463 bool no_call)
464{
465 struct thread_stack_entry *tse;
466 int err;
467
468 if (ts->cnt == ts->sz) {
469 err = thread_stack__grow(ts);
470 if (err)
471 return err;
472 }
473
474 tse = &ts->stack[ts->cnt++];
475 tse->ret_addr = ret_addr;
476 tse->timestamp = timestamp;
477 tse->ref = ref;
478 tse->branch_count = ts->branch_count;
479 tse->cp = cp;
480 tse->no_call = no_call;
481
482 return 0;
483}
484
485static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts,
486 u64 ret_addr, u64 timestamp, u64 ref,
487 struct symbol *sym)
488{
489 int err;
490
491 if (!ts->cnt)
492 return 1;
493
494 if (ts->cnt == 1) {
495 struct thread_stack_entry *tse = &ts->stack[0];
496
497 if (tse->cp->sym == sym)
498 return thread_stack__call_return(thread, ts, --ts->cnt,
499 timestamp, ref, false);
500 }
501
502 if (ts->stack[ts->cnt - 1].ret_addr == ret_addr) {
503 return thread_stack__call_return(thread, ts, --ts->cnt,
504 timestamp, ref, false);
505 } else {
506 size_t i = ts->cnt - 1;
507
508 while (i--) {
509 if (ts->stack[i].ret_addr != ret_addr)
510 continue;
511 i += 1;
512 while (ts->cnt > i) {
513 err = thread_stack__call_return(thread, ts,
514 --ts->cnt,
515 timestamp, ref,
516 true);
517 if (err)
518 return err;
519 }
520 return thread_stack__call_return(thread, ts, --ts->cnt,
521 timestamp, ref, false);
522 }
523 }
524
525 return 1;
526}
527
528static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts,
529 struct perf_sample *sample,
530 struct addr_location *from_al,
531 struct addr_location *to_al, u64 ref)
532{
533 struct call_path_root *cpr = ts->crp->cpr;
534 struct call_path *cp;
535 struct symbol *sym;
536 u64 ip;
537
538 if (sample->ip) {
539 ip = sample->ip;
540 sym = from_al->sym;
541 } else if (sample->addr) {
542 ip = sample->addr;
543 sym = to_al->sym;
544 } else {
545 return 0;
546 }
547
548 cp = call_path__findnew(cpr, &cpr->call_path, sym, ip,
549 ts->kernel_start);
550 if (!cp)
551 return -ENOMEM;
552
553 return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp,
554 true);
555}
556
557static int thread_stack__no_call_return(struct thread *thread,
558 struct thread_stack *ts,
559 struct perf_sample *sample,
560 struct addr_location *from_al,
561 struct addr_location *to_al, u64 ref)
562{
563 struct call_path_root *cpr = ts->crp->cpr;
564 struct call_path *cp, *parent;
565 u64 ks = ts->kernel_start;
566 int err;
567
568 if (sample->ip >= ks && sample->addr < ks) {
569 /* Return to userspace, so pop all kernel addresses */
570 while (thread_stack__in_kernel(ts)) {
571 err = thread_stack__call_return(thread, ts, --ts->cnt,
572 sample->time, ref,
573 true);
574 if (err)
575 return err;
576 }
577
578 /* If the stack is empty, push the userspace address */
579 if (!ts->cnt) {
580 cp = call_path__findnew(cpr, &cpr->call_path,
581 to_al->sym, sample->addr,
582 ts->kernel_start);
583 if (!cp)
584 return -ENOMEM;
585 return thread_stack__push_cp(ts, 0, sample->time, ref,
586 cp, true);
587 }
588 } else if (thread_stack__in_kernel(ts) && sample->ip < ks) {
589 /* Return to userspace, so pop all kernel addresses */
590 while (thread_stack__in_kernel(ts)) {
591 err = thread_stack__call_return(thread, ts, --ts->cnt,
592 sample->time, ref,
593 true);
594 if (err)
595 return err;
596 }
597 }
598
599 if (ts->cnt)
600 parent = ts->stack[ts->cnt - 1].cp;
601 else
602 parent = &cpr->call_path;
603
604 /* This 'return' had no 'call', so push and pop top of stack */
605 cp = call_path__findnew(cpr, parent, from_al->sym, sample->ip,
606 ts->kernel_start);
607 if (!cp)
608 return -ENOMEM;
609
610 err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp,
611 true);
612 if (err)
613 return err;
614
615 return thread_stack__pop_cp(thread, ts, sample->addr, sample->time, ref,
616 to_al->sym);
617}
618
619static int thread_stack__trace_begin(struct thread *thread,
620 struct thread_stack *ts, u64 timestamp,
621 u64 ref)
622{
623 struct thread_stack_entry *tse;
624 int err;
625
626 if (!ts->cnt)
627 return 0;
628
629 /* Pop trace end */
630 tse = &ts->stack[ts->cnt - 1];
631 if (tse->cp->sym == NULL && tse->cp->ip == 0) {
632 err = thread_stack__call_return(thread, ts, --ts->cnt,
633 timestamp, ref, false);
634 if (err)
635 return err;
636 }
637
638 return 0;
639}
640
641static int thread_stack__trace_end(struct thread_stack *ts,
642 struct perf_sample *sample, u64 ref)
643{
644 struct call_path_root *cpr = ts->crp->cpr;
645 struct call_path *cp;
646 u64 ret_addr;
647
648 /* No point having 'trace end' on the bottom of the stack */
649 if (!ts->cnt || (ts->cnt == 1 && ts->stack[0].ref == ref))
650 return 0;
651
652 cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, NULL, 0,
653 ts->kernel_start);
654 if (!cp)
655 return -ENOMEM;
656
657 ret_addr = sample->ip + sample->insn_len;
658
659 return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp,
660 false);
661}
662
663int thread_stack__process(struct thread *thread, struct comm *comm,
664 struct perf_sample *sample,
665 struct addr_location *from_al,
666 struct addr_location *to_al, u64 ref,
667 struct call_return_processor *crp)
668{
669 struct thread_stack *ts = thread->ts;
670 int err = 0;
671
672 if (ts) {
673 if (!ts->crp) {
674 /* Supersede thread_stack__event() */
675 thread_stack__free(thread);
676 thread->ts = thread_stack__new(thread, crp);
677 if (!thread->ts)
678 return -ENOMEM;
679 ts = thread->ts;
680 ts->comm = comm;
681 }
682 } else {
683 thread->ts = thread_stack__new(thread, crp);
684 if (!thread->ts)
685 return -ENOMEM;
686 ts = thread->ts;
687 ts->comm = comm;
688 }
689
690 /* Flush stack on exec */
691 if (ts->comm != comm && thread->pid_ == thread->tid) {
692 err = thread_stack__flush(thread, ts);
693 if (err)
694 return err;
695 ts->comm = comm;
696 }
697
698 /* If the stack is empty, put the current symbol on the stack */
699 if (!ts->cnt) {
700 err = thread_stack__bottom(thread, ts, sample, from_al, to_al,
701 ref);
702 if (err)
703 return err;
704 }
705
706 ts->branch_count += 1;
707 ts->last_time = sample->time;
708
709 if (sample->flags & PERF_IP_FLAG_CALL) {
710 struct call_path_root *cpr = ts->crp->cpr;
711 struct call_path *cp;
712 u64 ret_addr;
713
714 if (!sample->ip || !sample->addr)
715 return 0;
716
717 ret_addr = sample->ip + sample->insn_len;
718 if (ret_addr == sample->addr)
719 return 0; /* Zero-length calls are excluded */
720
721 cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp,
722 to_al->sym, sample->addr,
723 ts->kernel_start);
724 if (!cp)
725 return -ENOMEM;
726 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
727 cp, false);
728 } else if (sample->flags & PERF_IP_FLAG_RETURN) {
729 if (!sample->ip || !sample->addr)
730 return 0;
731
732 err = thread_stack__pop_cp(thread, ts, sample->addr,
733 sample->time, ref, from_al->sym);
734 if (err) {
735 if (err < 0)
736 return err;
737 err = thread_stack__no_call_return(thread, ts, sample,
738 from_al, to_al, ref);
739 }
740 } else if (sample->flags & PERF_IP_FLAG_TRACE_BEGIN) {
741 err = thread_stack__trace_begin(thread, ts, sample->time, ref);
742 } else if (sample->flags & PERF_IP_FLAG_TRACE_END) {
743 err = thread_stack__trace_end(ts, sample, ref);
744 }
745
746 return err;
747}
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
new file mode 100644
index 000000000000..b843bbef8ba2
--- /dev/null
+++ b/tools/perf/util/thread-stack.h
@@ -0,0 +1,111 @@
1/*
2 * thread-stack.h: Synthesize a thread's stack using call / return events
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_THREAD_STACK_H
17#define __PERF_THREAD_STACK_H
18
19#include <sys/types.h>
20
21#include <linux/types.h>
22#include <linux/rbtree.h>
23
24struct thread;
25struct comm;
26struct ip_callchain;
27struct symbol;
28struct dso;
29struct call_return_processor;
30struct comm;
31struct perf_sample;
32struct addr_location;
33
34/*
35 * Call/Return flags.
36 *
37 * CALL_RETURN_NO_CALL: 'return' but no matching 'call'
38 * CALL_RETURN_NO_RETURN: 'call' but no matching 'return'
39 */
40enum {
41 CALL_RETURN_NO_CALL = 1 << 0,
42 CALL_RETURN_NO_RETURN = 1 << 1,
43};
44
45/**
46 * struct call_return - paired call/return information.
47 * @thread: thread in which call/return occurred
48 * @comm: comm in which call/return occurred
49 * @cp: call path
50 * @call_time: timestamp of call (if known)
51 * @return_time: timestamp of return (if known)
52 * @branch_count: number of branches seen between call and return
53 * @call_ref: external reference to 'call' sample (e.g. db_id)
54 * @return_ref: external reference to 'return' sample (e.g. db_id)
55 * @db_id: id used for db-export
56 * @flags: Call/Return flags
57 */
58struct call_return {
59 struct thread *thread;
60 struct comm *comm;
61 struct call_path *cp;
62 u64 call_time;
63 u64 return_time;
64 u64 branch_count;
65 u64 call_ref;
66 u64 return_ref;
67 u64 db_id;
68 u32 flags;
69};
70
71/**
72 * struct call_path - node in list of calls leading to a function call.
73 * @parent: call path to the parent function call
74 * @sym: symbol of function called
75 * @ip: only if sym is null, the ip of the function
76 * @db_id: id used for db-export
77 * @in_kernel: whether function is a in the kernel
78 * @rb_node: node in parent's tree of called functions
79 * @children: tree of call paths of functions called
80 *
81 * In combination with the call_return structure, the call_path structure
82 * defines a context-sensitve call-graph.
83 */
84struct call_path {
85 struct call_path *parent;
86 struct symbol *sym;
87 u64 ip;
88 u64 db_id;
89 bool in_kernel;
90 struct rb_node rb_node;
91 struct rb_root children;
92};
93
94int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
95 u64 to_ip, u16 insn_len, u64 trace_nr);
96void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
97void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
98 size_t sz, u64 ip);
99void thread_stack__free(struct thread *thread);
100
101struct call_return_processor *
102call_return_processor__new(int (*process)(struct call_return *cr, void *data),
103 void *data);
104void call_return_processor__free(struct call_return_processor *crp);
105int thread_stack__process(struct thread *thread, struct comm *comm,
106 struct perf_sample *sample,
107 struct addr_location *from_al,
108 struct addr_location *to_al, u64 ref,
109 struct call_return_processor *crp);
110
111#endif
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index c41411726c7a..9ebc8b1f9be5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -4,6 +4,7 @@
4#include <string.h> 4#include <string.h>
5#include "session.h" 5#include "session.h"
6#include "thread.h" 6#include "thread.h"
7#include "thread-stack.h"
7#include "util.h" 8#include "util.h"
8#include "debug.h" 9#include "debug.h"
9#include "comm.h" 10#include "comm.h"
@@ -15,7 +16,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)
15 pid_t pid = thread->pid_; 16 pid_t pid = thread->pid_;
16 17
17 if (pid == thread->tid || pid == -1) { 18 if (pid == thread->tid || pid == -1) {
18 thread->mg = map_groups__new(); 19 thread->mg = map_groups__new(machine);
19 } else { 20 } else {
20 leader = machine__findnew_thread(machine, pid, pid); 21 leader = machine__findnew_thread(machine, pid, pid);
21 if (leader) 22 if (leader)
@@ -66,6 +67,8 @@ void thread__delete(struct thread *thread)
66{ 67{
67 struct comm *comm, *tmp; 68 struct comm *comm, *tmp;
68 69
70 thread_stack__free(thread);
71
69 if (thread->mg) { 72 if (thread->mg) {
70 map_groups__put(thread->mg); 73 map_groups__put(thread->mg);
71 thread->mg = NULL; 74 thread->mg = NULL;
@@ -100,15 +103,14 @@ struct comm *thread__exec_comm(const struct thread *thread)
100 return last; 103 return last;
101} 104}
102 105
103/* CHECKME: time should always be 0 if event aren't ordered */
104int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, 106int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
105 bool exec) 107 bool exec)
106{ 108{
107 struct comm *new, *curr = thread__comm(thread); 109 struct comm *new, *curr = thread__comm(thread);
108 int err; 110 int err;
109 111
110 /* Override latest entry if it had no specific time coverage */ 112 /* Override the default :tid entry */
111 if (!curr->start && !curr->exec) { 113 if (!thread->comm_set) {
112 err = comm__override(curr, str, timestamp, exec); 114 err = comm__override(curr, str, timestamp, exec);
113 if (err) 115 if (err)
114 return err; 116 return err;
@@ -198,7 +200,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
198} 200}
199 201
200void thread__find_cpumode_addr_location(struct thread *thread, 202void thread__find_cpumode_addr_location(struct thread *thread,
201 struct machine *machine,
202 enum map_type type, u64 addr, 203 enum map_type type, u64 addr,
203 struct addr_location *al) 204 struct addr_location *al)
204{ 205{
@@ -211,8 +212,7 @@ void thread__find_cpumode_addr_location(struct thread *thread,
211 }; 212 };
212 213
213 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { 214 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
214 thread__find_addr_location(thread, machine, cpumodes[i], type, 215 thread__find_addr_location(thread, cpumodes[i], type, addr, al);
215 addr, al);
216 if (al->map) 216 if (al->map)
217 break; 217 break;
218 } 218 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 8c75fa774706..160fd066a7d1 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -8,6 +8,8 @@
8#include "symbol.h" 8#include "symbol.h"
9#include <strlist.h> 9#include <strlist.h>
10 10
11struct thread_stack;
12
11struct thread { 13struct thread {
12 union { 14 union {
13 struct rb_node rb_node; 15 struct rb_node rb_node;
@@ -23,8 +25,10 @@ struct thread {
23 bool dead; /* if set thread has exited */ 25 bool dead; /* if set thread has exited */
24 struct list_head comm_list; 26 struct list_head comm_list;
25 int comm_len; 27 int comm_len;
28 u64 db_id;
26 29
27 void *priv; 30 void *priv;
31 struct thread_stack *ts;
28}; 32};
29 33
30struct machine; 34struct machine;
@@ -54,16 +58,15 @@ void thread__insert_map(struct thread *thread, struct map *map);
54int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 58int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
55size_t thread__fprintf(struct thread *thread, FILE *fp); 59size_t thread__fprintf(struct thread *thread, FILE *fp);
56 60
57void thread__find_addr_map(struct thread *thread, struct machine *machine, 61void thread__find_addr_map(struct thread *thread,
58 u8 cpumode, enum map_type type, u64 addr, 62 u8 cpumode, enum map_type type, u64 addr,
59 struct addr_location *al); 63 struct addr_location *al);
60 64
61void thread__find_addr_location(struct thread *thread, struct machine *machine, 65void thread__find_addr_location(struct thread *thread,
62 u8 cpumode, enum map_type type, u64 addr, 66 u8 cpumode, enum map_type type, u64 addr,
63 struct addr_location *al); 67 struct addr_location *al);
64 68
65void thread__find_cpumode_addr_location(struct thread *thread, 69void thread__find_cpumode_addr_location(struct thread *thread,
66 struct machine *machine,
67 enum map_type type, u64 addr, 70 enum map_type type, u64 addr,
68 struct addr_location *al); 71 struct addr_location *al);
69 72
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index f11636966a0f..bb2708bbfaca 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -39,7 +39,8 @@ struct perf_tool {
39 event_attr_op attr; 39 event_attr_op attr;
40 event_op2 tracing_data; 40 event_op2 tracing_data;
41 event_op2 finished_round, 41 event_op2 finished_round,
42 build_id; 42 build_id,
43 id_index;
43 bool ordered_events; 44 bool ordered_events;
44 bool ordering_requires_timestamps; 45 bool ordering_requires_timestamps;
45}; 46};
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 7419768c38b1..2dcfe9a7c8d0 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -26,7 +26,7 @@ static int __report_module(struct addr_location *al, u64 ip,
26 Dwfl_Module *mod; 26 Dwfl_Module *mod;
27 struct dso *dso = NULL; 27 struct dso *dso = NULL;
28 28
29 thread__find_addr_location(ui->thread, ui->machine, 29 thread__find_addr_location(ui->thread,
30 PERF_RECORD_MISC_USER, 30 PERF_RECORD_MISC_USER,
31 MAP__FUNCTION, ip, al); 31 MAP__FUNCTION, ip, al);
32 32
@@ -89,7 +89,7 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
89 struct addr_location al; 89 struct addr_location al;
90 ssize_t size; 90 ssize_t size;
91 91
92 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 92 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
93 MAP__FUNCTION, addr, &al); 93 MAP__FUNCTION, addr, &al);
94 if (!al.map) { 94 if (!al.map) {
95 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 95 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
@@ -164,14 +164,14 @@ frame_callback(Dwfl_Frame *state, void *arg)
164} 164}
165 165
166int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 166int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
167 struct machine *machine, struct thread *thread, 167 struct thread *thread,
168 struct perf_sample *data, 168 struct perf_sample *data,
169 int max_stack) 169 int max_stack)
170{ 170{
171 struct unwind_info ui = { 171 struct unwind_info ui = {
172 .sample = data, 172 .sample = data,
173 .thread = thread, 173 .thread = thread,
174 .machine = machine, 174 .machine = thread->mg->machine,
175 .cb = cb, 175 .cb = cb,
176 .arg = arg, 176 .arg = arg,
177 .max_stack = max_stack, 177 .max_stack = max_stack,
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 4d45c0dfe343..371219a6daf1 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -284,7 +284,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
284{ 284{
285 struct addr_location al; 285 struct addr_location al;
286 286
287 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 287 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
288 MAP__FUNCTION, ip, &al); 288 MAP__FUNCTION, ip, &al);
289 return al.map; 289 return al.map;
290} 290}
@@ -374,7 +374,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
374 struct addr_location al; 374 struct addr_location al;
375 ssize_t size; 375 ssize_t size;
376 376
377 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 377 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
378 MAP__FUNCTION, addr, &al); 378 MAP__FUNCTION, addr, &al);
379 if (!al.map) { 379 if (!al.map) {
380 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 380 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
@@ -476,14 +476,13 @@ static void put_unwind_info(unw_addr_space_t __maybe_unused as,
476 pr_debug("unwind: put_unwind_info called\n"); 476 pr_debug("unwind: put_unwind_info called\n");
477} 477}
478 478
479static int entry(u64 ip, struct thread *thread, struct machine *machine, 479static int entry(u64 ip, struct thread *thread,
480 unwind_entry_cb_t cb, void *arg) 480 unwind_entry_cb_t cb, void *arg)
481{ 481{
482 struct unwind_entry e; 482 struct unwind_entry e;
483 struct addr_location al; 483 struct addr_location al;
484 484
485 thread__find_addr_location(thread, machine, 485 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
486 PERF_RECORD_MISC_USER,
487 MAP__FUNCTION, ip, &al); 486 MAP__FUNCTION, ip, &al);
488 487
489 e.ip = ip; 488 e.ip = ip;
@@ -586,21 +585,21 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
586 unw_word_t ip; 585 unw_word_t ip;
587 586
588 unw_get_reg(&c, UNW_REG_IP, &ip); 587 unw_get_reg(&c, UNW_REG_IP, &ip);
589 ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; 588 ret = ip ? entry(ip, ui->thread, cb, arg) : 0;
590 } 589 }
591 590
592 return ret; 591 return ret;
593} 592}
594 593
595int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 594int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
596 struct machine *machine, struct thread *thread, 595 struct thread *thread,
597 struct perf_sample *data, int max_stack) 596 struct perf_sample *data, int max_stack)
598{ 597{
599 u64 ip; 598 u64 ip;
600 struct unwind_info ui = { 599 struct unwind_info ui = {
601 .sample = data, 600 .sample = data,
602 .thread = thread, 601 .thread = thread,
603 .machine = machine, 602 .machine = thread->mg->machine,
604 }; 603 };
605 int ret; 604 int ret;
606 605
@@ -611,7 +610,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
611 if (ret) 610 if (ret)
612 return ret; 611 return ret;
613 612
614 ret = entry(ip, thread, machine, cb, arg); 613 ret = entry(ip, thread, cb, arg);
615 if (ret) 614 if (ret)
616 return -ENOMEM; 615 return -ENOMEM;
617 616
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index f50b737235eb..12790cf94618 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -16,7 +16,6 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
16 16
17#ifdef HAVE_DWARF_UNWIND_SUPPORT 17#ifdef HAVE_DWARF_UNWIND_SUPPORT
18int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 18int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
19 struct machine *machine,
20 struct thread *thread, 19 struct thread *thread,
21 struct perf_sample *data, int max_stack); 20 struct perf_sample *data, int max_stack);
22/* libunwind specific */ 21/* libunwind specific */
@@ -38,7 +37,6 @@ static inline void unwind__finish_access(struct thread *thread __maybe_unused) {
38static inline int 37static inline int
39unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, 38unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
40 void *arg __maybe_unused, 39 void *arg __maybe_unused,
41 struct machine *machine __maybe_unused,
42 struct thread *thread __maybe_unused, 40 struct thread *thread __maybe_unused,
43 struct perf_sample *data __maybe_unused, 41 struct perf_sample *data __maybe_unused,
44 int max_stack __maybe_unused) 42 int max_stack __maybe_unused)
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index d5eab3f3323f..b86744f29eef 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -442,23 +442,6 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
442 return (unsigned long) -1; 442 return (unsigned long) -1;
443} 443}
444 444
445int filename__read_int(const char *filename, int *value)
446{
447 char line[64];
448 int fd = open(filename, O_RDONLY), err = -1;
449
450 if (fd < 0)
451 return -1;
452
453 if (read(fd, line, sizeof(line)) > 0) {
454 *value = atoi(line);
455 err = 0;
456 }
457
458 close(fd);
459 return err;
460}
461
462int filename__read_str(const char *filename, char **buf, size_t *sizep) 445int filename__read_str(const char *filename, char **buf, size_t *sizep)
463{ 446{
464 size_t size = 0, alloc_size = 0; 447 size_t size = 0, alloc_size = 0;
@@ -523,16 +506,9 @@ const char *get_filename_for_perf_kvm(void)
523 506
524int perf_event_paranoid(void) 507int perf_event_paranoid(void)
525{ 508{
526 char path[PATH_MAX];
527 const char *procfs = procfs__mountpoint();
528 int value; 509 int value;
529 510
530 if (!procfs) 511 if (sysctl__read_int("kernel/perf_event_paranoid", &value))
531 return INT_MAX;
532
533 scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs);
534
535 if (filename__read_int(path, &value))
536 return INT_MAX; 512 return INT_MAX;
537 513
538 return value; 514 return value;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 80bfdaa0e2a4..027a5153495c 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -153,8 +153,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)))
153extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); 153extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
154 154
155extern int prefixcmp(const char *str, const char *prefix); 155extern int prefixcmp(const char *str, const char *prefix);
156extern void set_buildid_dir(void); 156extern void set_buildid_dir(const char *dir);
157extern void disable_buildid_cache(void);
158 157
159static inline const char *skip_prefix(const char *str, const char *prefix) 158static inline const char *skip_prefix(const char *str, const char *prefix)
160{ 159{
@@ -270,35 +269,6 @@ void event_attr_init(struct perf_event_attr *attr);
270#define _STR(x) #x 269#define _STR(x) #x
271#define STR(x) _STR(x) 270#define STR(x) _STR(x)
272 271
273/*
274 * Determine whether some value is a power of two, where zero is
275 * *not* considered a power of two.
276 */
277
278static inline __attribute__((const))
279bool is_power_of_2(unsigned long n)
280{
281 return (n != 0 && ((n & (n - 1)) == 0));
282}
283
284static inline unsigned next_pow2(unsigned x)
285{
286 if (!x)
287 return 1;
288 return 1ULL << (32 - __builtin_clz(x - 1));
289}
290
291static inline unsigned long next_pow2_l(unsigned long x)
292{
293#if BITS_PER_LONG == 64
294 if (x <= (1UL << 31))
295 return next_pow2(x);
296 return (unsigned long)next_pow2(x >> 32) << 32;
297#else
298 return next_pow2(x);
299#endif
300}
301
302size_t hex_width(u64 v); 272size_t hex_width(u64 v);
303int hex2u64(const char *ptr, u64 *val); 273int hex2u64(const char *ptr, u64 *val);
304 274
@@ -338,11 +308,12 @@ static inline int path__join3(char *bf, size_t size,
338} 308}
339 309
340struct dso; 310struct dso;
311struct symbol;
341 312
342char *get_srcline(struct dso *dso, unsigned long addr); 313char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
314 bool show_sym);
343void free_srcline(char *srcline); 315void free_srcline(char *srcline);
344 316
345int filename__read_int(const char *filename, int *value);
346int filename__read_str(const char *filename, char **buf, size_t *sizep); 317int filename__read_str(const char *filename, char **buf, size_t *sizep);
347int perf_event_paranoid(void); 318int perf_event_paranoid(void);
348 319
@@ -351,4 +322,9 @@ void mem_bswap_32(void *src, int byte_size);
351 322
352const char *get_filename_for_perf_kvm(void); 323const char *get_filename_for_perf_kvm(void);
353bool find_process(const char *name); 324bool find_process(const char *name);
325
326#ifdef HAVE_ZLIB_SUPPORT
327int gzip_decompress_to_file(const char *input, int output_fd);
328#endif
329
354#endif /* GIT_COMPAT_UTIL_H */ 330#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index adca69384fcc..5c7dd796979d 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -12,9 +12,16 @@
12#include "util.h" 12#include "util.h"
13#include "symbol.h" 13#include "symbol.h"
14#include "machine.h" 14#include "machine.h"
15#include "thread.h"
15#include "linux/string.h" 16#include "linux/string.h"
16#include "debug.h" 17#include "debug.h"
17 18
19/*
20 * Include definition of find_vdso_map() also used in perf-read-vdso.c for
21 * building perf-read-vdso32 and perf-read-vdsox32.
22 */
23#include "find-vdso-map.c"
24
18#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX" 25#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
19 26
20struct vdso_file { 27struct vdso_file {
@@ -22,10 +29,15 @@ struct vdso_file {
22 bool error; 29 bool error;
23 char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)]; 30 char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)];
24 const char *dso_name; 31 const char *dso_name;
32 const char *read_prog;
25}; 33};
26 34
27struct vdso_info { 35struct vdso_info {
28 struct vdso_file vdso; 36 struct vdso_file vdso;
37#if BITS_PER_LONG == 64
38 struct vdso_file vdso32;
39 struct vdso_file vdsox32;
40#endif
29}; 41};
30 42
31static struct vdso_info *vdso_info__new(void) 43static struct vdso_info *vdso_info__new(void)
@@ -35,42 +47,23 @@ static struct vdso_info *vdso_info__new(void)
35 .temp_file_name = VDSO__TEMP_FILE_NAME, 47 .temp_file_name = VDSO__TEMP_FILE_NAME,
36 .dso_name = DSO__NAME_VDSO, 48 .dso_name = DSO__NAME_VDSO,
37 }, 49 },
50#if BITS_PER_LONG == 64
51 .vdso32 = {
52 .temp_file_name = VDSO__TEMP_FILE_NAME,
53 .dso_name = DSO__NAME_VDSO32,
54 .read_prog = "perf-read-vdso32",
55 },
56 .vdsox32 = {
57 .temp_file_name = VDSO__TEMP_FILE_NAME,
58 .dso_name = DSO__NAME_VDSOX32,
59 .read_prog = "perf-read-vdsox32",
60 },
61#endif
38 }; 62 };
39 63
40 return memdup(&vdso_info_init, sizeof(vdso_info_init)); 64 return memdup(&vdso_info_init, sizeof(vdso_info_init));
41} 65}
42 66
43static int find_vdso_map(void **start, void **end)
44{
45 FILE *maps;
46 char line[128];
47 int found = 0;
48
49 maps = fopen("/proc/self/maps", "r");
50 if (!maps) {
51 pr_err("vdso: cannot open maps\n");
52 return -1;
53 }
54
55 while (!found && fgets(line, sizeof(line), maps)) {
56 int m = -1;
57
58 /* We care only about private r-x mappings. */
59 if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
60 start, end, &m))
61 continue;
62 if (m < 0)
63 continue;
64
65 if (!strncmp(&line[m], VDSO__MAP_NAME,
66 sizeof(VDSO__MAP_NAME) - 1))
67 found = 1;
68 }
69
70 fclose(maps);
71 return !found;
72}
73
74static char *get_file(struct vdso_file *vdso_file) 67static char *get_file(struct vdso_file *vdso_file)
75{ 68{
76 char *vdso = NULL; 69 char *vdso = NULL;
@@ -117,6 +110,12 @@ void vdso__exit(struct machine *machine)
117 110
118 if (vdso_info->vdso.found) 111 if (vdso_info->vdso.found)
119 unlink(vdso_info->vdso.temp_file_name); 112 unlink(vdso_info->vdso.temp_file_name);
113#if BITS_PER_LONG == 64
114 if (vdso_info->vdso32.found)
115 unlink(vdso_info->vdso32.temp_file_name);
116 if (vdso_info->vdsox32.found)
117 unlink(vdso_info->vdsox32.temp_file_name);
118#endif
120 119
121 zfree(&machine->vdso_info); 120 zfree(&machine->vdso_info);
122} 121}
@@ -135,6 +134,153 @@ static struct dso *vdso__new(struct machine *machine, const char *short_name,
135 return dso; 134 return dso;
136} 135}
137 136
137#if BITS_PER_LONG == 64
138
139static enum dso_type machine__thread_dso_type(struct machine *machine,
140 struct thread *thread)
141{
142 enum dso_type dso_type = DSO__TYPE_UNKNOWN;
143 struct map *map;
144 struct dso *dso;
145
146 map = map_groups__first(thread->mg, MAP__FUNCTION);
147 for (; map ; map = map_groups__next(map)) {
148 dso = map->dso;
149 if (!dso || dso->long_name[0] != '/')
150 continue;
151 dso_type = dso__type(dso, machine);
152 if (dso_type != DSO__TYPE_UNKNOWN)
153 break;
154 }
155
156 return dso_type;
157}
158
159static int vdso__do_copy_compat(FILE *f, int fd)
160{
161 char buf[4096];
162 size_t count;
163
164 while (1) {
165 count = fread(buf, 1, sizeof(buf), f);
166 if (ferror(f))
167 return -errno;
168 if (feof(f))
169 break;
170 if (count && writen(fd, buf, count) != (ssize_t)count)
171 return -errno;
172 }
173
174 return 0;
175}
176
177static int vdso__copy_compat(const char *prog, int fd)
178{
179 FILE *f;
180 int err;
181
182 f = popen(prog, "r");
183 if (!f)
184 return -errno;
185
186 err = vdso__do_copy_compat(f, fd);
187
188 if (pclose(f) == -1)
189 return -errno;
190
191 return err;
192}
193
194static int vdso__create_compat_file(const char *prog, char *temp_name)
195{
196 int fd, err;
197
198 fd = mkstemp(temp_name);
199 if (fd < 0)
200 return -errno;
201
202 err = vdso__copy_compat(prog, fd);
203
204 if (close(fd) == -1)
205 return -errno;
206
207 return err;
208}
209
210static const char *vdso__get_compat_file(struct vdso_file *vdso_file)
211{
212 int err;
213
214 if (vdso_file->found)
215 return vdso_file->temp_file_name;
216
217 if (vdso_file->error)
218 return NULL;
219
220 err = vdso__create_compat_file(vdso_file->read_prog,
221 vdso_file->temp_file_name);
222 if (err) {
223 pr_err("%s failed, error %d\n", vdso_file->read_prog, err);
224 vdso_file->error = true;
225 return NULL;
226 }
227
228 vdso_file->found = true;
229
230 return vdso_file->temp_file_name;
231}
232
233static struct dso *vdso__findnew_compat(struct machine *machine,
234 struct vdso_file *vdso_file)
235{
236 const char *file_name;
237 struct dso *dso;
238
239 dso = dsos__find(&machine->user_dsos, vdso_file->dso_name, true);
240 if (dso)
241 return dso;
242
243 file_name = vdso__get_compat_file(vdso_file);
244 if (!file_name)
245 return NULL;
246
247 return vdso__new(machine, vdso_file->dso_name, file_name);
248}
249
250static int vdso__dso_findnew_compat(struct machine *machine,
251 struct thread *thread,
252 struct vdso_info *vdso_info,
253 struct dso **dso)
254{
255 enum dso_type dso_type;
256
257 dso_type = machine__thread_dso_type(machine, thread);
258
259#ifndef HAVE_PERF_READ_VDSO32
260 if (dso_type == DSO__TYPE_32BIT)
261 return 0;
262#endif
263#ifndef HAVE_PERF_READ_VDSOX32
264 if (dso_type == DSO__TYPE_X32BIT)
265 return 0;
266#endif
267
268 switch (dso_type) {
269 case DSO__TYPE_32BIT:
270 *dso = vdso__findnew_compat(machine, &vdso_info->vdso32);
271 return 1;
272 case DSO__TYPE_X32BIT:
273 *dso = vdso__findnew_compat(machine, &vdso_info->vdsox32);
274 return 1;
275 case DSO__TYPE_UNKNOWN:
276 case DSO__TYPE_64BIT:
277 default:
278 return 0;
279 }
280}
281
282#endif
283
138struct dso *vdso__dso_findnew(struct machine *machine, 284struct dso *vdso__dso_findnew(struct machine *machine,
139 struct thread *thread __maybe_unused) 285 struct thread *thread __maybe_unused)
140{ 286{
@@ -148,6 +294,11 @@ struct dso *vdso__dso_findnew(struct machine *machine,
148 if (!vdso_info) 294 if (!vdso_info)
149 return NULL; 295 return NULL;
150 296
297#if BITS_PER_LONG == 64
298 if (vdso__dso_findnew_compat(machine, thread, vdso_info, &dso))
299 return dso;
300#endif
301
151 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true); 302 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true);
152 if (!dso) { 303 if (!dso) {
153 char *file; 304 char *file;
@@ -164,5 +315,7 @@ struct dso *vdso__dso_findnew(struct machine *machine,
164 315
165bool dso__is_vdso(struct dso *dso) 316bool dso__is_vdso(struct dso *dso)
166{ 317{
167 return !strcmp(dso->short_name, DSO__NAME_VDSO); 318 return !strcmp(dso->short_name, DSO__NAME_VDSO) ||
319 !strcmp(dso->short_name, DSO__NAME_VDSO32) ||
320 !strcmp(dso->short_name, DSO__NAME_VDSOX32);
168} 321}
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h
index af9d6929a215..d97da1616f0c 100644
--- a/tools/perf/util/vdso.h
+++ b/tools/perf/util/vdso.h
@@ -7,7 +7,9 @@
7 7
8#define VDSO__MAP_NAME "[vdso]" 8#define VDSO__MAP_NAME "[vdso]"
9 9
10#define DSO__NAME_VDSO "[vdso]" 10#define DSO__NAME_VDSO "[vdso]"
11#define DSO__NAME_VDSO32 "[vdso32]"
12#define DSO__NAME_VDSOX32 "[vdsox32]"
11 13
12static inline bool is_vdso_map(const char *filename) 14static inline bool is_vdso_map(const char *filename)
13{ 15{
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
new file mode 100644
index 000000000000..495a449fc25c
--- /dev/null
+++ b/tools/perf/util/zlib.c
@@ -0,0 +1,78 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <sys/stat.h>
4#include <sys/mman.h>
5#include <zlib.h>
6
7#include "util/util.h"
8#include "util/debug.h"
9
10
11#define CHUNK_SIZE 16384
12
13int gzip_decompress_to_file(const char *input, int output_fd)
14{
15 int ret = Z_STREAM_ERROR;
16 int input_fd;
17 void *ptr;
18 int len;
19 struct stat stbuf;
20 unsigned char buf[CHUNK_SIZE];
21 z_stream zs = {
22 .zalloc = Z_NULL,
23 .zfree = Z_NULL,
24 .opaque = Z_NULL,
25 .avail_in = 0,
26 .next_in = Z_NULL,
27 };
28
29 input_fd = open(input, O_RDONLY);
30 if (input_fd < 0)
31 return -1;
32
33 if (fstat(input_fd, &stbuf) < 0)
34 goto out_close;
35
36 ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
37 if (ptr == MAP_FAILED)
38 goto out_close;
39
40 if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK)
41 goto out_unmap;
42
43 zs.next_in = ptr;
44 zs.avail_in = stbuf.st_size;
45
46 do {
47 zs.next_out = buf;
48 zs.avail_out = CHUNK_SIZE;
49
50 ret = inflate(&zs, Z_NO_FLUSH);
51 switch (ret) {
52 case Z_NEED_DICT:
53 ret = Z_DATA_ERROR;
54 /* fall through */
55 case Z_DATA_ERROR:
56 case Z_MEM_ERROR:
57 goto out;
58 default:
59 break;
60 }
61
62 len = CHUNK_SIZE - zs.avail_out;
63 if (writen(output_fd, buf, len) != len) {
64 ret = Z_DATA_ERROR;
65 goto out;
66 }
67
68 } while (ret != Z_STREAM_END);
69
70out:
71 inflateEnd(&zs);
72out_unmap:
73 munmap(ptr, stbuf.st_size);
74out_close:
75 close(input_fd);
76
77 return ret == Z_STREAM_END ? 0 : -1;
78}
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
index 7cdcf88659c7..9ea914378985 100644
--- a/tools/power/cpupower/utils/cpupower.c
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -199,7 +199,7 @@ int main(int argc, const char *argv[])
199 } 199 }
200 200
201 get_cpu_info(0, &cpupower_cpu_info); 201 get_cpu_info(0, &cpupower_cpu_info);
202 run_as_root = !getuid(); 202 run_as_root = !geteuid();
203 if (run_as_root) { 203 if (run_as_root) {
204 ret = uname(&uts); 204 ret = uname(&uts);
205 if (!ret && !strcmp(uts.machine, "x86_64") && 205 if (!ret && !strcmp(uts.machine, "x86_64") &&
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c
index 09afe5d87f2b..4e8fe2c7b054 100644
--- a/tools/power/cpupower/utils/helpers/sysfs.c
+++ b/tools/power/cpupower/utils/helpers/sysfs.c
@@ -361,7 +361,7 @@ unsigned int sysfs_get_idlestate_count(unsigned int cpu)
361 361
362 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); 362 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
363 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) 363 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
364 return -ENODEV; 364 return 0;
365 365
366 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); 366 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
367 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) 367 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index bf1398180785..b9cd036f0442 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -684,11 +684,8 @@ sub set_value {
684 } 684 }
685 ${$overrides}{$lvalue} = $prvalue; 685 ${$overrides}{$lvalue} = $prvalue;
686 } 686 }
687 if ($rvalue =~ /^\s*$/) { 687
688 delete $opt{$lvalue}; 688 $opt{$lvalue} = $prvalue;
689 } else {
690 $opt{$lvalue} = $prvalue;
691 }
692} 689}
693 690
694sub set_eval { 691sub set_eval {
@@ -2005,7 +2002,7 @@ sub get_version {
2005 # get the release name 2002 # get the release name
2006 return if ($have_version); 2003 return if ($have_version);
2007 doprint "$make kernelrelease ... "; 2004 doprint "$make kernelrelease ... ";
2008 $version = `$make kernelrelease | tail -1`; 2005 $version = `$make -s kernelrelease | tail -1`;
2009 chomp($version); 2006 chomp($version);
2010 doprint "$version\n"; 2007 doprint "$version\n";
2011 $have_version = 1; 2008 $have_version = 1;
@@ -3571,7 +3568,9 @@ sub test_this_config {
3571 undef %configs; 3568 undef %configs;
3572 assign_configs \%configs, $output_config; 3569 assign_configs \%configs, $output_config;
3573 3570
3574 return $config if (!defined($configs{$config})); 3571 if (!defined($configs{$config}) || $configs{$config} =~ /^#/) {
3572 return $config;
3573 }
3575 3574
3576 doprint "disabling config $config did not change .config\n"; 3575 doprint "disabling config $config did not change .config\n";
3577 3576
@@ -3945,12 +3944,22 @@ for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3945 } 3944 }
3946} 3945}
3947 3946
3947sub option_defined {
3948 my ($option) = @_;
3949
3950 if (defined($opt{$option}) && $opt{$option} !~ /^\s*$/) {
3951 return 1;
3952 }
3953
3954 return 0;
3955}
3956
3948sub __set_test_option { 3957sub __set_test_option {
3949 my ($name, $i) = @_; 3958 my ($name, $i) = @_;
3950 3959
3951 my $option = "$name\[$i\]"; 3960 my $option = "$name\[$i\]";
3952 3961
3953 if (defined($opt{$option})) { 3962 if (option_defined($option)) {
3954 return $opt{$option}; 3963 return $opt{$option};
3955 } 3964 }
3956 3965
@@ -3958,13 +3967,13 @@ sub __set_test_option {
3958 if ($i >= $test && 3967 if ($i >= $test &&
3959 $i < $test + $repeat_tests{$test}) { 3968 $i < $test + $repeat_tests{$test}) {
3960 $option = "$name\[$test\]"; 3969 $option = "$name\[$test\]";
3961 if (defined($opt{$option})) { 3970 if (option_defined($option)) {
3962 return $opt{$option}; 3971 return $opt{$option};
3963 } 3972 }
3964 } 3973 }
3965 } 3974 }
3966 3975
3967 if (defined($opt{$name})) { 3976 if (option_defined($name)) {
3968 return $opt{$name}; 3977 return $opt{$name};
3969 } 3978 }
3970 3979
@@ -4077,8 +4086,14 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
4077 my $installme = ""; 4086 my $installme = "";
4078 $installme = " no_install" if ($no_install); 4087 $installme = " no_install" if ($no_install);
4079 4088
4089 my $name = "";
4090
4091 if (defined($test_name)) {
4092 $name = " ($test_name)";
4093 }
4094
4080 doprint "\n\n"; 4095 doprint "\n\n";
4081 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; 4096 doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n";
4082 4097
4083 if (defined($pre_test)) { 4098 if (defined($pre_test)) {
4084 run_command $pre_test; 4099 run_command $pre_test;
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 45f145c6f843..4e511221a0c1 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -1,20 +1,23 @@
1TARGETS = breakpoints 1TARGETS = breakpoints
2TARGETS += cpu-hotplug 2TARGETS += cpu-hotplug
3TARGETS += efivarfs 3TARGETS += efivarfs
4TARGETS += exec
5TARGETS += firmware
6TARGETS += ftrace
4TARGETS += kcmp 7TARGETS += kcmp
5TARGETS += memfd 8TARGETS += memfd
6TARGETS += memory-hotplug 9TARGETS += memory-hotplug
7TARGETS += mqueue
8TARGETS += mount 10TARGETS += mount
11TARGETS += mqueue
9TARGETS += net 12TARGETS += net
13TARGETS += powerpc
10TARGETS += ptrace 14TARGETS += ptrace
15TARGETS += size
16TARGETS += sysctl
11TARGETS += timers 17TARGETS += timers
12TARGETS += vm
13TARGETS += powerpc
14TARGETS += user 18TARGETS += user
15TARGETS += sysctl 19TARGETS += vm
16TARGETS += firmware 20#Please keep the TARGETS list alphabetically sorted
17TARGETS += ftrace
18 21
19TARGETS_HOTPLUG = cpu-hotplug 22TARGETS_HOTPLUG = cpu-hotplug
20TARGETS_HOTPLUG += memory-hotplug 23TARGETS_HOTPLUG += memory-hotplug
diff --git a/tools/testing/selftests/README.txt b/tools/testing/selftests/README.txt
deleted file mode 100644
index 2660d5ff9179..000000000000
--- a/tools/testing/selftests/README.txt
+++ /dev/null
@@ -1,61 +0,0 @@
1Linux Kernel Selftests
2
3The kernel contains a set of "self tests" under the tools/testing/selftests/
4directory. These are intended to be small unit tests to exercise individual
5code paths in the kernel.
6
7On some systems, hot-plug tests could hang forever waiting for cpu and
8memory to be ready to be offlined. A special hot-plug target is created
9to run full range of hot-plug tests. In default mode, hot-plug tests run
10in safe mode with a limited scope. In limited mode, cpu-hotplug test is
11run on a single cpu as opposed to all hotplug capable cpus, and memory
12hotplug test is run on 2% of hotplug capable memory instead of 10%.
13
14Running the selftests (hotplug tests are run in limited mode)
15=============================================================
16
17To build the tests:
18
19 $ make -C tools/testing/selftests
20
21
22To run the tests:
23
24 $ make -C tools/testing/selftests run_tests
25
26- note that some tests will require root privileges.
27
28To run only tests targeted for a single subsystem: (including
29hotplug targets in limited mode)
30
31 $ make -C tools/testing/selftests TARGETS=cpu-hotplug run_tests
32
33See the top-level tools/testing/selftests/Makefile for the list of all possible
34targets.
35
36Running the full range hotplug selftests
37========================================
38
39To build the tests:
40
41 $ make -C tools/testing/selftests hotplug
42
43To run the tests:
44
45 $ make -C tools/testing/selftests run_hotplug
46
47- note that some tests will require root privileges.
48
49Contributing new tests
50======================
51
52In general, the rules for for selftests are
53
54 * Do as much as you can if you're not root;
55
56 * Don't take too long;
57
58 * Don't break the build on any architecture, and
59
60 * Don't cause the top-level "make run_tests" to fail if your feature is
61 unconfigured.
diff --git a/tools/testing/selftests/breakpoints/breakpoint_test.c b/tools/testing/selftests/breakpoints/breakpoint_test.c
index a0743f3b2b57..120895ab5505 100644
--- a/tools/testing/selftests/breakpoints/breakpoint_test.c
+++ b/tools/testing/selftests/breakpoints/breakpoint_test.c
@@ -17,6 +17,8 @@
17#include <sys/types.h> 17#include <sys/types.h>
18#include <sys/wait.h> 18#include <sys/wait.h>
19 19
20#include "../kselftest.h"
21
20 22
21/* Breakpoint access modes */ 23/* Breakpoint access modes */
22enum { 24enum {
@@ -42,7 +44,7 @@ static void set_breakpoint_addr(void *addr, int n)
42 offsetof(struct user, u_debugreg[n]), addr); 44 offsetof(struct user, u_debugreg[n]), addr);
43 if (ret) { 45 if (ret) {
44 perror("Can't set breakpoint addr\n"); 46 perror("Can't set breakpoint addr\n");
45 exit(-1); 47 ksft_exit_fail();
46 } 48 }
47} 49}
48 50
@@ -105,7 +107,7 @@ static void toggle_breakpoint(int n, int type, int len,
105 offsetof(struct user, u_debugreg[7]), dr7); 107 offsetof(struct user, u_debugreg[7]), dr7);
106 if (ret) { 108 if (ret) {
107 perror("Can't set dr7"); 109 perror("Can't set dr7");
108 exit(-1); 110 ksft_exit_fail();
109 } 111 }
110} 112}
111 113
@@ -275,7 +277,7 @@ static void check_success(const char *msg)
275 msg2 = "Ok"; 277 msg2 = "Ok";
276 if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1)) { 278 if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1)) {
277 perror("Can't poke\n"); 279 perror("Can't poke\n");
278 exit(-1); 280 ksft_exit_fail();
279 } 281 }
280 } 282 }
281 283
@@ -390,5 +392,5 @@ int main(int argc, char **argv)
390 392
391 wait(NULL); 393 wait(NULL);
392 394
393 return 0; 395 return ksft_exit_pass();
394} 396}
diff --git a/tools/testing/selftests/exec/.gitignore b/tools/testing/selftests/exec/.gitignore
new file mode 100644
index 000000000000..64073e050c6a
--- /dev/null
+++ b/tools/testing/selftests/exec/.gitignore
@@ -0,0 +1,9 @@
1subdir*
2script*
3execveat
4execveat.symlink
5execveat.moved
6execveat.path.ephemeral
7execveat.ephemeral
8execveat.denatured
9xxxxxxxx* \ No newline at end of file
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile
new file mode 100644
index 000000000000..66dfc2ce1788
--- /dev/null
+++ b/tools/testing/selftests/exec/Makefile
@@ -0,0 +1,25 @@
1CC = $(CROSS_COMPILE)gcc
2CFLAGS = -Wall
3BINARIES = execveat
4DEPS = execveat.symlink execveat.denatured script subdir
5all: $(BINARIES) $(DEPS)
6
7subdir:
8 mkdir -p $@
9script:
10 echo '#!/bin/sh' > $@
11 echo 'exit $$*' >> $@
12 chmod +x $@
13execveat.symlink: execveat
14 ln -s -f $< $@
15execveat.denatured: execveat
16 cp $< $@
17 chmod -x $@
18%: %.c
19 $(CC) $(CFLAGS) -o $@ $^
20
21run_tests: all
22 ./execveat
23
24clean:
25 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
new file mode 100644
index 000000000000..33a5c06d95ca
--- /dev/null
+++ b/tools/testing/selftests/exec/execveat.c
@@ -0,0 +1,397 @@
1/*
2 * Copyright (c) 2014 Google, Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2
5 *
6 * Selftests for execveat(2).
7 */
8
9#define _GNU_SOURCE /* to get O_PATH, AT_EMPTY_PATH */
10#include <sys/sendfile.h>
11#include <sys/stat.h>
12#include <sys/syscall.h>
13#include <sys/types.h>
14#include <sys/wait.h>
15#include <errno.h>
16#include <fcntl.h>
17#include <limits.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <unistd.h>
22
23static char longpath[2 * PATH_MAX] = "";
24static char *envp[] = { "IN_TEST=yes", NULL, NULL };
25static char *argv[] = { "execveat", "99", NULL };
26
27static int execveat_(int fd, const char *path, char **argv, char **envp,
28 int flags)
29{
30#ifdef __NR_execveat
31 return syscall(__NR_execveat, fd, path, argv, envp, flags);
32#else
33 errno = -ENOSYS;
34 return -1;
35#endif
36}
37
38#define check_execveat_fail(fd, path, flags, errno) \
39 _check_execveat_fail(fd, path, flags, errno, #errno)
40static int _check_execveat_fail(int fd, const char *path, int flags,
41 int expected_errno, const char *errno_str)
42{
43 int rc;
44
45 errno = 0;
46 printf("Check failure of execveat(%d, '%s', %d) with %s... ",
47 fd, path?:"(null)", flags, errno_str);
48 rc = execveat_(fd, path, argv, envp, flags);
49
50 if (rc > 0) {
51 printf("[FAIL] (unexpected success from execveat(2))\n");
52 return 1;
53 }
54 if (errno != expected_errno) {
55 printf("[FAIL] (expected errno %d (%s) not %d (%s)\n",
56 expected_errno, strerror(expected_errno),
57 errno, strerror(errno));
58 return 1;
59 }
60 printf("[OK]\n");
61 return 0;
62}
63
64static int check_execveat_invoked_rc(int fd, const char *path, int flags,
65 int expected_rc)
66{
67 int status;
68 int rc;
69 pid_t child;
70 int pathlen = path ? strlen(path) : 0;
71
72 if (pathlen > 40)
73 printf("Check success of execveat(%d, '%.20s...%s', %d)... ",
74 fd, path, (path + pathlen - 20), flags);
75 else
76 printf("Check success of execveat(%d, '%s', %d)... ",
77 fd, path?:"(null)", flags);
78 child = fork();
79 if (child < 0) {
80 printf("[FAIL] (fork() failed)\n");
81 return 1;
82 }
83 if (child == 0) {
84 /* Child: do execveat(). */
85 rc = execveat_(fd, path, argv, envp, flags);
86 printf("[FAIL]: execveat() failed, rc=%d errno=%d (%s)\n",
87 rc, errno, strerror(errno));
88 exit(1); /* should not reach here */
89 }
90 /* Parent: wait for & check child's exit status. */
91 rc = waitpid(child, &status, 0);
92 if (rc != child) {
93 printf("[FAIL] (waitpid(%d,...) returned %d)\n", child, rc);
94 return 1;
95 }
96 if (!WIFEXITED(status)) {
97 printf("[FAIL] (child %d did not exit cleanly, status=%08x)\n",
98 child, status);
99 return 1;
100 }
101 if (WEXITSTATUS(status) != expected_rc) {
102 printf("[FAIL] (child %d exited with %d not %d)\n",
103 child, WEXITSTATUS(status), expected_rc);
104 return 1;
105 }
106 printf("[OK]\n");
107 return 0;
108}
109
110static int check_execveat(int fd, const char *path, int flags)
111{
112 return check_execveat_invoked_rc(fd, path, flags, 99);
113}
114
115static char *concat(const char *left, const char *right)
116{
117 char *result = malloc(strlen(left) + strlen(right) + 1);
118
119 strcpy(result, left);
120 strcat(result, right);
121 return result;
122}
123
124static int open_or_die(const char *filename, int flags)
125{
126 int fd = open(filename, flags);
127
128 if (fd < 0) {
129 printf("Failed to open '%s'; "
130 "check prerequisites are available\n", filename);
131 exit(1);
132 }
133 return fd;
134}
135
136static void exe_cp(const char *src, const char *dest)
137{
138 int in_fd = open_or_die(src, O_RDONLY);
139 int out_fd = open(dest, O_RDWR|O_CREAT|O_TRUNC, 0755);
140 struct stat info;
141
142 fstat(in_fd, &info);
143 sendfile(out_fd, in_fd, NULL, info.st_size);
144 close(in_fd);
145 close(out_fd);
146}
147
148#define XX_DIR_LEN 200
149static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script)
150{
151 int fail = 0;
152 int ii, count, len;
153 char longname[XX_DIR_LEN + 1];
154 int fd;
155
156 if (*longpath == '\0') {
157 /* Create a filename close to PATH_MAX in length */
158 memset(longname, 'x', XX_DIR_LEN - 1);
159 longname[XX_DIR_LEN - 1] = '/';
160 longname[XX_DIR_LEN] = '\0';
161 count = (PATH_MAX - 3) / XX_DIR_LEN;
162 for (ii = 0; ii < count; ii++) {
163 strcat(longpath, longname);
164 mkdir(longpath, 0755);
165 }
166 len = (PATH_MAX - 3) - (count * XX_DIR_LEN);
167 if (len <= 0)
168 len = 1;
169 memset(longname, 'y', len);
170 longname[len] = '\0';
171 strcat(longpath, longname);
172 }
173 exe_cp(src, longpath);
174
175 /*
176 * Execute as a pre-opened file descriptor, which works whether this is
177 * a script or not (because the interpreter sees a filename like
178 * "/dev/fd/20").
179 */
180 fd = open(longpath, O_RDONLY);
181 if (fd > 0) {
182 printf("Invoke copy of '%s' via filename of length %lu:\n",
183 src, strlen(longpath));
184 fail += check_execveat(fd, "", AT_EMPTY_PATH);
185 } else {
186 printf("Failed to open length %lu filename, errno=%d (%s)\n",
187 strlen(longpath), errno, strerror(errno));
188 fail++;
189 }
190
191 /*
192 * Execute as a long pathname relative to ".". If this is a script,
193 * the interpreter will launch but fail to open the script because its
194 * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX.
195 */
196 if (is_script)
197 fail += check_execveat_invoked_rc(dot_dfd, longpath, 0, 127);
198 else
199 fail += check_execveat(dot_dfd, longpath, 0);
200
201 return fail;
202}
203
204static int run_tests(void)
205{
206 int fail = 0;
207 char *fullname = realpath("execveat", NULL);
208 char *fullname_script = realpath("script", NULL);
209 char *fullname_symlink = concat(fullname, ".symlink");
210 int subdir_dfd = open_or_die("subdir", O_DIRECTORY|O_RDONLY);
211 int subdir_dfd_ephemeral = open_or_die("subdir.ephemeral",
212 O_DIRECTORY|O_RDONLY);
213 int dot_dfd = open_or_die(".", O_DIRECTORY|O_RDONLY);
214 int dot_dfd_path = open_or_die(".", O_DIRECTORY|O_RDONLY|O_PATH);
215 int dot_dfd_cloexec = open_or_die(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC);
216 int fd = open_or_die("execveat", O_RDONLY);
217 int fd_path = open_or_die("execveat", O_RDONLY|O_PATH);
218 int fd_symlink = open_or_die("execveat.symlink", O_RDONLY);
219 int fd_denatured = open_or_die("execveat.denatured", O_RDONLY);
220 int fd_denatured_path = open_or_die("execveat.denatured",
221 O_RDONLY|O_PATH);
222 int fd_script = open_or_die("script", O_RDONLY);
223 int fd_ephemeral = open_or_die("execveat.ephemeral", O_RDONLY);
224 int fd_ephemeral_path = open_or_die("execveat.path.ephemeral",
225 O_RDONLY|O_PATH);
226 int fd_script_ephemeral = open_or_die("script.ephemeral", O_RDONLY);
227 int fd_cloexec = open_or_die("execveat", O_RDONLY|O_CLOEXEC);
228 int fd_script_cloexec = open_or_die("script", O_RDONLY|O_CLOEXEC);
229
230 /* Change file position to confirm it doesn't affect anything */
231 lseek(fd, 10, SEEK_SET);
232
233 /* Normal executable file: */
234 /* dfd + path */
235 fail += check_execveat(subdir_dfd, "../execveat", 0);
236 fail += check_execveat(dot_dfd, "execveat", 0);
237 fail += check_execveat(dot_dfd_path, "execveat", 0);
238 /* absolute path */
239 fail += check_execveat(AT_FDCWD, fullname, 0);
240 /* absolute path with nonsense dfd */
241 fail += check_execveat(99, fullname, 0);
242 /* fd + no path */
243 fail += check_execveat(fd, "", AT_EMPTY_PATH);
244 /* O_CLOEXEC fd + no path */
245 fail += check_execveat(fd_cloexec, "", AT_EMPTY_PATH);
246 /* O_PATH fd */
247 fail += check_execveat(fd_path, "", AT_EMPTY_PATH);
248
249 /* Mess with executable file that's already open: */
250 /* fd + no path to a file that's been renamed */
251 rename("execveat.ephemeral", "execveat.moved");
252 fail += check_execveat(fd_ephemeral, "", AT_EMPTY_PATH);
253 /* fd + no path to a file that's been deleted */
254 unlink("execveat.moved"); /* remove the file now fd open */
255 fail += check_execveat(fd_ephemeral, "", AT_EMPTY_PATH);
256
257 /* Mess with executable file that's already open with O_PATH */
258 /* fd + no path to a file that's been deleted */
259 unlink("execveat.path.ephemeral");
260 fail += check_execveat(fd_ephemeral_path, "", AT_EMPTY_PATH);
261
262 /* Invalid argument failures */
263 fail += check_execveat_fail(fd, "", 0, ENOENT);
264 fail += check_execveat_fail(fd, NULL, AT_EMPTY_PATH, EFAULT);
265
266 /* Symlink to executable file: */
267 /* dfd + path */
268 fail += check_execveat(dot_dfd, "execveat.symlink", 0);
269 fail += check_execveat(dot_dfd_path, "execveat.symlink", 0);
270 /* absolute path */
271 fail += check_execveat(AT_FDCWD, fullname_symlink, 0);
272 /* fd + no path, even with AT_SYMLINK_NOFOLLOW (already followed) */
273 fail += check_execveat(fd_symlink, "", AT_EMPTY_PATH);
274 fail += check_execveat(fd_symlink, "",
275 AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW);
276
277 /* Symlink fails when AT_SYMLINK_NOFOLLOW set: */
278 /* dfd + path */
279 fail += check_execveat_fail(dot_dfd, "execveat.symlink",
280 AT_SYMLINK_NOFOLLOW, ELOOP);
281 fail += check_execveat_fail(dot_dfd_path, "execveat.symlink",
282 AT_SYMLINK_NOFOLLOW, ELOOP);
283 /* absolute path */
284 fail += check_execveat_fail(AT_FDCWD, fullname_symlink,
285 AT_SYMLINK_NOFOLLOW, ELOOP);
286
287 /* Shell script wrapping executable file: */
288 /* dfd + path */
289 fail += check_execveat(subdir_dfd, "../script", 0);
290 fail += check_execveat(dot_dfd, "script", 0);
291 fail += check_execveat(dot_dfd_path, "script", 0);
292 /* absolute path */
293 fail += check_execveat(AT_FDCWD, fullname_script, 0);
294 /* fd + no path */
295 fail += check_execveat(fd_script, "", AT_EMPTY_PATH);
296 fail += check_execveat(fd_script, "",
297 AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW);
298 /* O_CLOEXEC fd fails for a script (as script file inaccessible) */
299 fail += check_execveat_fail(fd_script_cloexec, "", AT_EMPTY_PATH,
300 ENOENT);
301 fail += check_execveat_fail(dot_dfd_cloexec, "script", 0, ENOENT);
302
303 /* Mess with script file that's already open: */
304 /* fd + no path to a file that's been renamed */
305 rename("script.ephemeral", "script.moved");
306 fail += check_execveat(fd_script_ephemeral, "", AT_EMPTY_PATH);
307 /* fd + no path to a file that's been deleted */
308 unlink("script.moved"); /* remove the file while fd open */
309 fail += check_execveat(fd_script_ephemeral, "", AT_EMPTY_PATH);
310
311 /* Rename a subdirectory in the path: */
312 rename("subdir.ephemeral", "subdir.moved");
313 fail += check_execveat(subdir_dfd_ephemeral, "../script", 0);
314 fail += check_execveat(subdir_dfd_ephemeral, "script", 0);
315 /* Remove the subdir and its contents */
316 unlink("subdir.moved/script");
317 unlink("subdir.moved");
318 /* Shell loads via deleted subdir OK because name starts with .. */
319 fail += check_execveat(subdir_dfd_ephemeral, "../script", 0);
320 fail += check_execveat_fail(subdir_dfd_ephemeral, "script", 0, ENOENT);
321
322 /* Flag values other than AT_SYMLINK_NOFOLLOW => EINVAL */
323 fail += check_execveat_fail(dot_dfd, "execveat", 0xFFFF, EINVAL);
324 /* Invalid path => ENOENT */
325 fail += check_execveat_fail(dot_dfd, "no-such-file", 0, ENOENT);
326 fail += check_execveat_fail(dot_dfd_path, "no-such-file", 0, ENOENT);
327 fail += check_execveat_fail(AT_FDCWD, "no-such-file", 0, ENOENT);
328 /* Attempt to execute directory => EACCES */
329 fail += check_execveat_fail(dot_dfd, "", AT_EMPTY_PATH, EACCES);
330 /* Attempt to execute non-executable => EACCES */
331 fail += check_execveat_fail(dot_dfd, "Makefile", 0, EACCES);
332 fail += check_execveat_fail(fd_denatured, "", AT_EMPTY_PATH, EACCES);
333 fail += check_execveat_fail(fd_denatured_path, "", AT_EMPTY_PATH,
334 EACCES);
335 /* Attempt to execute nonsense FD => EBADF */
336 fail += check_execveat_fail(99, "", AT_EMPTY_PATH, EBADF);
337 fail += check_execveat_fail(99, "execveat", 0, EBADF);
338 /* Attempt to execute relative to non-directory => ENOTDIR */
339 fail += check_execveat_fail(fd, "execveat", 0, ENOTDIR);
340
341 fail += check_execveat_pathmax(dot_dfd, "execveat", 0);
342 fail += check_execveat_pathmax(dot_dfd, "script", 1);
343 return fail;
344}
345
346static void prerequisites(void)
347{
348 int fd;
349 const char *script = "#!/bin/sh\nexit $*\n";
350
351 /* Create ephemeral copies of files */
352 exe_cp("execveat", "execveat.ephemeral");
353 exe_cp("execveat", "execveat.path.ephemeral");
354 exe_cp("script", "script.ephemeral");
355 mkdir("subdir.ephemeral", 0755);
356
357 fd = open("subdir.ephemeral/script", O_RDWR|O_CREAT|O_TRUNC, 0755);
358 write(fd, script, strlen(script));
359 close(fd);
360}
361
362int main(int argc, char **argv)
363{
364 int ii;
365 int rc;
366 const char *verbose = getenv("VERBOSE");
367
368 if (argc >= 2) {
369 /* If we are invoked with an argument, don't run tests. */
370 const char *in_test = getenv("IN_TEST");
371
372 if (verbose) {
373 printf(" invoked with:");
374 for (ii = 0; ii < argc; ii++)
375 printf(" [%d]='%s'", ii, argv[ii]);
376 printf("\n");
377 }
378
379 /* Check expected environment transferred. */
380 if (!in_test || strcmp(in_test, "yes") != 0) {
381 printf("[FAIL] (no IN_TEST=yes in env)\n");
382 return 1;
383 }
384
385 /* Use the final argument as an exit code. */
386 rc = atoi(argv[argc - 1]);
387 fflush(stdout);
388 } else {
389 prerequisites();
390 if (verbose)
391 envp[1] = "VERBOSE=1";
392 rc = run_tests();
393 if (rc > 0)
394 printf("%d tests failed\n", rc);
395 }
396 return rc;
397}
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index 515247601df4..da48812ab95e 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -13,6 +13,7 @@ echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
13echo " Options:" 13echo " Options:"
14echo " -h|--help Show help message" 14echo " -h|--help Show help message"
15echo " -k|--keep Keep passed test logs" 15echo " -k|--keep Keep passed test logs"
16echo " -v|--verbose Show all stdout messages in testcases"
16echo " -d|--debug Debug mode (trace all shell commands)" 17echo " -d|--debug Debug mode (trace all shell commands)"
17exit $1 18exit $1
18} 19}
@@ -37,7 +38,7 @@ abspath() {
37} 38}
38 39
39find_testcases() { #directory 40find_testcases() { #directory
40 echo `find $1 -name \*.tc` 41 echo `find $1 -name \*.tc | sort`
41} 42}
42 43
43parse_opts() { # opts 44parse_opts() { # opts
@@ -53,6 +54,10 @@ parse_opts() { # opts
53 KEEP_LOG=1 54 KEEP_LOG=1
54 shift 1 55 shift 1
55 ;; 56 ;;
57 --verbose|-v)
58 VERBOSE=1
59 shift 1
60 ;;
56 --debug|-d) 61 --debug|-d)
57 DEBUG=1 62 DEBUG=1
58 shift 1 63 shift 1
@@ -90,6 +95,7 @@ TEST_CASES=`find_testcases $TEST_DIR`
90LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/ 95LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
91KEEP_LOG=0 96KEEP_LOG=0
92DEBUG=0 97DEBUG=0
98VERBOSE=0
93# Parse command-line options 99# Parse command-line options
94parse_opts $* 100parse_opts $*
95 101
@@ -135,15 +141,12 @@ TOTAL_RESULT=0
135CASENO=0 141CASENO=0
136testcase() { # testfile 142testcase() { # testfile
137 CASENO=$((CASENO+1)) 143 CASENO=$((CASENO+1))
138 prlog -n "[$CASENO]"`grep "^#[ \t]*description:" $1 | cut -f2 -d:` 144 desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:`
145 prlog -n "[$CASENO]$desc"
139} 146}
140 147
141eval_result() { # retval sigval 148eval_result() { # sigval
142 local retval=$2 149 case $1 in
143 if [ $2 -eq 0 ]; then
144 test $1 -ne 0 && retval=$FAIL
145 fi
146 case $retval in
147 $PASS) 150 $PASS)
148 prlog " [PASS]" 151 prlog " [PASS]"
149 PASSED_CASES="$PASSED_CASES $CASENO" 152 PASSED_CASES="$PASSED_CASES $CASENO"
@@ -187,6 +190,9 @@ SIG_RESULT=
187SIG_BASE=36 # Use realtime signals 190SIG_BASE=36 # Use realtime signals
188SIG_PID=$$ 191SIG_PID=$$
189 192
193SIG_FAIL=$((SIG_BASE + FAIL))
194trap 'SIG_RESULT=$FAIL' $SIG_FAIL
195
190SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED)) 196SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED))
191exit_unresolved () { 197exit_unresolved () {
192 kill -s $SIG_UNRESOLVED $SIG_PID 198 kill -s $SIG_UNRESOLVED $SIG_PID
@@ -215,17 +221,25 @@ exit_xfail () {
215} 221}
216trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL 222trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL
217 223
224__run_test() { # testfile
225 # setup PID and PPID, $$ is not updated.
226 (cd $TRACING_DIR; read PID _ < /proc/self/stat ; set -e; set -x; . $1)
227 [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID
228}
229
218# Run one test case 230# Run one test case
219run_test() { # testfile 231run_test() { # testfile
220 local testname=`basename $1` 232 local testname=`basename $1`
221 local testlog=`mktemp --tmpdir=$LOG_DIR ${testname}-XXXXXX.log` 233 local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX`
222 testcase $1 234 testcase $1
223 echo "execute: "$1 > $testlog 235 echo "execute: "$1 > $testlog
224 SIG_RESULT=0 236 SIG_RESULT=0
225 # setup PID and PPID, $$ is not updated. 237 if [ $VERBOSE -ne 0 ]; then
226 (cd $TRACING_DIR; read PID _ < /proc/self/stat ; 238 __run_test $1 2>> $testlog | tee -a $testlog
227 set -e; set -x; . $1) >> $testlog 2>&1 239 else
228 eval_result $? $SIG_RESULT 240 __run_test $1 >> $testlog 2>&1
241 fi
242 eval_result $SIG_RESULT
229 if [ $? -eq 0 ]; then 243 if [ $? -eq 0 ]; then
230 # Remove test log if the test was done as it was expected. 244 # Remove test log if the test was done as it was expected.
231 [ $KEEP_LOG -eq 0 ] && rm $testlog 245 [ $KEEP_LOG -eq 0 ] && rm $testlog
@@ -235,6 +249,9 @@ run_test() { # testfile
235 fi 249 fi
236} 250}
237 251
252# load in the helper functions
253. $TEST_DIR/functions
254
238# Main loop 255# Main loop
239for t in $TEST_CASES; do 256for t in $TEST_CASES; do
240 run_test $t 257 run_test $t
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
new file mode 100644
index 000000000000..fd9c49a13612
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
@@ -0,0 +1,5 @@
1#!/bin/sh
2# description: Basic event tracing check
3test -f available_events -a -f set_event -a -d events
4# check scheduler events are available
5grep -q sched available_events && exit 0 || exit -1 \ No newline at end of file
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-enable.tc b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc
new file mode 100644
index 000000000000..668616d9bb03
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc
@@ -0,0 +1,53 @@
1#!/bin/sh
2# description: event tracing - enable/disable with event level files
3
4do_reset() {
5 echo > set_event
6 clear_trace
7}
8
9fail() { #msg
10 do_reset
11 echo $1
12 exit -1
13}
14
15if [ ! -f set_event -o ! -d events/sched ]; then
16 echo "event tracing is not supported"
17 exit_unsupported
18fi
19
20reset_tracer
21do_reset
22
23echo 'sched:sched_switch' > set_event
24usleep 1
25
26count=`cat trace | grep sched_switch | wc -l`
27if [ $count -eq 0 ]; then
28 fail "sched_switch events are not recorded"
29fi
30
31do_reset
32
33echo 1 > events/sched/sched_switch/enable
34usleep 1
35
36count=`cat trace | grep sched_switch | wc -l`
37if [ $count -eq 0 ]; then
38 fail "sched_switch events are not recorded"
39fi
40
41do_reset
42
43echo 0 > events/sched/sched_switch/enable
44usleep 1
45
46count=`cat trace | grep sched_switch | wc -l`
47if [ $count -ne 0 ]; then
48 fail "sched_switch events should not be recorded"
49fi
50
51do_reset
52
53exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
new file mode 100644
index 000000000000..655c415b6e7f
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
@@ -0,0 +1,53 @@
1#!/bin/sh
2# description: event tracing - enable/disable with subsystem level files
3
4do_reset() {
5 echo > set_event
6 clear_trace
7}
8
9fail() { #msg
10 do_reset
11 echo $1
12 exit -1
13}
14
15if [ ! -f set_event -o ! -d events/sched ]; then
16 echo "event tracing is not supported"
17 exit_unsupported
18fi
19
20reset_tracer
21do_reset
22
23echo 'sched:*' > set_event
24usleep 1
25
26count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
27if [ $count -lt 3 ]; then
28 fail "at least fork, exec and exit events should be recorded"
29fi
30
31do_reset
32
33echo 1 > events/sched/enable
34usleep 1
35
36count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
37if [ $count -lt 3 ]; then
38 fail "at least fork, exec and exit events should be recorded"
39fi
40
41do_reset
42
43echo 0 > events/sched/enable
44usleep 1
45
46count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
47if [ $count -ne 0 ]; then
48 fail "any of scheduler events should not be recorded"
49fi
50
51do_reset
52
53exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
new file mode 100644
index 000000000000..480845774007
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
@@ -0,0 +1,47 @@
1#!/bin/sh
2# description: event tracing - enable/disable with top level files
3
4do_reset() {
5 echo > set_event
6 clear_trace
7}
8
9fail() { #msg
10 do_reset
11 echo $1
12 exit -1
13}
14
15if [ ! -f available_events -o ! -f set_event -o ! -d events ]; then
16 echo "event tracing is not supported"
17 exit_unsupported
18fi
19
20reset_tracer
21do_reset
22
23echo '*:*' > set_event
24count=`cat trace | grep -v ^# | wc -l`
25if [ $count -eq 0 ]; then
26 fail "none of events are recorded"
27fi
28
29do_reset
30
31echo 1 > events/enable
32count=`cat trace | grep -v ^# | wc -l`
33if [ $count -eq 0 ]; then
34 fail "none of events are recorded"
35fi
36
37do_reset
38
39echo 0 > events/enable
40count=`cat trace | grep -v ^# | wc -l`
41if [ $count -ne 0 ]; then
42 fail "any of events should not be recorded"
43fi
44
45do_reset
46
47exit 0
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
new file mode 100644
index 000000000000..c15e018e0220
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
@@ -0,0 +1,89 @@
1#!/bin/sh
2# description: ftrace - function graph filters with stack tracer
3
4# Make sure that function graph filtering works, and is not
5# affected by other tracers enabled (like stack tracer)
6
7if ! grep -q function_graph available_tracers; then
8 echo "no function graph tracer configured"
9 exit_unsupported
10fi
11
12if [ ! -f set_ftrace_filter ]; then
13 echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
14 exit_unsupported
15fi
16
17do_reset() {
18 reset_tracer
19 echo 0 > /proc/sys/kernel/stack_tracer_enabled
20 enable_tracing
21 clear_trace
22 echo > set_ftrace_filter
23}
24
25fail() { # msg
26 do_reset
27 echo $1
28 exit -1
29}
30
31disable_tracing
32clear_trace;
33
34# filter something, schedule is always good
35if ! echo "schedule" > set_ftrace_filter; then
36 # test for powerpc 64
37 if ! echo ".schedule" > set_ftrace_filter; then
38 fail "can not enable schedule filter"
39 fi
40fi
41
42echo function_graph > current_tracer
43
44if [ ! -f stack_trace ]; then
45 echo "Stack tracer not configured"
46 do_reset
47 exit_unsupported;
48fi
49
50echo "Now testing with stack tracer"
51
52echo 1 > /proc/sys/kernel/stack_tracer_enabled
53
54disable_tracing
55clear_trace
56enable_tracing
57sleep 1
58
59count=`cat trace | grep '()' | grep -v schedule | wc -l`
60
61if [ $count -ne 0 ]; then
62 fail "Graph filtering not working with stack tracer?"
63fi
64
65# Make sure we did find something
66count=`cat trace | grep 'schedule()' | wc -l`
67if [ $count -eq 0 ]; then
68 fail "No schedule traces found?"
69fi
70
71echo 0 > /proc/sys/kernel/stack_tracer_enabled
72clear_trace
73sleep 1
74
75
76count=`cat trace | grep '()' | grep -v schedule | wc -l`
77
78if [ $count -ne 0 ]; then
79 fail "Graph filtering not working after stack tracer disabled?"
80fi
81
82count=`cat trace | grep 'schedule()' | wc -l`
83if [ $count -eq 0 ]; then
84 fail "No schedule traces found?"
85fi
86
87do_reset
88
89exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
new file mode 100644
index 000000000000..6af5f6360b18
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
@@ -0,0 +1,52 @@
1#!/bin/sh
2# description: ftrace - function graph filters
3
4# Make sure that function graph filtering works
5
6if ! grep -q function_graph available_tracers; then
7 echo "no function graph tracer configured"
8 exit_unsupported
9fi
10
11do_reset() {
12 reset_tracer
13 enable_tracing
14 clear_trace
15}
16
17fail() { # msg
18 do_reset
19 echo $1
20 exit -1
21}
22
23disable_tracing
24clear_trace
25
26# filter something, schedule is always good
27if ! echo "schedule" > set_ftrace_filter; then
28 # test for powerpc 64
29 if ! echo ".schedule" > set_ftrace_filter; then
30 fail "can not enable schedule filter"
31 fi
32fi
33
34echo function_graph > current_tracer
35enable_tracing
36sleep 1
37# search for functions (has "()" on the line), and make sure
38# that only the schedule function was found
39count=`cat trace | grep '()' | grep -v schedule | wc -l`
40if [ $count -ne 0 ]; then
41 fail "Graph filtering not working by itself?"
42fi
43
44# Make sure we did find something
45count=`cat trace | grep 'schedule()' | wc -l`
46if [ $count -eq 0 ]; then
47 fail "No schedule traces found?"
48fi
49
50do_reset
51
52exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
new file mode 100644
index 000000000000..2e719cb1fc4d
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
@@ -0,0 +1,80 @@
1#!/bin/sh
2# description: ftrace - function profiler with function tracing
3
4# There was a bug after a rewrite of the ftrace infrastructure that
5# caused the function_profiler not to be able to run with the function
6# tracer, because the function_profiler used the function_graph tracer
7# and it was assumed the two could not run simultaneously.
8#
9# There was another related bug where the solution to the first bug
10# broke the way filtering of the function tracer worked.
11#
12# This test triggers those bugs on those kernels.
13#
14# We need function_graph and profiling to to run this test
15if ! grep -q function_graph available_tracers; then
16 echo "no function graph tracer configured"
17 exit_unsupported;
18fi
19
20if [ ! -f set_ftrace_filter ]; then
21 echo "set_ftrace_filter not found? Is dynamic ftrace not set?"
22 exit_unsupported
23fi
24
25if [ ! -f function_profile_enabled ]; then
26 echo "function_profile_enabled not found, function profiling enabled?"
27 exit_unsupported
28fi
29
30fail() { # mesg
31 reset_tracer
32 echo > set_ftrace_filter
33 echo $1
34 exit -1
35}
36
37echo "Testing function tracer with profiler:"
38echo "enable function tracer"
39echo function > current_tracer
40echo "enable profiler"
41echo 1 > function_profile_enabled
42
43sleep 1
44
45echo "Now filter on just schedule"
46echo '*schedule' > set_ftrace_filter
47clear_trace
48
49echo "Now disable function profiler"
50echo 0 > function_profile_enabled
51
52sleep 1
53
54# make sure only schedule functions exist
55
56echo "testing if only schedule is being traced"
57if grep -v -e '^#' -e 'schedule' trace; then
58 fail "more than schedule was found"
59fi
60
61echo "Make sure schedule was traced"
62if ! grep -e 'schedule' trace > /dev/null; then
63 cat trace
64 fail "can not find schedule in trace"
65fi
66
67echo > set_ftrace_filter
68clear_trace
69
70sleep 1
71
72echo "make sure something other than scheduler is being traced"
73if ! grep -v -e '^#' -e 'schedule' trace > /dev/null; then
74 cat trace
75 fail "no other functions besides schedule was found"
76fi
77
78reset_tracer
79
80exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
new file mode 100644
index 000000000000..5d8cd06d920f
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -0,0 +1,16 @@
1
2clear_trace() { # reset trace output
3 echo > trace
4}
5
6disable_tracing() { # stop trace recording
7 echo 0 > tracing_on
8}
9
10enable_tracing() { # start trace recording
11 echo 1 > tracing_on
12}
13
14reset_tracer() { # reset the current tracer
15 echo nop > current_tracer
16}
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
index 1b8b665ab2b3..a5a426211129 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
@@ -9,3 +9,4 @@ echo p:myevent do_fork > kprobe_events
9grep myevent kprobe_events 9grep myevent kprobe_events
10test -d events/kprobes/myevent 10test -d events/kprobes/myevent
11echo > kprobe_events 11echo > kprobe_events
12clear_trace
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
index b55c84003587..d8c7bb6581fe 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
@@ -11,3 +11,4 @@ echo 1 > events/kprobes/myevent/enable
11echo > kprobe_events && exit 1 # this must fail 11echo > kprobe_events && exit 1 # this must fail
12echo 0 > events/kprobes/myevent/enable 12echo 0 > events/kprobes/myevent/enable
13echo > kprobe_events # this must succeed 13echo > kprobe_events # this must succeed
14clear_trace
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
index a603d3f8db7b..c45ee2761354 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
@@ -12,5 +12,6 @@ echo 1 > events/kprobes/testprobe/enable
12( echo "forked") 12( echo "forked")
13echo 0 > events/kprobes/testprobe/enable 13echo 0 > events/kprobes/testprobe/enable
14echo "-:testprobe" >> kprobe_events 14echo "-:testprobe" >> kprobe_events
15clear_trace
15test -d events/kprobes/testprobe && exit 1 || exit 0 16test -d events/kprobes/testprobe && exit 1 || exit 0
16 17
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc
new file mode 100644
index 000000000000..ab41d2b29841
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc
@@ -0,0 +1,55 @@
1#!/bin/sh
2# description: Kprobe dynamic event with function tracer
3
4[ -f kprobe_events ] || exit_unsupported # this is configurable
5grep function available_tracers || exit_unsupported # this is configurable
6
7# prepare
8echo nop > current_tracer
9echo do_fork > set_ftrace_filter
10echo 0 > events/enable
11echo > kprobe_events
12echo 'p:testprobe do_fork' > kprobe_events
13
14# kprobe on / ftrace off
15echo 1 > events/kprobes/testprobe/enable
16echo > trace
17( echo "forked")
18grep testprobe trace
19! grep 'do_fork <-' trace
20
21# kprobe on / ftrace on
22echo function > current_tracer
23echo > trace
24( echo "forked")
25grep testprobe trace
26grep 'do_fork <-' trace
27
28# kprobe off / ftrace on
29echo 0 > events/kprobes/testprobe/enable
30echo > trace
31( echo "forked")
32! grep testprobe trace
33grep 'do_fork <-' trace
34
35# kprobe on / ftrace on
36echo 1 > events/kprobes/testprobe/enable
37echo function > current_tracer
38echo > trace
39( echo "forked")
40grep testprobe trace
41grep 'do_fork <-' trace
42
43# kprobe on / ftrace off
44echo nop > current_tracer
45echo > trace
46( echo "forked")
47grep testprobe trace
48! grep 'do_fork <-' trace
49
50# cleanup
51echo nop > current_tracer
52echo > set_ftrace_filter
53echo 0 > events/kprobes/testprobe/enable
54echo > kprobe_events
55echo > trace
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
index 283c29e7f7c4..31717985acc7 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
@@ -12,4 +12,5 @@ echo 1 > events/kprobes/testprobe2/enable
12( echo "forked") 12( echo "forked")
13echo 0 > events/kprobes/testprobe2/enable 13echo 0 > events/kprobes/testprobe2/enable
14echo '-:testprobe2' >> kprobe_events 14echo '-:testprobe2' >> kprobe_events
15clear_trace
15test -d events/kprobes/testprobe2 && exit 1 || exit 0 16test -d events/kprobes/testprobe2 && exit 1 || exit 0
diff --git a/tools/testing/selftests/ipc/msgque.c b/tools/testing/selftests/ipc/msgque.c
index 552f0810bffb..1b2ce334bb3f 100644
--- a/tools/testing/selftests/ipc/msgque.c
+++ b/tools/testing/selftests/ipc/msgque.c
@@ -5,6 +5,8 @@
5#include <linux/msg.h> 5#include <linux/msg.h>
6#include <fcntl.h> 6#include <fcntl.h>
7 7
8#include "../kselftest.h"
9
8#define MAX_MSG_SIZE 32 10#define MAX_MSG_SIZE 32
9 11
10struct msg1 { 12struct msg1 {
@@ -195,58 +197,58 @@ int main(int argc, char **argv)
195 197
196 if (getuid() != 0) { 198 if (getuid() != 0) {
197 printf("Please run the test as root - Exiting.\n"); 199 printf("Please run the test as root - Exiting.\n");
198 exit(1); 200 return ksft_exit_fail();
199 } 201 }
200 202
201 msgque.key = ftok(argv[0], 822155650); 203 msgque.key = ftok(argv[0], 822155650);
202 if (msgque.key == -1) { 204 if (msgque.key == -1) {
203 printf("Can't make key\n"); 205 printf("Can't make key: %d\n", -errno);
204 return -errno; 206 return ksft_exit_fail();
205 } 207 }
206 208
207 msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666); 209 msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);
208 if (msgque.msq_id == -1) { 210 if (msgque.msq_id == -1) {
209 err = -errno; 211 err = -errno;
210 printf("Can't create queue\n"); 212 printf("Can't create queue: %d\n", err);
211 goto err_out; 213 goto err_out;
212 } 214 }
213 215
214 err = fill_msgque(&msgque); 216 err = fill_msgque(&msgque);
215 if (err) { 217 if (err) {
216 printf("Failed to fill queue\n"); 218 printf("Failed to fill queue: %d\n", err);
217 goto err_destroy; 219 goto err_destroy;
218 } 220 }
219 221
220 err = dump_queue(&msgque); 222 err = dump_queue(&msgque);
221 if (err) { 223 if (err) {
222 printf("Failed to dump queue\n"); 224 printf("Failed to dump queue: %d\n", err);
223 goto err_destroy; 225 goto err_destroy;
224 } 226 }
225 227
226 err = check_and_destroy_queue(&msgque); 228 err = check_and_destroy_queue(&msgque);
227 if (err) { 229 if (err) {
228 printf("Failed to check and destroy queue\n"); 230 printf("Failed to check and destroy queue: %d\n", err);
229 goto err_out; 231 goto err_out;
230 } 232 }
231 233
232 err = restore_queue(&msgque); 234 err = restore_queue(&msgque);
233 if (err) { 235 if (err) {
234 printf("Failed to restore queue\n"); 236 printf("Failed to restore queue: %d\n", err);
235 goto err_destroy; 237 goto err_destroy;
236 } 238 }
237 239
238 err = check_and_destroy_queue(&msgque); 240 err = check_and_destroy_queue(&msgque);
239 if (err) { 241 if (err) {
240 printf("Failed to test queue\n"); 242 printf("Failed to test queue: %d\n", err);
241 goto err_out; 243 goto err_out;
242 } 244 }
243 return 0; 245 return ksft_exit_pass();
244 246
245err_destroy: 247err_destroy:
246 if (msgctl(msgque.msq_id, IPC_RMID, 0)) { 248 if (msgctl(msgque.msq_id, IPC_RMID, 0)) {
247 printf("Failed to destroy queue: %d\n", -errno); 249 printf("Failed to destroy queue: %d\n", -errno);
248 return -errno; 250 return ksft_exit_fail();
249 } 251 }
250err_out: 252err_out:
251 return err; 253 return ksft_exit_fail();
252} 254}
diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile
index 8aabd82db9e4..ff0eefdc6ceb 100644
--- a/tools/testing/selftests/kcmp/Makefile
+++ b/tools/testing/selftests/kcmp/Makefile
@@ -1,25 +1,7 @@
1uname_M := $(shell uname -m 2>/dev/null || echo not) 1CC := $(CROSS_COMPILE)$(CC)
2ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
3ifeq ($(ARCH),i386)
4 ARCH := x86
5 CFLAGS := -DCONFIG_X86_32 -D__i386__
6endif
7ifeq ($(ARCH),x86_64)
8 ARCH := x86
9 CFLAGS := -DCONFIG_X86_64 -D__x86_64__
10endif
11
12CFLAGS += -I../../../../arch/x86/include/generated/
13CFLAGS += -I../../../../include/
14CFLAGS += -I../../../../usr/include/ 2CFLAGS += -I../../../../usr/include/
15CFLAGS += -I../../../../arch/x86/include/
16 3
17all: 4all: kcmp_test
18ifeq ($(ARCH),x86)
19 gcc $(CFLAGS) kcmp_test.c -o kcmp_test
20else
21 echo "Not an x86 target, can't build kcmp selftest"
22endif
23 5
24run_tests: all 6run_tests: all
25 @./kcmp_test || echo "kcmp_test: [FAIL]" 7 @./kcmp_test || echo "kcmp_test: [FAIL]"
diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c
index dbba4084869c..a5a4da856dfe 100644
--- a/tools/testing/selftests/kcmp/kcmp_test.c
+++ b/tools/testing/selftests/kcmp/kcmp_test.c
@@ -17,6 +17,8 @@
17#include <sys/stat.h> 17#include <sys/stat.h>
18#include <sys/wait.h> 18#include <sys/wait.h>
19 19
20#include "../kselftest.h"
21
20static long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2) 22static long sys_kcmp(int pid1, int pid2, int type, int fd1, int fd2)
21{ 23{
22 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2); 24 return syscall(__NR_kcmp, pid1, pid2, type, fd1, fd2);
@@ -34,13 +36,13 @@ int main(int argc, char **argv)
34 36
35 if (fd1 < 0) { 37 if (fd1 < 0) {
36 perror("Can't create file"); 38 perror("Can't create file");
37 exit(1); 39 ksft_exit_fail();
38 } 40 }
39 41
40 pid2 = fork(); 42 pid2 = fork();
41 if (pid2 < 0) { 43 if (pid2 < 0) {
42 perror("fork failed"); 44 perror("fork failed");
43 exit(1); 45 ksft_exit_fail();
44 } 46 }
45 47
46 if (!pid2) { 48 if (!pid2) {
@@ -50,7 +52,7 @@ int main(int argc, char **argv)
50 fd2 = open(kpath, O_RDWR, 0644); 52 fd2 = open(kpath, O_RDWR, 0644);
51 if (fd2 < 0) { 53 if (fd2 < 0) {
52 perror("Can't open file"); 54 perror("Can't open file");
53 exit(1); 55 ksft_exit_fail();
54 } 56 }
55 57
56 /* An example of output and arguments */ 58 /* An example of output and arguments */
@@ -74,23 +76,34 @@ int main(int argc, char **argv)
74 if (ret) { 76 if (ret) {
75 printf("FAIL: 0 expected but %d returned (%s)\n", 77 printf("FAIL: 0 expected but %d returned (%s)\n",
76 ret, strerror(errno)); 78 ret, strerror(errno));
79 ksft_inc_fail_cnt();
77 ret = -1; 80 ret = -1;
78 } else 81 } else {
79 printf("PASS: 0 returned as expected\n"); 82 printf("PASS: 0 returned as expected\n");
83 ksft_inc_pass_cnt();
84 }
80 85
81 /* Compare with self */ 86 /* Compare with self */
82 ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0); 87 ret = sys_kcmp(pid1, pid1, KCMP_VM, 0, 0);
83 if (ret) { 88 if (ret) {
84 printf("FAIL: 0 expected but %d returned (%s)\n", 89 printf("FAIL: 0 expected but %d returned (%s)\n",
85 ret, strerror(errno)); 90 ret, strerror(errno));
91 ksft_inc_fail_cnt();
86 ret = -1; 92 ret = -1;
87 } else 93 } else {
88 printf("PASS: 0 returned as expected\n"); 94 printf("PASS: 0 returned as expected\n");
95 ksft_inc_pass_cnt();
96 }
97
98 ksft_print_cnts();
89 99
90 exit(ret); 100 if (ret)
101 ksft_exit_fail();
102 else
103 ksft_exit_pass();
91 } 104 }
92 105
93 waitpid(pid2, &status, P_ALL); 106 waitpid(pid2, &status, P_ALL);
94 107
95 return 0; 108 return ksft_exit_pass();
96} 109}
diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
new file mode 100644
index 000000000000..572c8888167a
--- /dev/null
+++ b/tools/testing/selftests/kselftest.h
@@ -0,0 +1,62 @@
1/*
2 * kselftest.h: kselftest framework return codes to include from
3 * selftests.
4 *
5 * Copyright (c) 2014 Shuah Khan <shuahkh@osg.samsung.com>
6 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
7 *
8 * This file is released under the GPLv2.
9 */
10#ifndef __KSELFTEST_H
11#define __KSELFTEST_H
12
13#include <stdlib.h>
14#include <unistd.h>
15
16/* counters */
17struct ksft_count {
18 unsigned int ksft_pass;
19 unsigned int ksft_fail;
20 unsigned int ksft_xfail;
21 unsigned int ksft_xpass;
22 unsigned int ksft_xskip;
23};
24
25static struct ksft_count ksft_cnt;
26
27static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; }
28static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; }
29static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; }
30static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; }
31static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; }
32
33static inline void ksft_print_cnts(void)
34{
35 printf("Pass: %d Fail: %d Xfail: %d Xpass: %d, Xskip: %d\n",
36 ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
37 ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
38 ksft_cnt.ksft_xskip);
39}
40
41static inline int ksft_exit_pass(void)
42{
43 exit(0);
44}
45static inline int ksft_exit_fail(void)
46{
47 exit(1);
48}
49static inline int ksft_exit_xfail(void)
50{
51 exit(2);
52}
53static inline int ksft_exit_xpass(void)
54{
55 exit(3);
56}
57static inline int ksft_exit_skip(void)
58{
59 exit(4);
60}
61
62#endif /* __KSELFTEST_H */
diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c
index 1b3ff2fda4d0..517785052f1c 100644
--- a/tools/testing/selftests/mount/unprivileged-remount-test.c
+++ b/tools/testing/selftests/mount/unprivileged-remount-test.c
@@ -6,6 +6,8 @@
6#include <sys/types.h> 6#include <sys/types.h>
7#include <sys/mount.h> 7#include <sys/mount.h>
8#include <sys/wait.h> 8#include <sys/wait.h>
9#include <sys/vfs.h>
10#include <sys/statvfs.h>
9#include <stdlib.h> 11#include <stdlib.h>
10#include <unistd.h> 12#include <unistd.h>
11#include <fcntl.h> 13#include <fcntl.h>
@@ -32,11 +34,14 @@
32# define CLONE_NEWPID 0x20000000 34# define CLONE_NEWPID 0x20000000
33#endif 35#endif
34 36
37#ifndef MS_REC
38# define MS_REC 16384
39#endif
35#ifndef MS_RELATIME 40#ifndef MS_RELATIME
36#define MS_RELATIME (1 << 21) 41# define MS_RELATIME (1 << 21)
37#endif 42#endif
38#ifndef MS_STRICTATIME 43#ifndef MS_STRICTATIME
39#define MS_STRICTATIME (1 << 24) 44# define MS_STRICTATIME (1 << 24)
40#endif 45#endif
41 46
42static void die(char *fmt, ...) 47static void die(char *fmt, ...)
@@ -48,17 +53,14 @@ static void die(char *fmt, ...)
48 exit(EXIT_FAILURE); 53 exit(EXIT_FAILURE);
49} 54}
50 55
51static void write_file(char *filename, char *fmt, ...) 56static void vmaybe_write_file(bool enoent_ok, char *filename, char *fmt, va_list ap)
52{ 57{
53 char buf[4096]; 58 char buf[4096];
54 int fd; 59 int fd;
55 ssize_t written; 60 ssize_t written;
56 int buf_len; 61 int buf_len;
57 va_list ap;
58 62
59 va_start(ap, fmt);
60 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); 63 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
61 va_end(ap);
62 if (buf_len < 0) { 64 if (buf_len < 0) {
63 die("vsnprintf failed: %s\n", 65 die("vsnprintf failed: %s\n",
64 strerror(errno)); 66 strerror(errno));
@@ -69,6 +71,8 @@ static void write_file(char *filename, char *fmt, ...)
69 71
70 fd = open(filename, O_WRONLY); 72 fd = open(filename, O_WRONLY);
71 if (fd < 0) { 73 if (fd < 0) {
74 if ((errno == ENOENT) && enoent_ok)
75 return;
72 die("open of %s failed: %s\n", 76 die("open of %s failed: %s\n",
73 filename, strerror(errno)); 77 filename, strerror(errno));
74 } 78 }
@@ -87,6 +91,65 @@ static void write_file(char *filename, char *fmt, ...)
87 } 91 }
88} 92}
89 93
94static void maybe_write_file(char *filename, char *fmt, ...)
95{
96 va_list ap;
97
98 va_start(ap, fmt);
99 vmaybe_write_file(true, filename, fmt, ap);
100 va_end(ap);
101
102}
103
104static void write_file(char *filename, char *fmt, ...)
105{
106 va_list ap;
107
108 va_start(ap, fmt);
109 vmaybe_write_file(false, filename, fmt, ap);
110 va_end(ap);
111
112}
113
114static int read_mnt_flags(const char *path)
115{
116 int ret;
117 struct statvfs stat;
118 int mnt_flags;
119
120 ret = statvfs(path, &stat);
121 if (ret != 0) {
122 die("statvfs of %s failed: %s\n",
123 path, strerror(errno));
124 }
125 if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | \
126 ST_NOEXEC | ST_NOATIME | ST_NODIRATIME | ST_RELATIME | \
127 ST_SYNCHRONOUS | ST_MANDLOCK)) {
128 die("Unrecognized mount flags\n");
129 }
130 mnt_flags = 0;
131 if (stat.f_flag & ST_RDONLY)
132 mnt_flags |= MS_RDONLY;
133 if (stat.f_flag & ST_NOSUID)
134 mnt_flags |= MS_NOSUID;
135 if (stat.f_flag & ST_NODEV)
136 mnt_flags |= MS_NODEV;
137 if (stat.f_flag & ST_NOEXEC)
138 mnt_flags |= MS_NOEXEC;
139 if (stat.f_flag & ST_NOATIME)
140 mnt_flags |= MS_NOATIME;
141 if (stat.f_flag & ST_NODIRATIME)
142 mnt_flags |= MS_NODIRATIME;
143 if (stat.f_flag & ST_RELATIME)
144 mnt_flags |= MS_RELATIME;
145 if (stat.f_flag & ST_SYNCHRONOUS)
146 mnt_flags |= MS_SYNCHRONOUS;
147 if (stat.f_flag & ST_MANDLOCK)
148 mnt_flags |= ST_MANDLOCK;
149
150 return mnt_flags;
151}
152
90static void create_and_enter_userns(void) 153static void create_and_enter_userns(void)
91{ 154{
92 uid_t uid; 155 uid_t uid;
@@ -100,13 +163,10 @@ static void create_and_enter_userns(void)
100 strerror(errno)); 163 strerror(errno));
101 } 164 }
102 165
166 maybe_write_file("/proc/self/setgroups", "deny");
103 write_file("/proc/self/uid_map", "0 %d 1", uid); 167 write_file("/proc/self/uid_map", "0 %d 1", uid);
104 write_file("/proc/self/gid_map", "0 %d 1", gid); 168 write_file("/proc/self/gid_map", "0 %d 1", gid);
105 169
106 if (setgroups(0, NULL) != 0) {
107 die("setgroups failed: %s\n",
108 strerror(errno));
109 }
110 if (setgid(0) != 0) { 170 if (setgid(0) != 0) {
111 die ("setgid(0) failed %s\n", 171 die ("setgid(0) failed %s\n",
112 strerror(errno)); 172 strerror(errno));
@@ -118,7 +178,8 @@ static void create_and_enter_userns(void)
118} 178}
119 179
120static 180static
121bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) 181bool test_unpriv_remount(const char *fstype, const char *mount_options,
182 int mount_flags, int remount_flags, int invalid_flags)
122{ 183{
123 pid_t child; 184 pid_t child;
124 185
@@ -151,9 +212,11 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags)
151 strerror(errno)); 212 strerror(errno));
152 } 213 }
153 214
154 if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) { 215 if (mount("testing", "/tmp", fstype, mount_flags, mount_options) != 0) {
155 die("mount of /tmp failed: %s\n", 216 die("mount of %s with options '%s' on /tmp failed: %s\n",
156 strerror(errno)); 217 fstype,
218 mount_options? mount_options : "",
219 strerror(errno));
157 } 220 }
158 221
159 create_and_enter_userns(); 222 create_and_enter_userns();
@@ -181,62 +244,127 @@ bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags)
181 244
182static bool test_unpriv_remount_simple(int mount_flags) 245static bool test_unpriv_remount_simple(int mount_flags)
183{ 246{
184 return test_unpriv_remount(mount_flags, mount_flags, 0); 247 return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags, 0);
185} 248}
186 249
187static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags) 250static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags)
188{ 251{
189 return test_unpriv_remount(mount_flags, mount_flags, invalid_flags); 252 return test_unpriv_remount("ramfs", NULL, mount_flags, mount_flags,
253 invalid_flags);
254}
255
256static bool test_priv_mount_unpriv_remount(void)
257{
258 pid_t child;
259 int ret;
260 const char *orig_path = "/dev";
261 const char *dest_path = "/tmp";
262 int orig_mnt_flags, remount_mnt_flags;
263
264 child = fork();
265 if (child == -1) {
266 die("fork failed: %s\n",
267 strerror(errno));
268 }
269 if (child != 0) { /* parent */
270 pid_t pid;
271 int status;
272 pid = waitpid(child, &status, 0);
273 if (pid == -1) {
274 die("waitpid failed: %s\n",
275 strerror(errno));
276 }
277 if (pid != child) {
278 die("waited for %d got %d\n",
279 child, pid);
280 }
281 if (!WIFEXITED(status)) {
282 die("child did not terminate cleanly\n");
283 }
284 return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false;
285 }
286
287 orig_mnt_flags = read_mnt_flags(orig_path);
288
289 create_and_enter_userns();
290 ret = unshare(CLONE_NEWNS);
291 if (ret != 0) {
292 die("unshare(CLONE_NEWNS) failed: %s\n",
293 strerror(errno));
294 }
295
296 ret = mount(orig_path, dest_path, "bind", MS_BIND | MS_REC, NULL);
297 if (ret != 0) {
298 die("recursive bind mount of %s onto %s failed: %s\n",
299 orig_path, dest_path, strerror(errno));
300 }
301
302 ret = mount(dest_path, dest_path, "none",
303 MS_REMOUNT | MS_BIND | orig_mnt_flags , NULL);
304 if (ret != 0) {
305 /* system("cat /proc/self/mounts"); */
306 die("remount of /tmp failed: %s\n",
307 strerror(errno));
308 }
309
310 remount_mnt_flags = read_mnt_flags(dest_path);
311 if (orig_mnt_flags != remount_mnt_flags) {
312 die("Mount flags unexpectedly changed during remount of %s originally mounted on %s\n",
313 dest_path, orig_path);
314 }
315 exit(EXIT_SUCCESS);
190} 316}
191 317
192int main(int argc, char **argv) 318int main(int argc, char **argv)
193{ 319{
194 if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) { 320 if (!test_unpriv_remount_simple(MS_RDONLY)) {
195 die("MS_RDONLY malfunctions\n"); 321 die("MS_RDONLY malfunctions\n");
196 } 322 }
197 if (!test_unpriv_remount_simple(MS_NODEV)) { 323 if (!test_unpriv_remount("devpts", "newinstance", MS_NODEV, MS_NODEV, 0)) {
198 die("MS_NODEV malfunctions\n"); 324 die("MS_NODEV malfunctions\n");
199 } 325 }
200 if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) { 326 if (!test_unpriv_remount_simple(MS_NOSUID)) {
201 die("MS_NOSUID malfunctions\n"); 327 die("MS_NOSUID malfunctions\n");
202 } 328 }
203 if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) { 329 if (!test_unpriv_remount_simple(MS_NOEXEC)) {
204 die("MS_NOEXEC malfunctions\n"); 330 die("MS_NOEXEC malfunctions\n");
205 } 331 }
206 if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV, 332 if (!test_unpriv_remount_atime(MS_RELATIME,
207 MS_NOATIME|MS_NODEV)) 333 MS_NOATIME))
208 { 334 {
209 die("MS_RELATIME malfunctions\n"); 335 die("MS_RELATIME malfunctions\n");
210 } 336 }
211 if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV, 337 if (!test_unpriv_remount_atime(MS_STRICTATIME,
212 MS_NOATIME|MS_NODEV)) 338 MS_NOATIME))
213 { 339 {
214 die("MS_STRICTATIME malfunctions\n"); 340 die("MS_STRICTATIME malfunctions\n");
215 } 341 }
216 if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV, 342 if (!test_unpriv_remount_atime(MS_NOATIME,
217 MS_STRICTATIME|MS_NODEV)) 343 MS_STRICTATIME))
218 { 344 {
219 die("MS_RELATIME malfunctions\n"); 345 die("MS_NOATIME malfunctions\n");
220 } 346 }
221 if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV, 347 if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME,
222 MS_NOATIME|MS_NODEV)) 348 MS_NOATIME))
223 { 349 {
224 die("MS_RELATIME malfunctions\n"); 350 die("MS_RELATIME|MS_NODIRATIME malfunctions\n");
225 } 351 }
226 if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV, 352 if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME,
227 MS_NOATIME|MS_NODEV)) 353 MS_NOATIME))
228 { 354 {
229 die("MS_RELATIME malfunctions\n"); 355 die("MS_STRICTATIME|MS_NODIRATIME malfunctions\n");
230 } 356 }
231 if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV, 357 if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME,
232 MS_STRICTATIME|MS_NODEV)) 358 MS_STRICTATIME))
233 { 359 {
234 die("MS_RELATIME malfunctions\n"); 360 die("MS_NOATIME|MS_DIRATIME malfunctions\n");
235 } 361 }
236 if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV, 362 if (!test_unpriv_remount("ramfs", NULL, MS_STRICTATIME, 0, MS_NOATIME))
237 MS_NOATIME|MS_NODEV))
238 { 363 {
239 die("Default atime malfunctions\n"); 364 die("Default atime malfunctions\n");
240 } 365 }
366 if (!test_priv_mount_unpriv_remount()) {
367 die("Mount flags unexpectedly changed after remount\n");
368 }
241 return EXIT_SUCCESS; 369 return EXIT_SUCCESS;
242} 370}
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index c7493b8f9b0e..62f22cc9941c 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -14,12 +14,6 @@ all: $(NET_PROGS)
14run_tests: all 14run_tests: all
15 @/bin/sh ./run_netsocktests || echo "sockettests: [FAIL]" 15 @/bin/sh ./run_netsocktests || echo "sockettests: [FAIL]"
16 @/bin/sh ./run_afpackettests || echo "afpackettests: [FAIL]" 16 @/bin/sh ./run_afpackettests || echo "afpackettests: [FAIL]"
17 @if /sbin/modprobe test_bpf ; then \ 17 ./test_bpf.sh
18 /sbin/rmmod test_bpf; \
19 echo "test_bpf: ok"; \
20 else \
21 echo "test_bpf: [FAIL]"; \
22 exit 1; \
23 fi
24clean: 18clean:
25 $(RM) $(NET_PROGS) 19 $(RM) $(NET_PROGS)
diff --git a/tools/testing/selftests/net/test_bpf.sh b/tools/testing/selftests/net/test_bpf.sh
new file mode 100755
index 000000000000..8b29796d46aa
--- /dev/null
+++ b/tools/testing/selftests/net/test_bpf.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2# Runs bpf test using test_bpf kernel module
3
4if /sbin/modprobe -q test_bpf ; then
5 /sbin/modprobe -q -r test_bpf;
6 echo "test_bpf: ok";
7else
8 echo "test_bpf: [FAIL]";
9 exit 1;
10fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index f6b2b4771b78..8ca9f21f2efc 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -45,7 +45,7 @@ trap 'rm -rf $T' 0
45touch $T 45touch $T
46 46
47. $KVM/bin/functions.sh 47. $KVM/bin/functions.sh
48. $KVPATH/ver_functions.sh 48. $CONFIGFRAG/ver_functions.sh
49 49
50config_template=${1} 50config_template=${1}
51config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'` 51config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'`
@@ -168,8 +168,8 @@ then
168 touch $resdir/buildonly 168 touch $resdir/buildonly
169 exit 0 169 exit 0
170fi 170fi
171echo $QEMU $qemu_args -m 512 -kernel $builddir/$BOOT_IMAGE -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd 171echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
172( $QEMU $qemu_args -m 512 -kernel $builddir/$BOOT_IMAGE -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) & 172( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) &
173qemu_pid=$! 173qemu_pid=$!
174commandcompleted=0 174commandcompleted=0
175echo Monitoring qemu job at pid $qemu_pid 175echo Monitoring qemu job at pid $qemu_pid
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index e527dc952eb0..368d64ac779e 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -47,7 +47,6 @@ resdir=""
47configs="" 47configs=""
48cpus=0 48cpus=0
49ds=`date +%Y.%m.%d-%H:%M:%S` 49ds=`date +%Y.%m.%d-%H:%M:%S`
50kversion=""
51 50
52. functions.sh 51. functions.sh
53 52
@@ -64,7 +63,6 @@ usage () {
64 echo " --duration minutes" 63 echo " --duration minutes"
65 echo " --interactive" 64 echo " --interactive"
66 echo " --kmake-arg kernel-make-arguments" 65 echo " --kmake-arg kernel-make-arguments"
67 echo " --kversion vN.NN"
68 echo " --mac nn:nn:nn:nn:nn:nn" 66 echo " --mac nn:nn:nn:nn:nn:nn"
69 echo " --no-initrd" 67 echo " --no-initrd"
70 echo " --qemu-args qemu-system-..." 68 echo " --qemu-args qemu-system-..."
@@ -128,11 +126,6 @@ do
128 TORTURE_KMAKE_ARG="$2" 126 TORTURE_KMAKE_ARG="$2"
129 shift 127 shift
130 ;; 128 ;;
131 --kversion)
132 checkarg --kversion "(kernel version)" $# "$2" '^v[0-9.]*$' '^error'
133 kversion=$2
134 shift
135 ;;
136 --mac) 129 --mac)
137 checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error 130 checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error
138 TORTURE_QEMU_MAC=$2 131 TORTURE_QEMU_MAC=$2
@@ -170,11 +163,10 @@ do
170done 163done
171 164
172CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG 165CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG
173KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
174 166
175if test -z "$configs" 167if test -z "$configs"
176then 168then
177 configs="`cat $CONFIGFRAG/$kversion/CFLIST`" 169 configs="`cat $CONFIGFRAG/CFLIST`"
178fi 170fi
179 171
180if test -z "$resdir" 172if test -z "$resdir"
@@ -186,10 +178,10 @@ fi
186touch $T/cfgcpu 178touch $T/cfgcpu
187for CF in $configs 179for CF in $configs
188do 180do
189 if test -f "$CONFIGFRAG/$kversion/$CF" 181 if test -f "$CONFIGFRAG/$CF"
190 then 182 then
191 cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` 183 cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$CF`
192 cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$kversion/$CF" "$cpu_count"` 184 cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF" "$cpu_count"`
193 echo $CF $cpu_count >> $T/cfgcpu 185 echo $CF $cpu_count >> $T/cfgcpu
194 else 186 else
195 echo "The --configs file $CF does not exist, terminating." 187 echo "The --configs file $CF does not exist, terminating."
@@ -252,7 +244,6 @@ END {
252cat << ___EOF___ > $T/script 244cat << ___EOF___ > $T/script
253CONFIGFRAG="$CONFIGFRAG"; export CONFIGFRAG 245CONFIGFRAG="$CONFIGFRAG"; export CONFIGFRAG
254KVM="$KVM"; export KVM 246KVM="$KVM"; export KVM
255KVPATH="$KVPATH"; export KVPATH
256PATH="$PATH"; export PATH 247PATH="$PATH"; export PATH
257TORTURE_BOOT_IMAGE="$TORTURE_BOOT_IMAGE"; export TORTURE_BOOT_IMAGE 248TORTURE_BOOT_IMAGE="$TORTURE_BOOT_IMAGE"; export TORTURE_BOOT_IMAGE
258TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY 249TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY
@@ -285,7 +276,7 @@ then
285fi 276fi
286___EOF___ 277___EOF___
287awk < $T/cfgcpu.pack \ 278awk < $T/cfgcpu.pack \
288 -v CONFIGDIR="$CONFIGFRAG/$kversion/" \ 279 -v CONFIGDIR="$CONFIGFRAG/" \
289 -v KVM="$KVM" \ 280 -v KVM="$KVM" \
290 -v ncpus=$cpus \ 281 -v ncpus=$cpus \
291 -v rd=$resdir/$ds/ \ 282 -v rd=$resdir/$ds/ \
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
index f4feaee40776..36e41df3d27a 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TINY02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
@@ -7,6 +7,8 @@ CONFIG_HZ_PERIODIC=y
7CONFIG_NO_HZ_IDLE=n 7CONFIG_NO_HZ_IDLE=n
8CONFIG_NO_HZ_FULL=n 8CONFIG_NO_HZ_FULL=n
9CONFIG_RCU_TRACE=y 9CONFIG_RCU_TRACE=y
10CONFIG_PROVE_LOCKING=y
11CONFIG_PROVE_RCU=y
10CONFIG_DEBUG_LOCK_ALLOC=y 12CONFIG_DEBUG_LOCK_ALLOC=y
11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 13CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
12CONFIG_PREEMPT_COUNT=y 14CONFIG_PREEMPT_COUNT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot b/tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot
new file mode 100644
index 000000000000..0f0802730014
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot
@@ -0,0 +1,2 @@
1rcupdate.rcu_self_test=1
2rcupdate.rcu_self_test_bh=1
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
index 38e3895759dd..f8a10a7500c6 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
@@ -2,7 +2,7 @@ CONFIG_SMP=y
2CONFIG_PREEMPT_NONE=n 2CONFIG_PREEMPT_NONE=n
3CONFIG_PREEMPT_VOLUNTARY=n 3CONFIG_PREEMPT_VOLUNTARY=n
4CONFIG_PREEMPT=y 4CONFIG_PREEMPT=y
5#CHECK#CONFIG_TREE_PREEMPT_RCU=y 5#CHECK#CONFIG_PREEMPT_RCU=y
6CONFIG_HZ_PERIODIC=n 6CONFIG_HZ_PERIODIC=n
7CONFIG_NO_HZ_IDLE=y 7CONFIG_NO_HZ_IDLE=y
8CONFIG_NO_HZ_FULL=n 8CONFIG_NO_HZ_FULL=n
@@ -14,6 +14,5 @@ CONFIG_RCU_NOCB_CPU=y
14CONFIG_RCU_NOCB_CPU_ZERO=y 14CONFIG_RCU_NOCB_CPU_ZERO=y
15CONFIG_DEBUG_LOCK_ALLOC=n 15CONFIG_DEBUG_LOCK_ALLOC=n
16CONFIG_RCU_CPU_STALL_INFO=n 16CONFIG_RCU_CPU_STALL_INFO=n
17CONFIG_RCU_CPU_STALL_VERBOSE=n
18CONFIG_RCU_BOOST=n 17CONFIG_RCU_BOOST=n
19CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 18CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
index ea119ba2f7d4..629122fb8b4a 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8
3CONFIG_PREEMPT_NONE=n 3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n 4CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y 5CONFIG_PREEMPT=y
6#CHECK#CONFIG_TREE_PREEMPT_RCU=y 6#CHECK#CONFIG_PREEMPT_RCU=y
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y 8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n 9CONFIG_NO_HZ_FULL=n
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=y 19CONFIG_DEBUG_LOCK_ALLOC=y
20CONFIG_PROVE_LOCKING=n 20CONFIG_PROVE_LOCKING=n
21CONFIG_RCU_CPU_STALL_INFO=n 21CONFIG_RCU_CPU_STALL_INFO=n
22CONFIG_RCU_CPU_STALL_VERBOSE=y
23CONFIG_RCU_BOOST=n 22CONFIG_RCU_BOOST=n
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T
index 19cf9485f48a..a25de47888a4 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02-T
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8
3CONFIG_PREEMPT_NONE=n 3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n 4CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y 5CONFIG_PREEMPT=y
6#CHECK#CONFIG_TREE_PREEMPT_RCU=y 6#CHECK#CONFIG_PREEMPT_RCU=y
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y 8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n 9CONFIG_NO_HZ_FULL=n
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=y 19CONFIG_DEBUG_LOCK_ALLOC=y
20CONFIG_PROVE_LOCKING=n 20CONFIG_PROVE_LOCKING=n
21CONFIG_RCU_CPU_STALL_INFO=n 21CONFIG_RCU_CPU_STALL_INFO=n
22CONFIG_RCU_CPU_STALL_VERBOSE=y
23CONFIG_RCU_BOOST=n 22CONFIG_RCU_BOOST=n
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
index f4567fb3e332..53f24e0a0ab6 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8
3CONFIG_PREEMPT_NONE=n 3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n 4CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y 5CONFIG_PREEMPT=y
6#CHECK#CONFIG_TREE_PREEMPT_RCU=y 6#CHECK#CONFIG_PREEMPT_RCU=y
7CONFIG_HZ_PERIODIC=y 7CONFIG_HZ_PERIODIC=y
8CONFIG_NO_HZ_IDLE=n 8CONFIG_NO_HZ_IDLE=n
9CONFIG_NO_HZ_FULL=n 9CONFIG_NO_HZ_FULL=n
@@ -15,7 +15,6 @@ CONFIG_RCU_FANOUT_EXACT=n
15CONFIG_RCU_NOCB_CPU=n 15CONFIG_RCU_NOCB_CPU=n
16CONFIG_DEBUG_LOCK_ALLOC=n 16CONFIG_DEBUG_LOCK_ALLOC=n
17CONFIG_RCU_CPU_STALL_INFO=n 17CONFIG_RCU_CPU_STALL_INFO=n
18CONFIG_RCU_CPU_STALL_VERBOSE=n
19CONFIG_RCU_BOOST=y 18CONFIG_RCU_BOOST=y
20CONFIG_RCU_BOOST_PRIO=2 19CONFIG_RCU_KTHREAD_PRIO=2
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 0a262fbb0c12..0f84db35b36d 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -19,5 +19,4 @@ CONFIG_RCU_FANOUT_EXACT=n
19CONFIG_RCU_NOCB_CPU=n 19CONFIG_RCU_NOCB_CPU=n
20CONFIG_DEBUG_LOCK_ALLOC=n 20CONFIG_DEBUG_LOCK_ALLOC=n
21CONFIG_RCU_CPU_STALL_INFO=y 21CONFIG_RCU_CPU_STALL_INFO=y
22CONFIG_RCU_CPU_STALL_VERBOSE=y
23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
index 3a06b97e9a73..212e3bfd2b2a 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE05
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
@@ -19,5 +19,4 @@ CONFIG_DEBUG_LOCK_ALLOC=y
19CONFIG_PROVE_LOCKING=y 19CONFIG_PROVE_LOCKING=y
20CONFIG_PROVE_RCU=y 20CONFIG_PROVE_RCU=y
21CONFIG_RCU_CPU_STALL_INFO=n 21CONFIG_RCU_CPU_STALL_INFO=n
22CONFIG_RCU_CPU_STALL_VERBOSE=n
23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
index 3b42b8b033cd..15b3e1a86f74 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
@@ -1 +1,2 @@
1rcutorture.torture_type=sched 1rcutorture.torture_type=sched
2rcupdate.rcu_self_test_sched=1
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
index 8f084cca91bf..7eee63b44218 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE06
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
@@ -20,5 +20,4 @@ CONFIG_DEBUG_LOCK_ALLOC=y
20CONFIG_PROVE_LOCKING=y 20CONFIG_PROVE_LOCKING=y
21CONFIG_PROVE_RCU=y 21CONFIG_PROVE_RCU=y
22CONFIG_RCU_CPU_STALL_INFO=n 22CONFIG_RCU_CPU_STALL_INFO=n
23CONFIG_RCU_CPU_STALL_VERBOSE=n
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=y 23CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot
new file mode 100644
index 000000000000..da9a03a398db
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot
@@ -0,0 +1,3 @@
1rcupdate.rcu_self_test=1
2rcupdate.rcu_self_test_bh=1
3rcupdate.rcu_self_test_sched=1
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index 8f1017666aa7..92a97fa97dec 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -19,5 +19,4 @@ CONFIG_RCU_FANOUT_EXACT=n
19CONFIG_RCU_NOCB_CPU=n 19CONFIG_RCU_NOCB_CPU=n
20CONFIG_DEBUG_LOCK_ALLOC=n 20CONFIG_DEBUG_LOCK_ALLOC=n
21CONFIG_RCU_CPU_STALL_INFO=y 21CONFIG_RCU_CPU_STALL_INFO=y
22CONFIG_RCU_CPU_STALL_VERBOSE=n
23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08 b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
index 69a2e255bf98..5812027d6f9f 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=16
3CONFIG_PREEMPT_NONE=n 3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n 4CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y 5CONFIG_PREEMPT=y
6#CHECK#CONFIG_TREE_PREEMPT_RCU=y 6#CHECK#CONFIG_PREEMPT_RCU=y
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y 8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n 9CONFIG_NO_HZ_FULL=n
@@ -18,7 +18,8 @@ CONFIG_RCU_FANOUT_LEAF=2
18CONFIG_RCU_NOCB_CPU=y 18CONFIG_RCU_NOCB_CPU=y
19CONFIG_RCU_NOCB_CPU_ALL=y 19CONFIG_RCU_NOCB_CPU_ALL=y
20CONFIG_DEBUG_LOCK_ALLOC=n 20CONFIG_DEBUG_LOCK_ALLOC=n
21CONFIG_PROVE_LOCKING=y
22CONFIG_PROVE_RCU=y
21CONFIG_RCU_CPU_STALL_INFO=n 23CONFIG_RCU_CPU_STALL_INFO=n
22CONFIG_RCU_CPU_STALL_VERBOSE=n
23CONFIG_RCU_BOOST=n 24CONFIG_RCU_BOOST=n
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 25CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
index a0f32fb8f17e..3eaeccacb083 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=16
3CONFIG_PREEMPT_NONE=n 3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n 4CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y 5CONFIG_PREEMPT=y
6#CHECK#CONFIG_TREE_PREEMPT_RCU=y 6#CHECK#CONFIG_PREEMPT_RCU=y
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y 8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n 9CONFIG_NO_HZ_FULL=n
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=y
19CONFIG_RCU_NOCB_CPU_ALL=y 19CONFIG_RCU_NOCB_CPU_ALL=y
20CONFIG_DEBUG_LOCK_ALLOC=n 20CONFIG_DEBUG_LOCK_ALLOC=n
21CONFIG_RCU_CPU_STALL_INFO=n 21CONFIG_RCU_CPU_STALL_INFO=n
22CONFIG_RCU_CPU_STALL_VERBOSE=n
23CONFIG_RCU_BOOST=n 22CONFIG_RCU_BOOST=n
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot
index 3b42b8b033cd..2561daf605ad 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot
@@ -1 +1,3 @@
1rcutorture.torture_type=sched 1rcutorture.torture_type=sched
2rcupdate.rcu_self_test=1
3rcupdate.rcu_self_test_sched=1
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE09 b/tools/testing/selftests/rcutorture/configs/rcu/TREE09
index b7a62a540ad1..6076b36f6c0b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE09
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE09
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=1
3CONFIG_PREEMPT_NONE=n 3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n 4CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y 5CONFIG_PREEMPT=y
6#CHECK#CONFIG_TREE_PREEMPT_RCU=y 6#CHECK#CONFIG_PREEMPT_RCU=y
7CONFIG_HZ_PERIODIC=n 7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y 8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n 9CONFIG_NO_HZ_FULL=n
@@ -14,6 +14,5 @@ CONFIG_HIBERNATION=n
14CONFIG_RCU_NOCB_CPU=n 14CONFIG_RCU_NOCB_CPU=n
15CONFIG_DEBUG_LOCK_ALLOC=n 15CONFIG_DEBUG_LOCK_ALLOC=n
16CONFIG_RCU_CPU_STALL_INFO=n 16CONFIG_RCU_CPU_STALL_INFO=n
17CONFIG_RCU_CPU_STALL_VERBOSE=n
18CONFIG_RCU_BOOST=n 17CONFIG_RCU_BOOST=n
19CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 18CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST
deleted file mode 100644
index 18223947bbcb..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST
+++ /dev/null
@@ -1,14 +0,0 @@
1P1-S-T-NH-SD-SMP-HP
2P2-2-t-nh-sd-SMP-hp
3P3-3-T-nh-SD-SMP-hp
4P4-A-t-NH-sd-SMP-HP
5P5-U-T-NH-sd-SMP-hp
6N1-S-T-NH-SD-SMP-HP
7N2-2-t-nh-sd-SMP-hp
8N3-3-T-nh-SD-SMP-hp
9N4-A-t-NH-sd-SMP-HP
10N5-U-T-NH-sd-SMP-hp
11PT1-nh
12PT2-NH
13NT1-nh
14NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644
index d3ef873eb6e7..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,18 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=8
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=y
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=n
11#CHECK#CONFIG_TREE_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_SYSFS_DEPRECATED_V2=y
15CONFIG_IKCONFIG=y
16CONFIG_IKCONFIG_PROC=y
17CONFIG_PRINTK_TIME=y
18
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644
index 02e418572b1b..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=4
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=y
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=n
13#CHECK#CONFIG_TREE_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644
index b3100f69c8cf..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=y
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=n
13#CHECK#CONFIG_TREE_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_PROVE_LOCKING=y
17CONFIG_PROVE_RCU=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644
index c56b44530725..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP
+++ /dev/null
@@ -1,18 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=6
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=y
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=n
11#CHECK#CONFIG_TREE_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_SYSFS_DEPRECATED_V2=y
15CONFIG_IKCONFIG=y
16CONFIG_IKCONFIG_PROC=y
17CONFIG_PRINTK_TIME=y
18
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644
index 90d924fea9e9..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_DEBUG_KERNEL=y
3CONFIG_RCU_CPU_STALL_INFO=y
4CONFIG_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=6
7CONFIG_NR_CPUS=8
8CONFIG_RCU_FANOUT_EXACT=y
9CONFIG_HOTPLUG_CPU=n
10CONFIG_SUSPEND=n
11CONFIG_HIBERNATION=n
12CONFIG_PREEMPT_NONE=y
13CONFIG_PREEMPT_VOLUNTARY=n
14CONFIG_PREEMPT=n
15#CHECK#CONFIG_TREE_RCU=y
16CONFIG_RCU_TORTURE_TEST=m
17CONFIG_MODULE_UNLOAD=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh
deleted file mode 100644
index 023f312a931c..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh
+++ /dev/null
@@ -1,23 +0,0 @@
1#CHECK#CONFIG_TINY_RCU=y
2CONFIG_RCU_TRACE=y
3CONFIG_RCU_TORTURE_TEST=m
4CONFIG_MODULE_UNLOAD=y
5CONFIG_SUSPEND=n
6CONFIG_HIBERNATION=n
7#
8CONFIG_SMP=n
9#
10CONFIG_HOTPLUG_CPU=n
11#
12CONFIG_NO_HZ=n
13#
14CONFIG_PREEMPT_NONE=y
15CONFIG_PREEMPT_VOLUNTARY=n
16CONFIG_PREEMPT=n
17CONFIG_PROVE_LOCKING=y
18CONFIG_PROVE_RCU=y
19CONFIG_SYSFS_DEPRECATED_V2=y
20CONFIG_IKCONFIG=y
21CONFIG_IKCONFIG_PROC=y
22CONFIG_PRINTK_TIME=y
23
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH
deleted file mode 100644
index 6fd0235dae73..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH
+++ /dev/null
@@ -1,20 +0,0 @@
1#CHECK#CONFIG_TINY_RCU=y
2CONFIG_RCU_TORTURE_TEST=m
3CONFIG_MODULE_UNLOAD=y
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6#
7CONFIG_SMP=n
8#
9CONFIG_HOTPLUG_CPU=n
10#
11CONFIG_NO_HZ=y
12#
13CONFIG_PREEMPT_NONE=y
14CONFIG_PREEMPT_VOLUNTARY=n
15CONFIG_PREEMPT=n
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644
index f72402d7c13d..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,19 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_CPU_STALL_INFO=y
3CONFIG_NO_HZ=y
4CONFIG_SMP=y
5CONFIG_RCU_FANOUT=8
6CONFIG_NR_CPUS=8
7CONFIG_RCU_FANOUT_EXACT=n
8CONFIG_HOTPLUG_CPU=y
9CONFIG_PREEMPT_NONE=n
10CONFIG_PREEMPT_VOLUNTARY=n
11CONFIG_PREEMPT=y
12#CHECK#CONFIG_TREE_PREEMPT_RCU=y
13CONFIG_RCU_TORTURE_TEST=m
14CONFIG_MODULE_UNLOAD=y
15CONFIG_SYSFS_DEPRECATED_V2=y
16CONFIG_IKCONFIG=y
17CONFIG_IKCONFIG_PROC=y
18CONFIG_PRINTK_TIME=y
19
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644
index 0f3b667d2a9f..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=4
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644
index b035e141bf2a..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644
index 3ccf6a9447f5..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=6
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=n
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=y
11#CHECK#CONFIG_TREE_PREEMPT_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_RT_MUTEXES=y
15CONFIG_RCU_BOOST=y
16CONFIG_RCU_BOOST_PRIO=2
17CONFIG_PROVE_LOCKING=y
18CONFIG_PROVE_RCU=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644
index a55c00877fe4..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp
+++ /dev/null
@@ -1,27 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_CPU_STALL_INFO=y
3CONFIG_NO_HZ=y
4CONFIG_SMP=y
5CONFIG_RCU_FANOUT=6
6CONFIG_NR_CPUS=8
7CONFIG_RCU_FANOUT_EXACT=y
8CONFIG_HOTPLUG_CPU=n
9CONFIG_SUSPEND=n
10CONFIG_HIBERNATION=n
11CONFIG_PREEMPT_NONE=n
12CONFIG_PREEMPT_VOLUNTARY=n
13CONFIG_PREEMPT=y
14#CHECK#CONFIG_TREE_PREEMPT_RCU=y
15CONFIG_DEBUG_KERNEL=y
16CONFIG_DEBUG_OBJECTS=y
17CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
18CONFIG_RT_MUTEXES=y
19CONFIG_RCU_BOOST=y
20CONFIG_RCU_BOOST_PRIO=2
21CONFIG_RCU_TORTURE_TEST=m
22CONFIG_MODULE_UNLOAD=y
23CONFIG_SYSFS_DEPRECATED_V2=y
24CONFIG_IKCONFIG=y
25CONFIG_IKCONFIG_PROC=y
26CONFIG_PRINTK_TIME=y
27
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh
deleted file mode 100644
index e3361c3894a1..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh
+++ /dev/null
@@ -1,23 +0,0 @@
1CONFIG_TINY_PREEMPT_RCU=y
2CONFIG_RCU_BOOST=y
3CONFIG_RCU_BOOST_PRIO=2
4CONFIG_RCU_TRACE=y
5CONFIG_RCU_TORTURE_TEST=m
6CONFIG_MODULE_UNLOAD=y
7CONFIG_SUSPEND=n
8CONFIG_HIBERNATION=n
9#
10CONFIG_SMP=n
11#
12CONFIG_HOTPLUG_CPU=n
13#
14CONFIG_NO_HZ=n
15#
16CONFIG_PREEMPT_NONE=n
17CONFIG_PREEMPT_VOLUNTARY=n
18CONFIG_PREEMPT=y
19CONFIG_SYSFS_DEPRECATED_V2=y
20CONFIG_IKCONFIG=y
21CONFIG_IKCONFIG_PROC=y
22CONFIG_PRINTK_TIME=y
23
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH
deleted file mode 100644
index 64abfc3b4d94..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_TINY_PREEMPT_RCU=y
2CONFIG_RCU_TORTURE_TEST=m
3CONFIG_MODULE_UNLOAD=y
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6#
7CONFIG_SMP=n
8#
9CONFIG_HOTPLUG_CPU=n
10#
11CONFIG_NO_HZ=y
12#
13CONFIG_PREEMPT_NONE=n
14CONFIG_PREEMPT_VOLUNTARY=n
15CONFIG_PREEMPT=y
16CONFIG_PROVE_LOCKING=y
17CONFIG_PROVE_RCU=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
deleted file mode 100644
index 5ace37a89780..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
+++ /dev/null
@@ -1,33 +0,0 @@
1#!/bin/bash
2#
3# Kernel-version-dependent shell functions for the rest of the scripts.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, you can access it online at
17# http://www.gnu.org/licenses/gpl-2.0.html.
18#
19# Copyright (C) IBM Corporation, 2013
20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22
23# per_version_boot_params bootparam-string config-file seconds
24#
25# Adds per-version torture-module parameters to kernels supporting them.
26# Which old kernels do not.
27per_version_boot_params () {
28 echo rcutorture.stat_interval=15 \
29 rcutorture.shutdown_secs=$3 \
30 rcutorture.rcutorture_runnable=1 \
31 rcutorture.test_no_idle_hz=1 \
32 rcutorture.verbose=1
33}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST
deleted file mode 100644
index da4cbc668f2a..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST
+++ /dev/null
@@ -1,17 +0,0 @@
1sysidleY.2013.06.19a
2sysidleN.2013.06.19a
3P1-S-T-NH-SD-SMP-HP
4P2-2-t-nh-sd-SMP-hp
5P3-3-T-nh-SD-SMP-hp
6P4-A-t-NH-sd-SMP-HP
7P5-U-T-NH-sd-SMP-hp
8P6---t-nh-SD-smp-hp
9N1-S-T-NH-SD-SMP-HP
10N2-2-t-nh-sd-SMP-hp
11N3-3-T-nh-SD-SMP-hp
12N4-A-t-NH-sd-SMP-HP
13N5-U-T-NH-sd-SMP-hp
14PT1-nh
15PT2-NH
16NT1-nh
17NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644
index d81e11d280aa..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,19 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_FAST_NO_HZ=y
3CONFIG_NO_HZ=y
4CONFIG_SMP=y
5CONFIG_RCU_FANOUT=8
6CONFIG_NR_CPUS=8
7CONFIG_RCU_FANOUT_EXACT=n
8CONFIG_HOTPLUG_CPU=y
9CONFIG_PREEMPT_NONE=y
10CONFIG_PREEMPT_VOLUNTARY=n
11CONFIG_PREEMPT=n
12#CHECK#CONFIG_TREE_RCU=y
13CONFIG_RCU_TORTURE_TEST=m
14CONFIG_MODULE_UNLOAD=y
15CONFIG_SYSFS_DEPRECATED_V2=y
16CONFIG_IKCONFIG=y
17CONFIG_IKCONFIG_PROC=y
18CONFIG_PRINTK_TIME=y
19
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644
index 02e418572b1b..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=4
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=y
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=n
13#CHECK#CONFIG_TREE_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644
index b3100f69c8cf..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=y
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=n
13#CHECK#CONFIG_TREE_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_PROVE_LOCKING=y
17CONFIG_PROVE_RCU=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644
index c56b44530725..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP
+++ /dev/null
@@ -1,18 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=6
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=y
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=n
11#CHECK#CONFIG_TREE_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_SYSFS_DEPRECATED_V2=y
15CONFIG_IKCONFIG=y
16CONFIG_IKCONFIG_PROC=y
17CONFIG_PRINTK_TIME=y
18
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644
index 90d924fea9e9..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_DEBUG_KERNEL=y
3CONFIG_RCU_CPU_STALL_INFO=y
4CONFIG_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=6
7CONFIG_NR_CPUS=8
8CONFIG_RCU_FANOUT_EXACT=y
9CONFIG_HOTPLUG_CPU=n
10CONFIG_SUSPEND=n
11CONFIG_HIBERNATION=n
12CONFIG_PREEMPT_NONE=y
13CONFIG_PREEMPT_VOLUNTARY=n
14CONFIG_PREEMPT=n
15#CHECK#CONFIG_TREE_RCU=y
16CONFIG_RCU_TORTURE_TEST=m
17CONFIG_MODULE_UNLOAD=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp
deleted file mode 100644
index 0ccc36d72738..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp
+++ /dev/null
@@ -1,19 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_NR_CPUS=1
5CONFIG_RCU_FANOUT_EXACT=n
6CONFIG_HOTPLUG_CPU=n
7CONFIG_SUSPEND=n
8CONFIG_HIBERNATION=n
9CONFIG_PREEMPT_NONE=y
10CONFIG_PREEMPT_VOLUNTARY=n
11CONFIG_PREEMPT=n
12#CHECK#CONFIG_TREE_RCU=y
13CONFIG_RCU_TORTURE_TEST=m
14CONFIG_MODULE_UNLOAD=y
15CONFIG_SYSFS_DEPRECATED_V2=y
16CONFIG_IKCONFIG=y
17CONFIG_IKCONFIG_PROC=y
18CONFIG_PRINTK_TIME=y
19
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP
deleted file mode 100644
index 3f640cf84973..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,26 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_DEBUG_KERNEL=y
3CONFIG_RCU_CPU_STALL_INFO=y
4CONFIG_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=2
7CONFIG_NR_CPUS=16
8CONFIG_RCU_FANOUT_EXACT=n
9CONFIG_HOTPLUG_CPU=y
10CONFIG_RCU_NOCB_CPU=y
11CONFIG_RCU_NOCB_CPU_NONE=y
12CONFIG_RCU_NOCB_CPU_ZERO=n
13CONFIG_RCU_NOCB_CPU_ALL=n
14CONFIG_SUSPEND=n
15CONFIG_HIBERNATION=n
16CONFIG_PREEMPT_NONE=y
17CONFIG_PREEMPT_VOLUNTARY=n
18CONFIG_PREEMPT=n
19#CHECK#CONFIG_TREE_RCU=y
20CONFIG_RCU_TORTURE_TEST=m
21CONFIG_MODULE_UNLOAD=y
22CONFIG_SYSFS_DEPRECATED_V2=y
23CONFIG_IKCONFIG=y
24CONFIG_IKCONFIG_PROC=y
25CONFIG_PRINTK_TIME=y
26
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP
deleted file mode 100644
index 285da2dd8ac3..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_DEBUG_KERNEL=y
3CONFIG_RCU_CPU_STALL_INFO=y
4CONFIG_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=14
7CONFIG_NR_CPUS=16
8CONFIG_RCU_FANOUT_EXACT=y
9CONFIG_HOTPLUG_CPU=y
10CONFIG_SUSPEND=n
11CONFIG_HIBERNATION=n
12CONFIG_PREEMPT_NONE=y
13CONFIG_PREEMPT_VOLUNTARY=n
14CONFIG_PREEMPT=n
15#CHECK#CONFIG_TREE_RCU=y
16CONFIG_RCU_TORTURE_TEST=m
17CONFIG_MODULE_UNLOAD=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh
deleted file mode 100644
index 023f312a931c..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh
+++ /dev/null
@@ -1,23 +0,0 @@
1#CHECK#CONFIG_TINY_RCU=y
2CONFIG_RCU_TRACE=y
3CONFIG_RCU_TORTURE_TEST=m
4CONFIG_MODULE_UNLOAD=y
5CONFIG_SUSPEND=n
6CONFIG_HIBERNATION=n
7#
8CONFIG_SMP=n
9#
10CONFIG_HOTPLUG_CPU=n
11#
12CONFIG_NO_HZ=n
13#
14CONFIG_PREEMPT_NONE=y
15CONFIG_PREEMPT_VOLUNTARY=n
16CONFIG_PREEMPT=n
17CONFIG_PROVE_LOCKING=y
18CONFIG_PROVE_RCU=y
19CONFIG_SYSFS_DEPRECATED_V2=y
20CONFIG_IKCONFIG=y
21CONFIG_IKCONFIG_PROC=y
22CONFIG_PRINTK_TIME=y
23
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH
deleted file mode 100644
index 6fd0235dae73..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH
+++ /dev/null
@@ -1,20 +0,0 @@
1#CHECK#CONFIG_TINY_RCU=y
2CONFIG_RCU_TORTURE_TEST=m
3CONFIG_MODULE_UNLOAD=y
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6#
7CONFIG_SMP=n
8#
9CONFIG_HOTPLUG_CPU=n
10#
11CONFIG_NO_HZ=y
12#
13CONFIG_PREEMPT_NONE=y
14CONFIG_PREEMPT_VOLUNTARY=n
15CONFIG_PREEMPT=n
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644
index 9647c44cf4b7..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_CPU_STALL_INFO=y
3CONFIG_NO_HZ=y
4CONFIG_RCU_FAST_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=8
7CONFIG_NR_CPUS=8
8CONFIG_RCU_FANOUT_EXACT=n
9CONFIG_HOTPLUG_CPU=y
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644
index 0f3b667d2a9f..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=4
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644
index b035e141bf2a..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644
index 3ccf6a9447f5..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=6
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=n
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=y
11#CHECK#CONFIG_TREE_PREEMPT_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_RT_MUTEXES=y
15CONFIG_RCU_BOOST=y
16CONFIG_RCU_BOOST_PRIO=2
17CONFIG_PROVE_LOCKING=y
18CONFIG_PROVE_RCU=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644
index a55c00877fe4..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp
+++ /dev/null
@@ -1,27 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_CPU_STALL_INFO=y
3CONFIG_NO_HZ=y
4CONFIG_SMP=y
5CONFIG_RCU_FANOUT=6
6CONFIG_NR_CPUS=8
7CONFIG_RCU_FANOUT_EXACT=y
8CONFIG_HOTPLUG_CPU=n
9CONFIG_SUSPEND=n
10CONFIG_HIBERNATION=n
11CONFIG_PREEMPT_NONE=n
12CONFIG_PREEMPT_VOLUNTARY=n
13CONFIG_PREEMPT=y
14#CHECK#CONFIG_TREE_PREEMPT_RCU=y
15CONFIG_DEBUG_KERNEL=y
16CONFIG_DEBUG_OBJECTS=y
17CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
18CONFIG_RT_MUTEXES=y
19CONFIG_RCU_BOOST=y
20CONFIG_RCU_BOOST_PRIO=2
21CONFIG_RCU_TORTURE_TEST=m
22CONFIG_MODULE_UNLOAD=y
23CONFIG_SYSFS_DEPRECATED_V2=y
24CONFIG_IKCONFIG=y
25CONFIG_IKCONFIG_PROC=y
26CONFIG_PRINTK_TIME=y
27
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp
deleted file mode 100644
index f4c9175828bf..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp
+++ /dev/null
@@ -1,18 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=n
4CONFIG_RCU_FANOUT_EXACT=n
5CONFIG_HOTPLUG_CPU=n
6CONFIG_SUSPEND=n
7CONFIG_HIBERNATION=n
8CONFIG_PREEMPT_NONE=n
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=y
11CONFIG_TREE_PREEMPT_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_SYSFS_DEPRECATED_V2=y
15CONFIG_IKCONFIG=y
16CONFIG_IKCONFIG_PROC=y
17CONFIG_PRINTK_TIME=y
18
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP
deleted file mode 100644
index 77a8c5b75763..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,30 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=16
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_RCU_NOCB_CPU=y
9CONFIG_RCU_NOCB_CPU_NONE=n
10CONFIG_RCU_NOCB_CPU_ZERO=n
11CONFIG_RCU_NOCB_CPU_ALL=y
12CONFIG_SUSPEND=n
13CONFIG_HIBERNATION=n
14CONFIG_PREEMPT_NONE=n
15CONFIG_PREEMPT_VOLUNTARY=n
16CONFIG_PREEMPT=y
17#CHECK#CONFIG_TREE_PREEMPT_RCU=y
18CONFIG_RCU_TORTURE_TEST=m
19CONFIG_MODULE_UNLOAD=y
20CONFIG_PROVE_LOCKING=y
21CONFIG_PROVE_RCU=y
22CONFIG_DEBUG_KERNEL=y
23CONFIG_DEBUG_OBJECTS=y
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
25CONFIG_SYSFS_DEPRECATED_V2=y
26CONFIG_SLUB=y
27CONFIG_IKCONFIG=y
28CONFIG_IKCONFIG_PROC=y
29CONFIG_PRINTK_TIME=y
30
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all
deleted file mode 100644
index 0eecebc6e95f..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all
+++ /dev/null
@@ -1,30 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=16
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_RCU_NOCB_CPU=y
9CONFIG_RCU_NOCB_CPU_NONE=y
10CONFIG_RCU_NOCB_CPU_ZERO=n
11CONFIG_RCU_NOCB_CPU_ALL=n
12CONFIG_SUSPEND=n
13CONFIG_HIBERNATION=n
14CONFIG_PREEMPT_NONE=n
15CONFIG_PREEMPT_VOLUNTARY=n
16CONFIG_PREEMPT=y
17#CHECK#CONFIG_TREE_PREEMPT_RCU=y
18CONFIG_RCU_TORTURE_TEST=m
19CONFIG_MODULE_UNLOAD=y
20CONFIG_PROVE_LOCKING=y
21CONFIG_PROVE_RCU=y
22CONFIG_DEBUG_KERNEL=y
23CONFIG_DEBUG_OBJECTS=y
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
25CONFIG_SYSFS_DEPRECATED_V2=y
26CONFIG_SLUB=y
27CONFIG_IKCONFIG=y
28CONFIG_IKCONFIG_PROC=y
29CONFIG_PRINTK_TIME=y
30
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none
deleted file mode 100644
index 0eecebc6e95f..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none
+++ /dev/null
@@ -1,30 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=16
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_RCU_NOCB_CPU=y
9CONFIG_RCU_NOCB_CPU_NONE=y
10CONFIG_RCU_NOCB_CPU_ZERO=n
11CONFIG_RCU_NOCB_CPU_ALL=n
12CONFIG_SUSPEND=n
13CONFIG_HIBERNATION=n
14CONFIG_PREEMPT_NONE=n
15CONFIG_PREEMPT_VOLUNTARY=n
16CONFIG_PREEMPT=y
17#CHECK#CONFIG_TREE_PREEMPT_RCU=y
18CONFIG_RCU_TORTURE_TEST=m
19CONFIG_MODULE_UNLOAD=y
20CONFIG_PROVE_LOCKING=y
21CONFIG_PROVE_RCU=y
22CONFIG_DEBUG_KERNEL=y
23CONFIG_DEBUG_OBJECTS=y
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
25CONFIG_SYSFS_DEPRECATED_V2=y
26CONFIG_SLUB=y
27CONFIG_IKCONFIG=y
28CONFIG_IKCONFIG_PROC=y
29CONFIG_PRINTK_TIME=y
30
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp
deleted file mode 100644
index 588bc70420cd..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp
+++ /dev/null
@@ -1,30 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=16
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_RCU_NOCB_CPU=y
9CONFIG_RCU_NOCB_CPU_NONE=n
10CONFIG_RCU_NOCB_CPU_ZERO=y
11CONFIG_RCU_NOCB_CPU_ALL=n
12CONFIG_SUSPEND=n
13CONFIG_HIBERNATION=n
14CONFIG_PREEMPT_NONE=n
15CONFIG_PREEMPT_VOLUNTARY=n
16CONFIG_PREEMPT=y
17#CHECK#CONFIG_TREE_PREEMPT_RCU=y
18CONFIG_RCU_TORTURE_TEST=m
19CONFIG_MODULE_UNLOAD=y
20CONFIG_PROVE_LOCKING=y
21CONFIG_PROVE_RCU=y
22CONFIG_DEBUG_KERNEL=y
23CONFIG_DEBUG_OBJECTS=y
24CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
25CONFIG_SYSFS_DEPRECATED_V2=y
26CONFIG_SLUB=y
27CONFIG_IKCONFIG=y
28CONFIG_IKCONFIG_PROC=y
29CONFIG_PRINTK_TIME=y
30
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh
deleted file mode 100644
index e3361c3894a1..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh
+++ /dev/null
@@ -1,23 +0,0 @@
1CONFIG_TINY_PREEMPT_RCU=y
2CONFIG_RCU_BOOST=y
3CONFIG_RCU_BOOST_PRIO=2
4CONFIG_RCU_TRACE=y
5CONFIG_RCU_TORTURE_TEST=m
6CONFIG_MODULE_UNLOAD=y
7CONFIG_SUSPEND=n
8CONFIG_HIBERNATION=n
9#
10CONFIG_SMP=n
11#
12CONFIG_HOTPLUG_CPU=n
13#
14CONFIG_NO_HZ=n
15#
16CONFIG_PREEMPT_NONE=n
17CONFIG_PREEMPT_VOLUNTARY=n
18CONFIG_PREEMPT=y
19CONFIG_SYSFS_DEPRECATED_V2=y
20CONFIG_IKCONFIG=y
21CONFIG_IKCONFIG_PROC=y
22CONFIG_PRINTK_TIME=y
23
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH
deleted file mode 100644
index 64abfc3b4d94..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_TINY_PREEMPT_RCU=y
2CONFIG_RCU_TORTURE_TEST=m
3CONFIG_MODULE_UNLOAD=y
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6#
7CONFIG_SMP=n
8#
9CONFIG_HOTPLUG_CPU=n
10#
11CONFIG_NO_HZ=y
12#
13CONFIG_PREEMPT_NONE=n
14CONFIG_PREEMPT_VOLUNTARY=n
15CONFIG_PREEMPT=y
16CONFIG_PROVE_LOCKING=y
17CONFIG_PROVE_RCU=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST
deleted file mode 100644
index 18223947bbcb..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST
+++ /dev/null
@@ -1,14 +0,0 @@
1P1-S-T-NH-SD-SMP-HP
2P2-2-t-nh-sd-SMP-hp
3P3-3-T-nh-SD-SMP-hp
4P4-A-t-NH-sd-SMP-HP
5P5-U-T-NH-sd-SMP-hp
6N1-S-T-NH-SD-SMP-HP
7N2-2-t-nh-sd-SMP-hp
8N3-3-T-nh-SD-SMP-hp
9N4-A-t-NH-sd-SMP-HP
10N5-U-T-NH-sd-SMP-hp
11PT1-nh
12PT2-NH
13NT1-nh
14NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644
index d81e11d280aa..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,19 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_FAST_NO_HZ=y
3CONFIG_NO_HZ=y
4CONFIG_SMP=y
5CONFIG_RCU_FANOUT=8
6CONFIG_NR_CPUS=8
7CONFIG_RCU_FANOUT_EXACT=n
8CONFIG_HOTPLUG_CPU=y
9CONFIG_PREEMPT_NONE=y
10CONFIG_PREEMPT_VOLUNTARY=n
11CONFIG_PREEMPT=n
12#CHECK#CONFIG_TREE_RCU=y
13CONFIG_RCU_TORTURE_TEST=m
14CONFIG_MODULE_UNLOAD=y
15CONFIG_SYSFS_DEPRECATED_V2=y
16CONFIG_IKCONFIG=y
17CONFIG_IKCONFIG_PROC=y
18CONFIG_PRINTK_TIME=y
19
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644
index 02e418572b1b..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=4
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=y
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=n
13#CHECK#CONFIG_TREE_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644
index b3100f69c8cf..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=y
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=n
13#CHECK#CONFIG_TREE_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_PROVE_LOCKING=y
17CONFIG_PROVE_RCU=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644
index c56b44530725..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP
+++ /dev/null
@@ -1,18 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=6
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=y
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=n
11#CHECK#CONFIG_TREE_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_SYSFS_DEPRECATED_V2=y
15CONFIG_IKCONFIG=y
16CONFIG_IKCONFIG_PROC=y
17CONFIG_PRINTK_TIME=y
18
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644
index 90d924fea9e9..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_DEBUG_KERNEL=y
3CONFIG_RCU_CPU_STALL_INFO=y
4CONFIG_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=6
7CONFIG_NR_CPUS=8
8CONFIG_RCU_FANOUT_EXACT=y
9CONFIG_HOTPLUG_CPU=n
10CONFIG_SUSPEND=n
11CONFIG_HIBERNATION=n
12CONFIG_PREEMPT_NONE=y
13CONFIG_PREEMPT_VOLUNTARY=n
14CONFIG_PREEMPT=n
15#CHECK#CONFIG_TREE_RCU=y
16CONFIG_RCU_TORTURE_TEST=m
17CONFIG_MODULE_UNLOAD=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh
deleted file mode 100644
index 023f312a931c..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh
+++ /dev/null
@@ -1,23 +0,0 @@
1#CHECK#CONFIG_TINY_RCU=y
2CONFIG_RCU_TRACE=y
3CONFIG_RCU_TORTURE_TEST=m
4CONFIG_MODULE_UNLOAD=y
5CONFIG_SUSPEND=n
6CONFIG_HIBERNATION=n
7#
8CONFIG_SMP=n
9#
10CONFIG_HOTPLUG_CPU=n
11#
12CONFIG_NO_HZ=n
13#
14CONFIG_PREEMPT_NONE=y
15CONFIG_PREEMPT_VOLUNTARY=n
16CONFIG_PREEMPT=n
17CONFIG_PROVE_LOCKING=y
18CONFIG_PROVE_RCU=y
19CONFIG_SYSFS_DEPRECATED_V2=y
20CONFIG_IKCONFIG=y
21CONFIG_IKCONFIG_PROC=y
22CONFIG_PRINTK_TIME=y
23
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH
deleted file mode 100644
index 6fd0235dae73..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH
+++ /dev/null
@@ -1,20 +0,0 @@
1#CHECK#CONFIG_TINY_RCU=y
2CONFIG_RCU_TORTURE_TEST=m
3CONFIG_MODULE_UNLOAD=y
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6#
7CONFIG_SMP=n
8#
9CONFIG_HOTPLUG_CPU=n
10#
11CONFIG_NO_HZ=y
12#
13CONFIG_PREEMPT_NONE=y
14CONFIG_PREEMPT_VOLUNTARY=n
15CONFIG_PREEMPT=n
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644
index 9647c44cf4b7..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_CPU_STALL_INFO=y
3CONFIG_NO_HZ=y
4CONFIG_RCU_FAST_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=8
7CONFIG_NR_CPUS=8
8CONFIG_RCU_FANOUT_EXACT=n
9CONFIG_HOTPLUG_CPU=y
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644
index 0f3b667d2a9f..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=4
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644
index b035e141bf2a..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644
index 3ccf6a9447f5..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=6
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=n
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=y
11#CHECK#CONFIG_TREE_PREEMPT_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_RT_MUTEXES=y
15CONFIG_RCU_BOOST=y
16CONFIG_RCU_BOOST_PRIO=2
17CONFIG_PROVE_LOCKING=y
18CONFIG_PROVE_RCU=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644
index a55c00877fe4..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp
+++ /dev/null
@@ -1,27 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_CPU_STALL_INFO=y
3CONFIG_NO_HZ=y
4CONFIG_SMP=y
5CONFIG_RCU_FANOUT=6
6CONFIG_NR_CPUS=8
7CONFIG_RCU_FANOUT_EXACT=y
8CONFIG_HOTPLUG_CPU=n
9CONFIG_SUSPEND=n
10CONFIG_HIBERNATION=n
11CONFIG_PREEMPT_NONE=n
12CONFIG_PREEMPT_VOLUNTARY=n
13CONFIG_PREEMPT=y
14#CHECK#CONFIG_TREE_PREEMPT_RCU=y
15CONFIG_DEBUG_KERNEL=y
16CONFIG_DEBUG_OBJECTS=y
17CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
18CONFIG_RT_MUTEXES=y
19CONFIG_RCU_BOOST=y
20CONFIG_RCU_BOOST_PRIO=2
21CONFIG_RCU_TORTURE_TEST=m
22CONFIG_MODULE_UNLOAD=y
23CONFIG_SYSFS_DEPRECATED_V2=y
24CONFIG_IKCONFIG=y
25CONFIG_IKCONFIG_PROC=y
26CONFIG_PRINTK_TIME=y
27
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh
deleted file mode 100644
index e3361c3894a1..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh
+++ /dev/null
@@ -1,23 +0,0 @@
1CONFIG_TINY_PREEMPT_RCU=y
2CONFIG_RCU_BOOST=y
3CONFIG_RCU_BOOST_PRIO=2
4CONFIG_RCU_TRACE=y
5CONFIG_RCU_TORTURE_TEST=m
6CONFIG_MODULE_UNLOAD=y
7CONFIG_SUSPEND=n
8CONFIG_HIBERNATION=n
9#
10CONFIG_SMP=n
11#
12CONFIG_HOTPLUG_CPU=n
13#
14CONFIG_NO_HZ=n
15#
16CONFIG_PREEMPT_NONE=n
17CONFIG_PREEMPT_VOLUNTARY=n
18CONFIG_PREEMPT=y
19CONFIG_SYSFS_DEPRECATED_V2=y
20CONFIG_IKCONFIG=y
21CONFIG_IKCONFIG_PROC=y
22CONFIG_PRINTK_TIME=y
23
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH
deleted file mode 100644
index 64abfc3b4d94..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_TINY_PREEMPT_RCU=y
2CONFIG_RCU_TORTURE_TEST=m
3CONFIG_MODULE_UNLOAD=y
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6#
7CONFIG_SMP=n
8#
9CONFIG_HOTPLUG_CPU=n
10#
11CONFIG_NO_HZ=y
12#
13CONFIG_PREEMPT_NONE=n
14CONFIG_PREEMPT_VOLUNTARY=n
15CONFIG_PREEMPT=y
16CONFIG_PROVE_LOCKING=y
17CONFIG_PROVE_RCU=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
deleted file mode 100644
index bae55692ce6e..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
+++ /dev/null
@@ -1,44 +0,0 @@
1#!/bin/bash
2#
3# Kernel-version-dependent shell functions for the rest of the scripts.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, you can access it online at
17# http://www.gnu.org/licenses/gpl-2.0.html.
18#
19# Copyright (C) IBM Corporation, 2013
20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22
23# rcutorture_param_onoff bootparam-string config-file
24#
25# Adds onoff rcutorture module parameters to kernels having it.
26rcutorture_param_onoff () {
27 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
28 then
29 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
30 echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
31 fi
32}
33
34# per_version_boot_params bootparam-string config-file seconds
35#
36# Adds per-version torture-module parameters to kernels supporting them.
37per_version_boot_params () {
38 echo $1 `rcutorture_param_onoff "$1" "$2"` \
39 rcutorture.stat_interval=15 \
40 rcutorture.shutdown_secs=$3 \
41 rcutorture.rcutorture_runnable=1 \
42 rcutorture.test_no_idle_hz=1 \
43 rcutorture.verbose=1
44}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST
deleted file mode 100644
index 18223947bbcb..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST
+++ /dev/null
@@ -1,14 +0,0 @@
1P1-S-T-NH-SD-SMP-HP
2P2-2-t-nh-sd-SMP-hp
3P3-3-T-nh-SD-SMP-hp
4P4-A-t-NH-sd-SMP-HP
5P5-U-T-NH-sd-SMP-hp
6N1-S-T-NH-SD-SMP-HP
7N2-2-t-nh-sd-SMP-hp
8N3-3-T-nh-SD-SMP-hp
9N4-A-t-NH-sd-SMP-HP
10N5-U-T-NH-sd-SMP-hp
11PT1-nh
12PT2-NH
13NT1-nh
14NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644
index d81e11d280aa..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,19 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_FAST_NO_HZ=y
3CONFIG_NO_HZ=y
4CONFIG_SMP=y
5CONFIG_RCU_FANOUT=8
6CONFIG_NR_CPUS=8
7CONFIG_RCU_FANOUT_EXACT=n
8CONFIG_HOTPLUG_CPU=y
9CONFIG_PREEMPT_NONE=y
10CONFIG_PREEMPT_VOLUNTARY=n
11CONFIG_PREEMPT=n
12#CHECK#CONFIG_TREE_RCU=y
13CONFIG_RCU_TORTURE_TEST=m
14CONFIG_MODULE_UNLOAD=y
15CONFIG_SYSFS_DEPRECATED_V2=y
16CONFIG_IKCONFIG=y
17CONFIG_IKCONFIG_PROC=y
18CONFIG_PRINTK_TIME=y
19
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644
index 02e418572b1b..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=4
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=y
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=n
13#CHECK#CONFIG_TREE_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644
index b3100f69c8cf..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=y
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=n
13#CHECK#CONFIG_TREE_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_PROVE_LOCKING=y
17CONFIG_PROVE_RCU=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644
index c56b44530725..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP
+++ /dev/null
@@ -1,18 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=6
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=y
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=n
11#CHECK#CONFIG_TREE_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_SYSFS_DEPRECATED_V2=y
15CONFIG_IKCONFIG=y
16CONFIG_IKCONFIG_PROC=y
17CONFIG_PRINTK_TIME=y
18
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644
index 90d924fea9e9..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_DEBUG_KERNEL=y
3CONFIG_RCU_CPU_STALL_INFO=y
4CONFIG_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=6
7CONFIG_NR_CPUS=8
8CONFIG_RCU_FANOUT_EXACT=y
9CONFIG_HOTPLUG_CPU=n
10CONFIG_SUSPEND=n
11CONFIG_HIBERNATION=n
12CONFIG_PREEMPT_NONE=y
13CONFIG_PREEMPT_VOLUNTARY=n
14CONFIG_PREEMPT=n
15#CHECK#CONFIG_TREE_RCU=y
16CONFIG_RCU_TORTURE_TEST=m
17CONFIG_MODULE_UNLOAD=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh
deleted file mode 100644
index 023f312a931c..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh
+++ /dev/null
@@ -1,23 +0,0 @@
1#CHECK#CONFIG_TINY_RCU=y
2CONFIG_RCU_TRACE=y
3CONFIG_RCU_TORTURE_TEST=m
4CONFIG_MODULE_UNLOAD=y
5CONFIG_SUSPEND=n
6CONFIG_HIBERNATION=n
7#
8CONFIG_SMP=n
9#
10CONFIG_HOTPLUG_CPU=n
11#
12CONFIG_NO_HZ=n
13#
14CONFIG_PREEMPT_NONE=y
15CONFIG_PREEMPT_VOLUNTARY=n
16CONFIG_PREEMPT=n
17CONFIG_PROVE_LOCKING=y
18CONFIG_PROVE_RCU=y
19CONFIG_SYSFS_DEPRECATED_V2=y
20CONFIG_IKCONFIG=y
21CONFIG_IKCONFIG_PROC=y
22CONFIG_PRINTK_TIME=y
23
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH
deleted file mode 100644
index 6fd0235dae73..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH
+++ /dev/null
@@ -1,20 +0,0 @@
1#CHECK#CONFIG_TINY_RCU=y
2CONFIG_RCU_TORTURE_TEST=m
3CONFIG_MODULE_UNLOAD=y
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6#
7CONFIG_SMP=n
8#
9CONFIG_HOTPLUG_CPU=n
10#
11CONFIG_NO_HZ=y
12#
13CONFIG_PREEMPT_NONE=y
14CONFIG_PREEMPT_VOLUNTARY=n
15CONFIG_PREEMPT=n
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644
index 9647c44cf4b7..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_CPU_STALL_INFO=y
3CONFIG_NO_HZ=y
4CONFIG_RCU_FAST_NO_HZ=y
5CONFIG_SMP=y
6CONFIG_RCU_FANOUT=8
7CONFIG_NR_CPUS=8
8CONFIG_RCU_FANOUT_EXACT=n
9CONFIG_HOTPLUG_CPU=y
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644
index 0f3b667d2a9f..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=4
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644
index b035e141bf2a..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp
+++ /dev/null
@@ -1,20 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_NO_HZ=n
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=2
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=n
8CONFIG_SUSPEND=n
9CONFIG_HIBERNATION=n
10CONFIG_PREEMPT_NONE=n
11CONFIG_PREEMPT_VOLUNTARY=n
12CONFIG_PREEMPT=y
13#CHECK#CONFIG_TREE_PREEMPT_RCU=y
14CONFIG_RCU_TORTURE_TEST=m
15CONFIG_MODULE_UNLOAD=y
16CONFIG_SYSFS_DEPRECATED_V2=y
17CONFIG_IKCONFIG=y
18CONFIG_IKCONFIG_PROC=y
19CONFIG_PRINTK_TIME=y
20
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644
index 3ccf6a9447f5..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_RCU_TRACE=n
2CONFIG_NO_HZ=y
3CONFIG_SMP=y
4CONFIG_RCU_FANOUT=6
5CONFIG_NR_CPUS=8
6CONFIG_RCU_FANOUT_EXACT=n
7CONFIG_HOTPLUG_CPU=y
8CONFIG_PREEMPT_NONE=n
9CONFIG_PREEMPT_VOLUNTARY=n
10CONFIG_PREEMPT=y
11#CHECK#CONFIG_TREE_PREEMPT_RCU=y
12CONFIG_RCU_TORTURE_TEST=m
13CONFIG_MODULE_UNLOAD=y
14CONFIG_RT_MUTEXES=y
15CONFIG_RCU_BOOST=y
16CONFIG_RCU_BOOST_PRIO=2
17CONFIG_PROVE_LOCKING=y
18CONFIG_PROVE_RCU=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644
index a55c00877fe4..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp
+++ /dev/null
@@ -1,27 +0,0 @@
1CONFIG_RCU_TRACE=y
2CONFIG_RCU_CPU_STALL_INFO=y
3CONFIG_NO_HZ=y
4CONFIG_SMP=y
5CONFIG_RCU_FANOUT=6
6CONFIG_NR_CPUS=8
7CONFIG_RCU_FANOUT_EXACT=y
8CONFIG_HOTPLUG_CPU=n
9CONFIG_SUSPEND=n
10CONFIG_HIBERNATION=n
11CONFIG_PREEMPT_NONE=n
12CONFIG_PREEMPT_VOLUNTARY=n
13CONFIG_PREEMPT=y
14#CHECK#CONFIG_TREE_PREEMPT_RCU=y
15CONFIG_DEBUG_KERNEL=y
16CONFIG_DEBUG_OBJECTS=y
17CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
18CONFIG_RT_MUTEXES=y
19CONFIG_RCU_BOOST=y
20CONFIG_RCU_BOOST_PRIO=2
21CONFIG_RCU_TORTURE_TEST=m
22CONFIG_MODULE_UNLOAD=y
23CONFIG_SYSFS_DEPRECATED_V2=y
24CONFIG_IKCONFIG=y
25CONFIG_IKCONFIG_PROC=y
26CONFIG_PRINTK_TIME=y
27
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh
deleted file mode 100644
index e3361c3894a1..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh
+++ /dev/null
@@ -1,23 +0,0 @@
1CONFIG_TINY_PREEMPT_RCU=y
2CONFIG_RCU_BOOST=y
3CONFIG_RCU_BOOST_PRIO=2
4CONFIG_RCU_TRACE=y
5CONFIG_RCU_TORTURE_TEST=m
6CONFIG_MODULE_UNLOAD=y
7CONFIG_SUSPEND=n
8CONFIG_HIBERNATION=n
9#
10CONFIG_SMP=n
11#
12CONFIG_HOTPLUG_CPU=n
13#
14CONFIG_NO_HZ=n
15#
16CONFIG_PREEMPT_NONE=n
17CONFIG_PREEMPT_VOLUNTARY=n
18CONFIG_PREEMPT=y
19CONFIG_SYSFS_DEPRECATED_V2=y
20CONFIG_IKCONFIG=y
21CONFIG_IKCONFIG_PROC=y
22CONFIG_PRINTK_TIME=y
23
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH
deleted file mode 100644
index 64abfc3b4d94..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH
+++ /dev/null
@@ -1,22 +0,0 @@
1CONFIG_TINY_PREEMPT_RCU=y
2CONFIG_RCU_TORTURE_TEST=m
3CONFIG_MODULE_UNLOAD=y
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6#
7CONFIG_SMP=n
8#
9CONFIG_HOTPLUG_CPU=n
10#
11CONFIG_NO_HZ=y
12#
13CONFIG_PREEMPT_NONE=n
14CONFIG_PREEMPT_VOLUNTARY=n
15CONFIG_PREEMPT=y
16CONFIG_PROVE_LOCKING=y
17CONFIG_PROVE_RCU=y
18CONFIG_SYSFS_DEPRECATED_V2=y
19CONFIG_IKCONFIG=y
20CONFIG_IKCONFIG_PROC=y
21CONFIG_PRINTK_TIME=y
22
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
deleted file mode 100644
index 8977d8d31b19..000000000000
--- a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
+++ /dev/null
@@ -1,57 +0,0 @@
1#!/bin/bash
2#
3# Kernel-version-dependent shell functions for the rest of the scripts.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, you can access it online at
17# http://www.gnu.org/licenses/gpl-2.0.html.
18#
19# Copyright (C) IBM Corporation, 2013
20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22
23# rcutorture_param_n_barrier_cbs bootparam-string
24#
25# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
26rcutorture_param_n_barrier_cbs () {
27 if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
28 then
29 :
30 else
31 echo rcutorture.n_barrier_cbs=4
32 fi
33}
34
35# rcutorture_param_onoff bootparam-string config-file
36#
37# Adds onoff rcutorture module parameters to kernels having it.
38rcutorture_param_onoff () {
39 if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
40 then
41 echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
42 echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
43 fi
44}
45
46# per_version_boot_params bootparam-string config-file seconds
47#
48# Adds per-version torture-module parameters to kernels supporting them.
49per_version_boot_params () {
50 echo $1 `rcutorture_param_onoff "$1" "$2"` \
51 `rcutorture_param_n_barrier_cbs "$1"` \
52 rcutorture.stat_interval=15 \
53 rcutorture.shutdown_secs=$3 \
54 rcutorture.rcutorture_runnable=1 \
55 rcutorture.test_no_idle_hz=1 \
56 rcutorture.verbose=1
57}
diff --git a/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt
index 28db67b54e55..9ef33a743b73 100644
--- a/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt
+++ b/tools/testing/selftests/rcutorture/doc/TINY_RCU.txt
@@ -34,7 +34,7 @@ CONFIG_PREEMPT
34CONFIG_PREEMPT_RCU 34CONFIG_PREEMPT_RCU
35CONFIG_SMP 35CONFIG_SMP
36CONFIG_TINY_RCU 36CONFIG_TINY_RCU
37CONFIG_TREE_PREEMPT_RCU 37CONFIG_PREEMPT_RCU
38CONFIG_TREE_RCU 38CONFIG_TREE_RCU
39 39
40 All forced by CONFIG_TINY_RCU. 40 All forced by CONFIG_TINY_RCU.
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
index 3e588db86a17..ec03c883db00 100644
--- a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
+++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
@@ -1,5 +1,5 @@
1This document gives a brief rationale for the TREE_RCU-related test 1This document gives a brief rationale for the TREE_RCU-related test
2cases, a group that includes TREE_PREEMPT_RCU. 2cases, a group that includes PREEMPT_RCU.
3 3
4 4
5Kconfig Parameters: 5Kconfig Parameters:
@@ -14,10 +14,9 @@ CONFIG_NO_HZ_FULL_SYSIDLE -- Do one.
14CONFIG_PREEMPT -- Do half. (First three and #8.) 14CONFIG_PREEMPT -- Do half. (First three and #8.)
15CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not. 15CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not.
16CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING. 16CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING.
17CONFIG_RCU_BOOST -- one of TREE_PREEMPT_RCU. 17CONFIG_RCU_BOOST -- one of PREEMPT_RCU.
18CONFIG_RCU_BOOST_PRIO -- set to 2 for _BOOST testing. 18CONFIG_RCU_KTHREAD_PRIO -- set to 2 for _BOOST testing.
19CONFIG_RCU_CPU_STALL_INFO -- do one with and without _VERBOSE. 19CONFIG_RCU_CPU_STALL_INFO -- Do one.
20CONFIG_RCU_CPU_STALL_VERBOSE -- do one with and without _INFO.
21CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others. 20CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others.
22CONFIG_RCU_FANOUT_EXACT -- Do one. 21CONFIG_RCU_FANOUT_EXACT -- Do one.
23CONFIG_RCU_FANOUT_LEAF -- Do one non-default. 22CONFIG_RCU_FANOUT_LEAF -- Do one non-default.
@@ -27,7 +26,7 @@ CONFIG_RCU_NOCB_CPU_ALL -- Do one.
27CONFIG_RCU_NOCB_CPU_NONE -- Do one. 26CONFIG_RCU_NOCB_CPU_NONE -- Do one.
28CONFIG_RCU_NOCB_CPU_ZERO -- Do one. 27CONFIG_RCU_NOCB_CPU_ZERO -- Do one.
29CONFIG_RCU_TRACE -- Do half. 28CONFIG_RCU_TRACE -- Do half.
30CONFIG_SMP -- Need one !SMP for TREE_PREEMPT_RCU. 29CONFIG_SMP -- Need one !SMP for PREEMPT_RCU.
31RCU-bh: Do one with PREEMPT and one with !PREEMPT. 30RCU-bh: Do one with PREEMPT and one with !PREEMPT.
32RCU-sched: Do one with PREEMPT but not BOOST. 31RCU-sched: Do one with PREEMPT but not BOOST.
33 32
@@ -77,7 +76,7 @@ CONFIG_RCU_CPU_STALL_TIMEOUT
77 76
78CONFIG_RCU_STALL_COMMON 77CONFIG_RCU_STALL_COMMON
79 78
80 Implied by TREE_RCU and TREE_PREEMPT_RCU. 79 Implied by TREE_RCU and PREEMPT_RCU.
81 80
82CONFIG_RCU_TORTURE_TEST 81CONFIG_RCU_TORTURE_TEST
83CONFIG_RCU_TORTURE_TEST_RUNNABLE 82CONFIG_RCU_TORTURE_TEST_RUNNABLE
@@ -88,7 +87,7 @@ CONFIG_RCU_USER_QS
88 87
89 Redundant with CONFIG_NO_HZ_FULL. 88 Redundant with CONFIG_NO_HZ_FULL.
90 89
91CONFIG_TREE_PREEMPT_RCU 90CONFIG_PREEMPT_RCU
92CONFIG_TREE_RCU 91CONFIG_TREE_RCU
93 92
94 These are controlled by CONFIG_PREEMPT. 93 These are controlled by CONFIG_PREEMPT.
diff --git a/tools/testing/selftests/size/.gitignore b/tools/testing/selftests/size/.gitignore
new file mode 100644
index 000000000000..189b7818de34
--- /dev/null
+++ b/tools/testing/selftests/size/.gitignore
@@ -0,0 +1 @@
get_size
diff --git a/tools/testing/selftests/size/Makefile b/tools/testing/selftests/size/Makefile
new file mode 100644
index 000000000000..04dc25e4fa92
--- /dev/null
+++ b/tools/testing/selftests/size/Makefile
@@ -0,0 +1,12 @@
1CC = $(CROSS_COMPILE)gcc
2
3all: get_size
4
5get_size: get_size.c
6 $(CC) -static -ffreestanding -nostartfiles -s $< -o $@
7
8run_tests: all
9 ./get_size
10
11clean:
12 $(RM) get_size
diff --git a/tools/testing/selftests/size/get_size.c b/tools/testing/selftests/size/get_size.c
new file mode 100644
index 000000000000..2d1af7cca463
--- /dev/null
+++ b/tools/testing/selftests/size/get_size.c
@@ -0,0 +1,100 @@
1/*
2 * Copyright 2014 Sony Mobile Communications Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2
5 *
6 * Selftest for runtime system size
7 *
8 * Prints the amount of RAM that the currently running system is using.
9 *
10 * This program tries to be as small as possible itself, to
11 * avoid perturbing the system memory utilization with its
12 * own execution. It also attempts to have as few dependencies
13 * on kernel features as possible.
14 *
15 * It should be statically linked, with startup libs avoided.
16 * It uses no library calls, and only the following 3 syscalls:
17 * sysinfo(), write(), and _exit()
18 *
19 * For output, it avoids printf (which in some C libraries
20 * has large external dependencies) by implementing it's own
21 * number output and print routines, and using __builtin_strlen()
22 */
23
24#include <sys/sysinfo.h>
25#include <unistd.h>
26
27#define STDOUT_FILENO 1
28
29static int print(const char *s)
30{
31 return write(STDOUT_FILENO, s, __builtin_strlen(s));
32}
33
34static inline char *num_to_str(unsigned long num, char *buf, int len)
35{
36 unsigned int digit;
37
38 /* put digits in buffer from back to front */
39 buf += len - 1;
40 *buf = 0;
41 do {
42 digit = num % 10;
43 *(--buf) = digit + '0';
44 num /= 10;
45 } while (num > 0);
46
47 return buf;
48}
49
50static int print_num(unsigned long num)
51{
52 char num_buf[30];
53
54 return print(num_to_str(num, num_buf, sizeof(num_buf)));
55}
56
57static int print_k_value(const char *s, unsigned long num, unsigned long units)
58{
59 unsigned long long temp;
60 int ccode;
61
62 print(s);
63
64 temp = num;
65 temp = (temp * units)/1024;
66 num = temp;
67 ccode = print_num(num);
68 print("\n");
69 return ccode;
70}
71
72/* this program has no main(), as startup libraries are not used */
73void _start(void)
74{
75 int ccode;
76 struct sysinfo info;
77 unsigned long used;
78
79 print("Testing system size.\n");
80 print("1..1\n");
81
82 ccode = sysinfo(&info);
83 if (ccode < 0) {
84 print("not ok 1 get runtime memory use\n");
85 print("# could not get sysinfo\n");
86 _exit(ccode);
87 }
88 /* ignore cache complexities for now */
89 used = info.totalram - info.freeram - info.bufferram;
90 print_k_value("ok 1 get runtime memory use # size = ", used,
91 info.mem_unit);
92
93 print("# System runtime memory report (units in Kilobytes):\n");
94 print_k_value("# Total: ", info.totalram, info.mem_unit);
95 print_k_value("# Free: ", info.freeram, info.mem_unit);
96 print_k_value("# Buffer: ", info.bufferram, info.mem_unit);
97 print_k_value("# In use: ", used, info.mem_unit);
98
99 _exit(0);
100}
diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c
index 41bd85559d4b..f87d970a485c 100644
--- a/tools/testing/selftests/timers/posix_timers.c
+++ b/tools/testing/selftests/timers/posix_timers.c
@@ -15,6 +15,8 @@
15#include <time.h> 15#include <time.h>
16#include <pthread.h> 16#include <pthread.h>
17 17
18#include "../kselftest.h"
19
18#define DELAY 2 20#define DELAY 2
19#define USECS_PER_SEC 1000000 21#define USECS_PER_SEC 1000000
20 22
@@ -194,16 +196,16 @@ int main(int argc, char **argv)
194 printf("based timers if other threads run on the CPU...\n"); 196 printf("based timers if other threads run on the CPU...\n");
195 197
196 if (check_itimer(ITIMER_VIRTUAL) < 0) 198 if (check_itimer(ITIMER_VIRTUAL) < 0)
197 return -1; 199 return ksft_exit_fail();
198 200
199 if (check_itimer(ITIMER_PROF) < 0) 201 if (check_itimer(ITIMER_PROF) < 0)
200 return -1; 202 return ksft_exit_fail();
201 203
202 if (check_itimer(ITIMER_REAL) < 0) 204 if (check_itimer(ITIMER_REAL) < 0)
203 return -1; 205 return ksft_exit_fail();
204 206
205 if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0) 207 if (check_timer_create(CLOCK_THREAD_CPUTIME_ID) < 0)
206 return -1; 208 return ksft_exit_fail();
207 209
208 /* 210 /*
209 * It's unfortunately hard to reliably test a timer expiration 211 * It's unfortunately hard to reliably test a timer expiration
@@ -215,7 +217,7 @@ int main(int argc, char **argv)
215 * find a better solution. 217 * find a better solution.
216 */ 218 */
217 if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0) 219 if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0)
218 return -1; 220 return ksft_exit_fail();
219 221
220 return 0; 222 return ksft_exit_pass();
221} 223}
diff --git a/tools/testing/selftests/user/Makefile b/tools/testing/selftests/user/Makefile
index 396255bd720e..12c9d15bab07 100644
--- a/tools/testing/selftests/user/Makefile
+++ b/tools/testing/selftests/user/Makefile
@@ -4,10 +4,4 @@
4all: 4all:
5 5
6run_tests: all 6run_tests: all
7 @if /sbin/modprobe test_user_copy ; then \ 7 ./test_user_copy.sh
8 rmmod test_user_copy; \
9 echo "user_copy: ok"; \
10 else \
11 echo "user_copy: [FAIL]"; \
12 exit 1; \
13 fi
diff --git a/tools/testing/selftests/user/test_user_copy.sh b/tools/testing/selftests/user/test_user_copy.sh
new file mode 100755
index 000000000000..350107f40c1d
--- /dev/null
+++ b/tools/testing/selftests/user/test_user_copy.sh
@@ -0,0 +1,10 @@
1#!/bin/sh
2# Runs copy_to/from_user infrastructure using test_user_copy kernel module
3
4if /sbin/modprobe -q test_user_copy; then
5 /sbin/modprobe -q -r test_user_copy
6 echo "user_copy: ok"
7else
8 echo "user_copy: [FAIL]"
9 exit 1
10fi
diff --git a/tools/thermal/tmon/sysfs.c b/tools/thermal/tmon/sysfs.c
index dfe454855cd2..1c12536f2081 100644
--- a/tools/thermal/tmon/sysfs.c
+++ b/tools/thermal/tmon/sysfs.c
@@ -446,7 +446,7 @@ int probe_thermal_sysfs(void)
446 return -1; 446 return -1;
447 } 447 }
448 448
449 ptdata.tzi = calloc(sizeof(struct tz_info), ptdata.max_tz_instance+1); 449 ptdata.tzi = calloc(ptdata.max_tz_instance+1, sizeof(struct tz_info));
450 if (!ptdata.tzi) { 450 if (!ptdata.tzi) {
451 fprintf(stderr, "Err: allocate tz_info\n"); 451 fprintf(stderr, "Err: allocate tz_info\n");
452 return -1; 452 return -1;
@@ -454,8 +454,8 @@ int probe_thermal_sysfs(void)
454 454
455 /* we still show thermal zone information if there is no cdev */ 455 /* we still show thermal zone information if there is no cdev */
456 if (ptdata.nr_cooling_dev) { 456 if (ptdata.nr_cooling_dev) {
457 ptdata.cdi = calloc(sizeof(struct cdev_info), 457 ptdata.cdi = calloc(ptdata.max_cdev_instance + 1,
458 ptdata.max_cdev_instance + 1); 458 sizeof(struct cdev_info));
459 if (!ptdata.cdi) { 459 if (!ptdata.cdi) {
460 free(ptdata.tzi); 460 free(ptdata.tzi);
461 fprintf(stderr, "Err: allocate cdev_info\n"); 461 fprintf(stderr, "Err: allocate cdev_info\n");
diff --git a/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c b/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c
index af4b0508be77..aaca1f44e788 100644
--- a/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c
+++ b/tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c
@@ -342,7 +342,7 @@ int main(int argc, char *argv[])
342 iobuf[i].requested = ret; 342 iobuf[i].requested = ret;
343 printf("submit: %d requests buf: %d\n", ret, i); 343 printf("submit: %d requests buf: %d\n", ret, i);
344 } else 344 } else
345 perror("unable to submit reqests"); 345 perror("unable to submit requests");
346 } 346 }
347 347
348 /* if event is ready to read */ 348 /* if event is ready to read */
diff --git a/tools/usb/usbip/libsrc/list.h b/tools/usb/usbip/libsrc/list.h
index 8d0c936e184f..5eaaa78e2c6a 100644
--- a/tools/usb/usbip/libsrc/list.h
+++ b/tools/usb/usbip/libsrc/list.h
@@ -98,7 +98,7 @@ static inline void list_del(struct list_head *entry)
98 * list_entry - get the struct for this entry 98 * list_entry - get the struct for this entry
99 * @ptr: the &struct list_head pointer. 99 * @ptr: the &struct list_head pointer.
100 * @type: the type of the struct this is embedded in. 100 * @type: the type of the struct this is embedded in.
101 * @member: the name of the list_struct within the struct. 101 * @member: the name of the list_head within the struct.
102 */ 102 */
103#define list_entry(ptr, type, member) \ 103#define list_entry(ptr, type, member) \
104 container_of(ptr, type, member) 104 container_of(ptr, type, member)
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index 2f87f2d348ba..2a7cd2b8d966 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -91,7 +91,6 @@ static void usbipd_help(void)
91static int recv_request_import(int sockfd) 91static int recv_request_import(int sockfd)
92{ 92{
93 struct op_import_request req; 93 struct op_import_request req;
94 struct op_common reply;
95 struct usbip_exported_device *edev; 94 struct usbip_exported_device *edev;
96 struct usbip_usb_device pdu_udev; 95 struct usbip_usb_device pdu_udev;
97 struct list_head *i; 96 struct list_head *i;
@@ -100,7 +99,6 @@ static int recv_request_import(int sockfd)
100 int rc; 99 int rc;
101 100
102 memset(&req, 0, sizeof(req)); 101 memset(&req, 0, sizeof(req));
103 memset(&reply, 0, sizeof(reply));
104 102
105 rc = usbip_net_recv(sockfd, &req, sizeof(req)); 103 rc = usbip_net_recv(sockfd, &req, sizeof(req));
106 if (rc < 0) { 104 if (rc < 0) {
diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
index 9325f4693821..505ad51b3b51 100644
--- a/tools/virtio/Makefile
+++ b/tools/virtio/Makefile
@@ -3,7 +3,7 @@ test: virtio_test vringh_test
3virtio_test: virtio_ring.o virtio_test.o 3virtio_test: virtio_ring.o virtio_test.o
4vringh_test: vringh_test.o vringh.o virtio_ring.o 4vringh_test: vringh_test.o vringh.o virtio_ring.o
5 5
6CFLAGS += -g -O2 -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE 6CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE
7vpath %.c ../../drivers/virtio ../../drivers/vhost 7vpath %.c ../../drivers/virtio ../../drivers/vhost
8mod: 8mod:
9 ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test 9 ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index 5a2d1f0f6bc7..a3e07016a440 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -6,31 +6,12 @@
6/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */ 6/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
7#define list_add_tail(a, b) do {} while (0) 7#define list_add_tail(a, b) do {} while (0)
8#define list_del(a) do {} while (0) 8#define list_del(a) do {} while (0)
9 9#define list_for_each_entry(a, b, c) while (0)
10#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
11#define BITS_PER_BYTE 8
12#define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE)
13#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
14
15/* TODO: Not atomic as it should be:
16 * we don't use this for anything important. */
17static inline void clear_bit(int nr, volatile unsigned long *addr)
18{
19 unsigned long mask = BIT_MASK(nr);
20 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
21
22 *p &= ~mask;
23}
24
25static inline int test_bit(int nr, const volatile unsigned long *addr)
26{
27 return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
28}
29/* end of stubs */ 10/* end of stubs */
30 11
31struct virtio_device { 12struct virtio_device {
32 void *dev; 13 void *dev;
33 unsigned long features[1]; 14 u64 features;
34}; 15};
35 16
36struct virtqueue { 17struct virtqueue {
diff --git a/tools/virtio/linux/virtio_byteorder.h b/tools/virtio/linux/virtio_byteorder.h
new file mode 100644
index 000000000000..9de9e6ac1d10
--- /dev/null
+++ b/tools/virtio/linux/virtio_byteorder.h
@@ -0,0 +1,8 @@
1#ifndef _LINUX_VIRTIO_BYTEORDER_STUB_H
2#define _LINUX_VIRTIO_BYTEORDER_STUB_H
3
4#include <asm/byteorder.h>
5#include "../../include/linux/byteorder/generic.h"
6#include "../../include/linux/virtio_byteorder.h"
7
8#endif
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h
index 5049967f99f7..806d683ab107 100644
--- a/tools/virtio/linux/virtio_config.h
+++ b/tools/virtio/linux/virtio_config.h
@@ -1,6 +1,72 @@
1#define VIRTIO_TRANSPORT_F_START 28 1#include <linux/virtio_byteorder.h>
2#define VIRTIO_TRANSPORT_F_END 32 2#include <linux/virtio.h>
3#include <uapi/linux/virtio_config.h>
4
5/*
6 * __virtio_test_bit - helper to test feature bits. For use by transports.
7 * Devices should normally use virtio_has_feature,
8 * which includes more checks.
9 * @vdev: the device
10 * @fbit: the feature bit
11 */
12static inline bool __virtio_test_bit(const struct virtio_device *vdev,
13 unsigned int fbit)
14{
15 return vdev->features & (1ULL << fbit);
16}
17
18/**
19 * __virtio_set_bit - helper to set feature bits. For use by transports.
20 * @vdev: the device
21 * @fbit: the feature bit
22 */
23static inline void __virtio_set_bit(struct virtio_device *vdev,
24 unsigned int fbit)
25{
26 vdev->features |= (1ULL << fbit);
27}
28
29/**
30 * __virtio_clear_bit - helper to clear feature bits. For use by transports.
31 * @vdev: the device
32 * @fbit: the feature bit
33 */
34static inline void __virtio_clear_bit(struct virtio_device *vdev,
35 unsigned int fbit)
36{
37 vdev->features &= ~(1ULL << fbit);
38}
3 39
4#define virtio_has_feature(dev, feature) \ 40#define virtio_has_feature(dev, feature) \
5 test_bit((feature), (dev)->features) 41 (__virtio_test_bit((dev), feature))
42
43static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
44{
45 return __virtio16_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
46}
47
48static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
49{
50 return __cpu_to_virtio16(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
51}
52
53static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
54{
55 return __virtio32_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
56}
57
58static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
59{
60 return __cpu_to_virtio32(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
61}
62
63static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
64{
65 return __virtio64_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
66}
67
68static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
69{
70 return __cpu_to_virtio64(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
71}
6 72
diff --git a/tools/virtio/uapi/linux/virtio_types.h b/tools/virtio/uapi/linux/virtio_types.h
new file mode 100644
index 000000000000..e7a1096e7c97
--- /dev/null
+++ b/tools/virtio/uapi/linux/virtio_types.h
@@ -0,0 +1 @@
#include "../../include/uapi/linux/virtio_types.h"
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index 00ea679b3826..e0445898f08f 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -11,6 +11,7 @@
11#include <sys/types.h> 11#include <sys/types.h>
12#include <fcntl.h> 12#include <fcntl.h>
13#include <stdbool.h> 13#include <stdbool.h>
14#include <linux/virtio_types.h>
14#include <linux/vhost.h> 15#include <linux/vhost.h>
15#include <linux/virtio.h> 16#include <linux/virtio.h>
16#include <linux/virtio_ring.h> 17#include <linux/virtio_ring.h>
@@ -60,7 +61,7 @@ void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info)
60{ 61{
61 struct vhost_vring_state state = { .index = info->idx }; 62 struct vhost_vring_state state = { .index = info->idx };
62 struct vhost_vring_file file = { .index = info->idx }; 63 struct vhost_vring_file file = { .index = info->idx };
63 unsigned long long features = dev->vdev.features[0]; 64 unsigned long long features = dev->vdev.features;
64 struct vhost_vring_addr addr = { 65 struct vhost_vring_addr addr = {
65 .index = info->idx, 66 .index = info->idx,
66 .desc_user_addr = (uint64_t)(unsigned long)info->vring.desc, 67 .desc_user_addr = (uint64_t)(unsigned long)info->vring.desc,
@@ -113,8 +114,7 @@ static void vdev_info_init(struct vdev_info* dev, unsigned long long features)
113{ 114{
114 int r; 115 int r;
115 memset(dev, 0, sizeof *dev); 116 memset(dev, 0, sizeof *dev);
116 dev->vdev.features[0] = features; 117 dev->vdev.features = features;
117 dev->vdev.features[1] = features >> 32;
118 dev->buf_size = 1024; 118 dev->buf_size = 1024;
119 dev->buf = malloc(dev->buf_size); 119 dev->buf = malloc(dev->buf_size);
120 assert(dev->buf); 120 assert(dev->buf);
@@ -228,6 +228,14 @@ const struct option longopts[] = {
228 .val = 'i', 228 .val = 'i',
229 }, 229 },
230 { 230 {
231 .name = "virtio-1",
232 .val = '1',
233 },
234 {
235 .name = "no-virtio-1",
236 .val = '0',
237 },
238 {
231 .name = "delayed-interrupt", 239 .name = "delayed-interrupt",
232 .val = 'D', 240 .val = 'D',
233 }, 241 },
@@ -244,6 +252,7 @@ static void help(void)
244 fprintf(stderr, "Usage: virtio_test [--help]" 252 fprintf(stderr, "Usage: virtio_test [--help]"
245 " [--no-indirect]" 253 " [--no-indirect]"
246 " [--no-event-idx]" 254 " [--no-event-idx]"
255 " [--no-virtio-1]"
247 " [--delayed-interrupt]" 256 " [--delayed-interrupt]"
248 "\n"); 257 "\n");
249} 258}
@@ -252,7 +261,7 @@ int main(int argc, char **argv)
252{ 261{
253 struct vdev_info dev; 262 struct vdev_info dev;
254 unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | 263 unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
255 (1ULL << VIRTIO_RING_F_EVENT_IDX); 264 (1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1);
256 int o; 265 int o;
257 bool delayed = false; 266 bool delayed = false;
258 267
@@ -273,6 +282,9 @@ int main(int argc, char **argv)
273 case 'i': 282 case 'i':
274 features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC); 283 features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC);
275 break; 284 break;
285 case '0':
286 features &= ~(1ULL << VIRTIO_F_VERSION_1);
287 break;
276 case 'D': 288 case 'D':
277 delayed = true; 289 delayed = true;
278 break; 290 break;
diff --git a/tools/virtio/vringh_test.c b/tools/virtio/vringh_test.c
index 14a4f4cab5b9..5f94f5105678 100644
--- a/tools/virtio/vringh_test.c
+++ b/tools/virtio/vringh_test.c
@@ -7,6 +7,7 @@
7#include <linux/virtio.h> 7#include <linux/virtio.h>
8#include <linux/vringh.h> 8#include <linux/vringh.h>
9#include <linux/virtio_ring.h> 9#include <linux/virtio_ring.h>
10#include <linux/virtio_config.h>
10#include <linux/uaccess.h> 11#include <linux/uaccess.h>
11#include <sys/types.h> 12#include <sys/types.h>
12#include <sys/stat.h> 13#include <sys/stat.h>
@@ -131,7 +132,7 @@ static inline int vringh_get_head(struct vringh *vrh, u16 *head)
131 return 1; 132 return 1;
132} 133}
133 134
134static int parallel_test(unsigned long features, 135static int parallel_test(u64 features,
135 bool (*getrange)(struct vringh *vrh, 136 bool (*getrange)(struct vringh *vrh,
136 u64 addr, struct vringh_range *r), 137 u64 addr, struct vringh_range *r),
137 bool fast_vringh) 138 bool fast_vringh)
@@ -304,7 +305,7 @@ static int parallel_test(unsigned long features,
304 close(to_guest[1]); 305 close(to_guest[1]);
305 close(to_host[0]); 306 close(to_host[0]);
306 307
307 gvdev.vdev.features[0] = features; 308 gvdev.vdev.features = features;
308 gvdev.to_host_fd = to_host[1]; 309 gvdev.to_host_fd = to_host[1];
309 gvdev.notifies = 0; 310 gvdev.notifies = 0;
310 311
@@ -449,13 +450,15 @@ int main(int argc, char *argv[])
449 bool fast_vringh = false, parallel = false; 450 bool fast_vringh = false, parallel = false;
450 451
451 getrange = getrange_iov; 452 getrange = getrange_iov;
452 vdev.features[0] = 0; 453 vdev.features = 0;
453 454
454 while (argv[1]) { 455 while (argv[1]) {
455 if (strcmp(argv[1], "--indirect") == 0) 456 if (strcmp(argv[1], "--indirect") == 0)
456 vdev.features[0] |= (1 << VIRTIO_RING_F_INDIRECT_DESC); 457 __virtio_set_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC);
457 else if (strcmp(argv[1], "--eventidx") == 0) 458 else if (strcmp(argv[1], "--eventidx") == 0)
458 vdev.features[0] |= (1 << VIRTIO_RING_F_EVENT_IDX); 459 __virtio_set_bit(&vdev, VIRTIO_RING_F_EVENT_IDX);
460 else if (strcmp(argv[1], "--virtio-1") == 0)
461 __virtio_set_bit(&vdev, VIRTIO_F_VERSION_1);
459 else if (strcmp(argv[1], "--slow-range") == 0) 462 else if (strcmp(argv[1], "--slow-range") == 0)
460 getrange = getrange_slow; 463 getrange = getrange_slow;
461 else if (strcmp(argv[1], "--fast-vringh") == 0) 464 else if (strcmp(argv[1], "--fast-vringh") == 0)
@@ -468,7 +471,7 @@ int main(int argc, char *argv[])
468 } 471 }
469 472
470 if (parallel) 473 if (parallel)
471 return parallel_test(vdev.features[0], getrange, fast_vringh); 474 return parallel_test(vdev.features, getrange, fast_vringh);
472 475
473 if (posix_memalign(&__user_addr_min, PAGE_SIZE, USER_MEM) != 0) 476 if (posix_memalign(&__user_addr_min, PAGE_SIZE, USER_MEM) != 0)
474 abort(); 477 abort();
@@ -483,7 +486,7 @@ int main(int argc, char *argv[])
483 486
484 /* Set up host side. */ 487 /* Set up host side. */
485 vring_init(&vrh.vring, RINGSIZE, __user_addr_min, ALIGN); 488 vring_init(&vrh.vring, RINGSIZE, __user_addr_min, ALIGN);
486 vringh_init_user(&vrh, vdev.features[0], RINGSIZE, true, 489 vringh_init_user(&vrh, vdev.features, RINGSIZE, true,
487 vrh.vring.desc, vrh.vring.avail, vrh.vring.used); 490 vrh.vring.desc, vrh.vring.avail, vrh.vring.used);
488 491
489 /* No descriptor to get yet... */ 492 /* No descriptor to get yet... */
@@ -652,13 +655,13 @@ int main(int argc, char *argv[])
652 } 655 }
653 656
654 /* Test weird (but legal!) indirect. */ 657 /* Test weird (but legal!) indirect. */
655 if (vdev.features[0] & (1 << VIRTIO_RING_F_INDIRECT_DESC)) { 658 if (__virtio_test_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC)) {
656 char *data = __user_addr_max - USER_MEM/4; 659 char *data = __user_addr_max - USER_MEM/4;
657 struct vring_desc *d = __user_addr_max - USER_MEM/2; 660 struct vring_desc *d = __user_addr_max - USER_MEM/2;
658 struct vring vring; 661 struct vring vring;
659 662
660 /* Force creation of direct, which we modify. */ 663 /* Force creation of direct, which we modify. */
661 vdev.features[0] &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC); 664 __virtio_clear_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC);
662 vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true, 665 vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true,
663 __user_addr_min, 666 __user_addr_min,
664 never_notify_host, 667 never_notify_host,
diff --git a/tools/vm/Makefile b/tools/vm/Makefile
index 3d907dacf2ac..ac884b65a072 100644
--- a/tools/vm/Makefile
+++ b/tools/vm/Makefile
@@ -1,6 +1,6 @@
1# Makefile for vm tools 1# Makefile for vm tools
2# 2#
3TARGETS=page-types slabinfo 3TARGETS=page-types slabinfo page_owner_sort
4 4
5LIB_DIR = ../lib/api 5LIB_DIR = ../lib/api
6LIBS = $(LIB_DIR)/libapikfs.a 6LIBS = $(LIB_DIR)/libapikfs.a
@@ -18,5 +18,5 @@ $(LIBS):
18 $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) 18 $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
19 19
20clean: 20clean:
21 $(RM) page-types slabinfo 21 $(RM) page-types slabinfo page_owner_sort
22 make -C $(LIB_DIR) clean 22 make -C $(LIB_DIR) clean
diff --git a/tools/vm/page_owner_sort.c b/tools/vm/page_owner_sort.c
new file mode 100644
index 000000000000..77147b42d598
--- /dev/null
+++ b/tools/vm/page_owner_sort.c
@@ -0,0 +1,144 @@
1/*
2 * User-space helper to sort the output of /sys/kernel/debug/page_owner
3 *
4 * Example use:
5 * cat /sys/kernel/debug/page_owner > page_owner_full.txt
6 * grep -v ^PFN page_owner_full.txt > page_owner.txt
7 * ./sort page_owner.txt sorted_page_owner.txt
8*/
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16#include <string.h>
17
18struct block_list {
19 char *txt;
20 int len;
21 int num;
22};
23
24
25static struct block_list *list;
26static int list_size;
27static int max_size;
28
29struct block_list *block_head;
30
31int read_block(char *buf, int buf_size, FILE *fin)
32{
33 char *curr = buf, *const buf_end = buf + buf_size;
34
35 while (buf_end - curr > 1 && fgets(curr, buf_end - curr, fin)) {
36 if (*curr == '\n') /* empty line */
37 return curr - buf;
38 curr += strlen(curr);
39 }
40
41 return -1; /* EOF or no space left in buf. */
42}
43
44static int compare_txt(const void *p1, const void *p2)
45{
46 const struct block_list *l1 = p1, *l2 = p2;
47
48 return strcmp(l1->txt, l2->txt);
49}
50
51static int compare_num(const void *p1, const void *p2)
52{
53 const struct block_list *l1 = p1, *l2 = p2;
54
55 return l2->num - l1->num;
56}
57
58static void add_list(char *buf, int len)
59{
60 if (list_size != 0 &&
61 len == list[list_size-1].len &&
62 memcmp(buf, list[list_size-1].txt, len) == 0) {
63 list[list_size-1].num++;
64 return;
65 }
66 if (list_size == max_size) {
67 printf("max_size too small??\n");
68 exit(1);
69 }
70 list[list_size].txt = malloc(len+1);
71 list[list_size].len = len;
72 list[list_size].num = 1;
73 memcpy(list[list_size].txt, buf, len);
74 list[list_size].txt[len] = 0;
75 list_size++;
76 if (list_size % 1000 == 0) {
77 printf("loaded %d\r", list_size);
78 fflush(stdout);
79 }
80}
81
82#define BUF_SIZE 1024
83
84int main(int argc, char **argv)
85{
86 FILE *fin, *fout;
87 char buf[BUF_SIZE];
88 int ret, i, count;
89 struct block_list *list2;
90 struct stat st;
91
92 if (argc < 3) {
93 printf("Usage: ./program <input> <output>\n");
94 perror("open: ");
95 exit(1);
96 }
97
98 fin = fopen(argv[1], "r");
99 fout = fopen(argv[2], "w");
100 if (!fin || !fout) {
101 printf("Usage: ./program <input> <output>\n");
102 perror("open: ");
103 exit(1);
104 }
105
106 fstat(fileno(fin), &st);
107 max_size = st.st_size / 100; /* hack ... */
108
109 list = malloc(max_size * sizeof(*list));
110
111 for ( ; ; ) {
112 ret = read_block(buf, BUF_SIZE, fin);
113 if (ret < 0)
114 break;
115
116 add_list(buf, ret);
117 }
118
119 printf("loaded %d\n", list_size);
120
121 printf("sorting ....\n");
122
123 qsort(list, list_size, sizeof(list[0]), compare_txt);
124
125 list2 = malloc(sizeof(*list) * list_size);
126
127 printf("culling\n");
128
129 for (i = count = 0; i < list_size; i++) {
130 if (count == 0 ||
131 strcmp(list2[count-1].txt, list[i].txt) != 0) {
132 list2[count++] = list[i];
133 } else {
134 list2[count-1].num += list[i].num;
135 }
136 }
137
138 qsort(list2, count, sizeof(list[0]), compare_num);
139
140 for (i = 0; i < count; i++)
141 fprintf(fout, "%d times:\n%s\n", list2[i].num, list2[i].txt);
142
143 return 0;
144}