aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2014-11-20 08:42:02 -0500
committerJiri Kosina <jkosina@suse.cz>2014-11-20 08:42:02 -0500
commita02001086bbfb4da35d1228bebc2f1b442db455f (patch)
tree62ab47936cef06fd08657ca5b6cd1df98c19be57 /tools
parenteff264efeeb0898408e8c9df72d8a32621035bed (diff)
parentfc14f9c1272f62c3e8d01300f52467c0d9af50f9 (diff)
Merge Linus' tree to be be to apply submitted patches to newer code than
current trivial.git base
Diffstat (limited to 'tools')
-rw-r--r--tools/include/tools/endian.h56
-rw-r--r--tools/lib/api/Makefile7
-rw-r--r--tools/lib/api/fd/array.c127
-rw-r--r--tools/lib/api/fd/array.h46
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/perf-diff.txt6
-rw-r--r--tools/perf/Documentation/perf-kvm.txt4
-rw-r--r--tools/perf/Documentation/perf-list.txt2
-rw-r--r--tools/perf/Documentation/perf-probe.txt3
-rw-r--r--tools/perf/Documentation/perf-record.txt2
-rw-r--r--tools/perf/Documentation/perf-report.txt5
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt4
-rw-r--r--tools/perf/Documentation/perf-script-python.txt6
-rw-r--r--tools/perf/Documentation/perf-script.txt4
-rw-r--r--tools/perf/Documentation/perf-test.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt9
-rw-r--r--tools/perf/Documentation/perf-trace.txt2
-rw-r--r--tools/perf/Makefile.perf11
-rw-r--r--tools/perf/arch/arm/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/arm/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/arm64/include/perf_regs.h2
-rw-r--r--tools/perf/arch/arm64/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/common.c9
-rw-r--r--tools/perf/arch/powerpc/Makefile2
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c1
-rw-r--r--tools/perf/bench/futex-hash.c7
-rw-r--r--tools/perf/bench/futex-requeue.c28
-rw-r--r--tools/perf/bench/futex-wake.c15
-rw-r--r--tools/perf/bench/sched-messaging.c2
-rw-r--r--tools/perf/builtin-annotate.c89
-rw-r--r--tools/perf/builtin-buildid-cache.c44
-rw-r--r--tools/perf/builtin-diff.c32
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-help.c20
-rw-r--r--tools/perf/builtin-inject.c33
-rw-r--r--tools/perf/builtin-kmem.c56
-rw-r--r--tools/perf/builtin-kvm.c113
-rw-r--r--tools/perf/builtin-lock.c7
-rw-r--r--tools/perf/builtin-mem.c6
-rw-r--r--tools/perf/builtin-probe.c12
-rw-r--r--tools/perf/builtin-record.c148
-rw-r--r--tools/perf/builtin-report.c54
-rw-r--r--tools/perf/builtin-sched.c12
-rw-r--r--tools/perf/builtin-script.c96
-rw-r--r--tools/perf/builtin-stat.c12
-rw-r--r--tools/perf/builtin-timechart.c8
-rw-r--r--tools/perf/builtin-top.c135
-rw-r--r--tools/perf/builtin-trace.c73
-rw-r--r--tools/perf/config/Makefile52
-rw-r--r--tools/perf/config/feature-checks/Makefile18
-rw-r--r--tools/perf/config/utilities.mak2
-rw-r--r--tools/perf/perf-sys.h30
-rw-r--r--tools/perf/perf-with-kcore.sh259
-rw-r--r--tools/perf/perf.c10
-rw-r--r--tools/perf/perf.h3
-rw-r--r--tools/perf/tests/builtin-test.c23
-rw-r--r--tools/perf/tests/dwarf-unwind.c3
-rw-r--r--tools/perf/tests/fdarray.c174
-rw-r--r--tools/perf/tests/hists_cumulate.c8
-rw-r--r--tools/perf/tests/hists_filter.c23
-rw-r--r--tools/perf/tests/hists_link.c23
-rw-r--r--tools/perf/tests/hists_output.c20
-rw-r--r--tools/perf/tests/mmap-basic.c7
-rw-r--r--tools/perf/tests/open-syscall-all-cpus.c5
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c9
-rw-r--r--tools/perf/tests/open-syscall.c3
-rw-r--r--tools/perf/tests/parse-events.c36
-rw-r--r--tools/perf/tests/perf-record.c15
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/rdpmc.c6
-rw-r--r--tools/perf/tests/sw-clock.c6
-rw-r--r--tools/perf/tests/switch-tracking.c572
-rw-r--r--tools/perf/tests/task-exit.c8
-rw-r--r--tools/perf/tests/tests.h3
-rw-r--r--tools/perf/ui/browsers/header.c1
-rw-r--r--tools/perf/ui/browsers/hists.c436
-rw-r--r--tools/perf/ui/gtk/hists.c20
-rw-r--r--tools/perf/ui/hist.c284
-rw-r--r--tools/perf/ui/stdio/hist.c4
-rw-r--r--tools/perf/util/annotate.c29
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c240
-rw-r--r--tools/perf/util/callchain.h8
-rw-r--r--tools/perf/util/cloexec.c35
-rw-r--r--tools/perf/util/color.c16
-rw-r--r--tools/perf/util/color.h1
-rw-r--r--tools/perf/util/comm.c7
-rw-r--r--tools/perf/util/comm.h6
-rw-r--r--tools/perf/util/config.c40
-rw-r--r--tools/perf/util/data.c8
-rw-r--r--tools/perf/util/debug.c36
-rw-r--r--tools/perf/util/debug.h11
-rw-r--r--tools/perf/util/dso.c121
-rw-r--r--tools/perf/util/dso.h16
-rw-r--r--tools/perf/util/event.c14
-rw-r--r--tools/perf/util/event.h28
-rw-r--r--tools/perf/util/evlist.c285
-rw-r--r--tools/perf/util/evlist.h23
-rw-r--r--tools/perf/util/evsel.c144
-rw-r--r--tools/perf/util/evsel.h19
-rw-r--r--tools/perf/util/header.c59
-rw-r--r--tools/perf/util/hist.c95
-rw-r--r--tools/perf/util/hist.h67
-rw-r--r--tools/perf/util/include/linux/string.h1
-rw-r--r--tools/perf/util/kvm-stat.h1
-rw-r--r--tools/perf/util/machine.c102
-rw-r--r--tools/perf/util/machine.h26
-rw-r--r--tools/perf/util/map.c9
-rw-r--r--tools/perf/util/ordered-events.c286
-rw-r--r--tools/perf/util/ordered-events.h59
-rw-r--r--tools/perf/util/parse-events.c162
-rw-r--r--tools/perf/util/parse-events.h14
-rw-r--r--tools/perf/util/parse-events.l30
-rw-r--r--tools/perf/util/parse-events.y50
-rw-r--r--tools/perf/util/pmu.c127
-rw-r--r--tools/perf/util/pmu.h35
-rw-r--r--tools/perf/util/probe-event.c181
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/probe-finder.c23
-rw-r--r--tools/perf/util/python.c6
-rw-r--r--tools/perf/util/record.c40
-rw-r--r--tools/perf/util/run-command.c9
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c121
-rw-r--r--tools/perf/util/session.c324
-rw-r--r--tools/perf/util/session.h33
-rw-r--r--tools/perf/util/sort.c221
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/string.c114
-rw-r--r--tools/perf/util/symbol-elf.c31
-rw-r--r--tools/perf/util/symbol.c51
-rw-r--r--tools/perf/util/symbol.h16
-rw-r--r--tools/perf/util/thread.c33
-rw-r--r--tools/perf/util/thread.h10
-rw-r--r--tools/perf/util/thread_map.c21
-rw-r--r--tools/perf/util/thread_map.h1
-rw-r--r--tools/perf/util/tool.h2
-rw-r--r--tools/perf/util/trace-event-scripting.c7
-rw-r--r--tools/perf/util/trace-event.h1
-rw-r--r--tools/perf/util/unwind-libunwind.c49
-rw-r--r--tools/perf/util/unwind.h20
-rw-r--r--tools/perf/util/util.c62
-rw-r--r--tools/perf/util/util.h23
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c8
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c2
-rw-r--r--tools/power/x86/turbostat/turbostat.c80
-rwxr-xr-xtools/testing/ktest/ktest.pl61
-rw-r--r--tools/testing/ktest/sample.conf10
-rw-r--r--tools/testing/selftests/Makefile3
-rw-r--r--tools/testing/selftests/ftrace/Makefile7
-rw-r--r--tools/testing/selftests/ftrace/README82
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest253
-rw-r--r--tools/testing/selftests/ftrace/samples/fail.tc4
-rw-r--r--tools/testing/selftests/ftrace/samples/pass.tc3
-rw-r--r--tools/testing/selftests/ftrace/samples/unresolved.tc4
-rw-r--r--tools/testing/selftests/ftrace/samples/unsupported.tc3
-rw-r--r--tools/testing/selftests/ftrace/samples/untested.tc3
-rw-r--r--tools/testing/selftests/ftrace/samples/xfail.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/basic1.tc3
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/basic2.tc7
-rw-r--r--tools/testing/selftests/ftrace/test.d/00basic/basic3.tc8
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc11
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc13
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc16
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc15
-rw-r--r--tools/testing/selftests/ftrace/test.d/template9
-rw-r--r--tools/testing/selftests/ipc/Makefile6
-rw-r--r--tools/testing/selftests/kcmp/Makefile6
-rw-r--r--tools/testing/selftests/memfd/.gitignore4
-rw-r--r--tools/testing/selftests/memfd/Makefile20
-rw-r--r--tools/testing/selftests/memfd/fuse_mnt.c110
-rw-r--r--tools/testing/selftests/memfd/fuse_test.c311
-rw-r--r--tools/testing/selftests/memfd/memfd_test.c911
-rw-r--r--tools/testing/selftests/memfd/run_fuse_test.sh14
-rw-r--r--tools/testing/selftests/mount/Makefile17
-rw-r--r--tools/testing/selftests/mount/unprivileged-remount-test.c242
-rw-r--r--tools/testing/selftests/net/psock_fanout.c2
-rw-r--r--tools/testing/selftests/powerpc/Makefile12
-rw-r--r--tools/testing/selftests/powerpc/pmu/Makefile19
-rw-r--r--tools/testing/selftests/powerpc/pmu/count_instructions.c30
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/busy_loop.S271
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c91
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb.c261
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb.h1
-rw-r--r--tools/testing/selftests/powerpc/pmu/l3_bank_test.c48
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.c50
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.h1
-rw-r--r--tools/testing/selftests/powerpc/pmu/per_event_excludes.c114
-rw-r--r--tools/testing/selftests/powerpc/primitives/Makefile17
l---------tools/testing/selftests/powerpc/primitives/asm/asm-compat.h1
-rw-r--r--tools/testing/selftests/powerpc/primitives/asm/ppc-opcode.h0
-rw-r--r--tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c147
l---------tools/testing/selftests/powerpc/primitives/word-at-a-time.h1
-rw-r--r--tools/testing/selftests/ptrace/peeksiginfo.c4
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/rcutorture/bin/config2frag.sh4
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/configcheck.sh4
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/configinit.sh4
-rw-r--r--tools/testing/selftests/rcutorture/bin/functions.sh20
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-build.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh5
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/rcutorture/bin/kvm.sh6
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-build.sh5
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-console.sh9
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-torture.sh5
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/CFLIST3
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK026
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK02.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK036
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK03.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK046
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/LOCK04.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFLIST3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS019
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS01.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS025
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS02.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS0313
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE014
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE073
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE07.boot1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh2
-rw-r--r--tools/testing/selftests/rcutorture/doc/initrd.txt1
-rw-r--r--tools/testing/selftests/vm/Makefile1
-rw-r--r--tools/testing/selftests/vm/transhuge-stress.c144
-rw-r--r--tools/usb/ffs-test.c126
-rw-r--r--tools/usb/usbip/.gitignore28
-rw-r--r--tools/usb/usbip/AUTHORS3
-rw-r--r--tools/usb/usbip/COPYING340
-rw-r--r--tools/usb/usbip/INSTALL237
-rw-r--r--tools/usb/usbip/Makefile.am6
-rw-r--r--tools/usb/usbip/README202
-rwxr-xr-xtools/usb/usbip/autogen.sh9
-rwxr-xr-xtools/usb/usbip/cleanup.sh12
-rw-r--r--tools/usb/usbip/configure.ac111
-rw-r--r--tools/usb/usbip/doc/usbip.895
-rw-r--r--tools/usb/usbip/doc/usbipd.891
-rw-r--r--tools/usb/usbip/libsrc/Makefile.am8
-rw-r--r--tools/usb/usbip/libsrc/list.h136
-rw-r--r--tools/usb/usbip/libsrc/names.c504
-rw-r--r--tools/usb/usbip/libsrc/names.h41
-rw-r--r--tools/usb/usbip/libsrc/sysfs_utils.c31
-rw-r--r--tools/usb/usbip/libsrc/sysfs_utils.h8
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.c285
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.h137
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_driver.c280
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_driver.h49
-rw-r--r--tools/usb/usbip/libsrc/vhci_driver.c411
-rw-r--r--tools/usb/usbip/libsrc/vhci_driver.h59
-rw-r--r--tools/usb/usbip/src/Makefile.am11
-rw-r--r--tools/usb/usbip/src/usbip.c201
-rw-r--r--tools/usb/usbip/src/usbip.h40
-rw-r--r--tools/usb/usbip/src/usbip_attach.c241
-rw-r--r--tools/usb/usbip/src/usbip_bind.c214
-rw-r--r--tools/usb/usbip/src/usbip_detach.c110
-rw-r--r--tools/usb/usbip/src/usbip_list.c283
-rw-r--r--tools/usb/usbip/src/usbip_network.c303
-rw-r--r--tools/usb/usbip/src/usbip_network.h185
-rw-r--r--tools/usb/usbip/src/usbip_port.c57
-rw-r--r--tools/usb/usbip/src/usbip_unbind.c141
-rw-r--r--tools/usb/usbip/src/usbipd.c679
-rw-r--r--tools/usb/usbip/src/utils.c52
-rw-r--r--tools/usb/usbip/src/utils.h25
-rw-r--r--tools/vm/page-types.c1
270 files changed, 14089 insertions, 2277 deletions
diff --git a/tools/include/tools/endian.h b/tools/include/tools/endian.h
new file mode 100644
index 000000000000..8001194008da
--- /dev/null
+++ b/tools/include/tools/endian.h
@@ -0,0 +1,56 @@
1#ifndef _TOOLS_ENDIAN_H
2#define _TOOLS_ENDIAN_H
3
4#include <byteswap.h>
5
6#if __BYTE_ORDER == __LITTLE_ENDIAN
7
8#ifndef htole16
9#define htole16(x) (x)
10#endif
11#ifndef htole32
12#define htole32(x) (x)
13#endif
14#ifndef htole64
15#define htole64(x) (x)
16#endif
17
18#ifndef le16toh
19#define le16toh(x) (x)
20#endif
21
22#ifndef le32toh
23#define le32toh(x) (x)
24#endif
25
26#ifndef le64toh
27#define le64toh(x) (x)
28#endif
29
30#else /* __BYTE_ORDER */
31
32#ifndef htole16
33#define htole16(x) __bswap_16(x)
34#endif
35#ifndef htole32
36#define htole32(x) __bswap_32(x)
37#endif
38#ifndef htole64
39#define htole64(x) __bswap_64(x)
40#endif
41
42#ifndef le16toh
43#define le16toh(x) __bswap_16(x)
44#endif
45
46#ifndef le32toh
47#define le32toh(x) __bswap_32(x)
48#endif
49
50#ifndef le64toh
51#define le64toh(x) __bswap_64(x)
52#endif
53
54#endif
55
56#endif /* _TOOLS_ENDIAN_H */
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index ce00f7ee6455..36c08b1f4afb 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -10,9 +10,14 @@ LIB_OBJS=
10 10
11LIB_H += fs/debugfs.h 11LIB_H += fs/debugfs.h
12LIB_H += fs/fs.h 12LIB_H += fs/fs.h
13# See comment below about piggybacking...
14LIB_H += fd/array.h
13 15
14LIB_OBJS += $(OUTPUT)fs/debugfs.o 16LIB_OBJS += $(OUTPUT)fs/debugfs.o
15LIB_OBJS += $(OUTPUT)fs/fs.o 17LIB_OBJS += $(OUTPUT)fs/fs.o
18# XXX piggybacking here, need to introduce libapikfd, or rename this
19# to plain libapik.a and make it have it all api goodies
20LIB_OBJS += $(OUTPUT)fd/array.o
16 21
17LIBFILE = libapikfs.a 22LIBFILE = libapikfs.a
18 23
@@ -29,7 +34,7 @@ $(LIBFILE): $(LIB_OBJS)
29$(LIB_OBJS): $(LIB_H) 34$(LIB_OBJS): $(LIB_H)
30 35
31libapi_dirs: 36libapi_dirs:
32 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/ 37 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs
33 38
34$(OUTPUT)%.o: %.c libapi_dirs 39$(OUTPUT)%.o: %.c libapi_dirs
35 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 40 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
diff --git a/tools/lib/api/fd/array.c b/tools/lib/api/fd/array.c
new file mode 100644
index 000000000000..0e636c4339b8
--- /dev/null
+++ b/tools/lib/api/fd/array.c
@@ -0,0 +1,127 @@
1/*
2 * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Released under the GPL v2. (and only v2, not any later version)
5 */
6#include "array.h"
7#include <errno.h>
8#include <fcntl.h>
9#include <poll.h>
10#include <stdlib.h>
11#include <unistd.h>
12
13void fdarray__init(struct fdarray *fda, int nr_autogrow)
14{
15 fda->entries = NULL;
16 fda->priv = NULL;
17 fda->nr = fda->nr_alloc = 0;
18 fda->nr_autogrow = nr_autogrow;
19}
20
21int fdarray__grow(struct fdarray *fda, int nr)
22{
23 void *priv;
24 int nr_alloc = fda->nr_alloc + nr;
25 size_t psize = sizeof(fda->priv[0]) * nr_alloc;
26 size_t size = sizeof(struct pollfd) * nr_alloc;
27 struct pollfd *entries = realloc(fda->entries, size);
28
29 if (entries == NULL)
30 return -ENOMEM;
31
32 priv = realloc(fda->priv, psize);
33 if (priv == NULL) {
34 free(entries);
35 return -ENOMEM;
36 }
37
38 fda->nr_alloc = nr_alloc;
39 fda->entries = entries;
40 fda->priv = priv;
41 return 0;
42}
43
44struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow)
45{
46 struct fdarray *fda = calloc(1, sizeof(*fda));
47
48 if (fda != NULL) {
49 if (fdarray__grow(fda, nr_alloc)) {
50 free(fda);
51 fda = NULL;
52 } else {
53 fda->nr_autogrow = nr_autogrow;
54 }
55 }
56
57 return fda;
58}
59
60void fdarray__exit(struct fdarray *fda)
61{
62 free(fda->entries);
63 free(fda->priv);
64 fdarray__init(fda, 0);
65}
66
67void fdarray__delete(struct fdarray *fda)
68{
69 fdarray__exit(fda);
70 free(fda);
71}
72
73int fdarray__add(struct fdarray *fda, int fd, short revents)
74{
75 int pos = fda->nr;
76
77 if (fda->nr == fda->nr_alloc &&
78 fdarray__grow(fda, fda->nr_autogrow) < 0)
79 return -ENOMEM;
80
81 fda->entries[fda->nr].fd = fd;
82 fda->entries[fda->nr].events = revents;
83 fda->nr++;
84 return pos;
85}
86
87int fdarray__filter(struct fdarray *fda, short revents,
88 void (*entry_destructor)(struct fdarray *fda, int fd))
89{
90 int fd, nr = 0;
91
92 if (fda->nr == 0)
93 return 0;
94
95 for (fd = 0; fd < fda->nr; ++fd) {
96 if (fda->entries[fd].revents & revents) {
97 if (entry_destructor)
98 entry_destructor(fda, fd);
99
100 continue;
101 }
102
103 if (fd != nr) {
104 fda->entries[nr] = fda->entries[fd];
105 fda->priv[nr] = fda->priv[fd];
106 }
107
108 ++nr;
109 }
110
111 return fda->nr = nr;
112}
113
114int fdarray__poll(struct fdarray *fda, int timeout)
115{
116 return poll(fda->entries, fda->nr, timeout);
117}
118
119int fdarray__fprintf(struct fdarray *fda, FILE *fp)
120{
121 int fd, printed = fprintf(fp, "%d [ ", fda->nr);
122
123 for (fd = 0; fd < fda->nr; ++fd)
124 printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd);
125
126 return printed + fprintf(fp, " ]");
127}
diff --git a/tools/lib/api/fd/array.h b/tools/lib/api/fd/array.h
new file mode 100644
index 000000000000..45db01818f45
--- /dev/null
+++ b/tools/lib/api/fd/array.h
@@ -0,0 +1,46 @@
1#ifndef __API_FD_ARRAY__
2#define __API_FD_ARRAY__
3
4#include <stdio.h>
5
6struct pollfd;
7
8/**
9 * struct fdarray: Array of file descriptors
10 *
11 * @priv: Per array entry priv area, users should access just its contents,
12 * not set it to anything, as it is kept in synch with @entries, being
13 * realloc'ed, * for instance, in fdarray__{grow,filter}.
14 *
15 * I.e. using 'fda->priv[N].idx = * value' where N < fda->nr is ok,
16 * but doing 'fda->priv = malloc(M)' is not allowed.
17 */
18struct fdarray {
19 int nr;
20 int nr_alloc;
21 int nr_autogrow;
22 struct pollfd *entries;
23 union {
24 int idx;
25 } *priv;
26};
27
28void fdarray__init(struct fdarray *fda, int nr_autogrow);
29void fdarray__exit(struct fdarray *fda);
30
31struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow);
32void fdarray__delete(struct fdarray *fda);
33
34int fdarray__add(struct fdarray *fda, int fd, short revents);
35int fdarray__poll(struct fdarray *fda, int timeout);
36int fdarray__filter(struct fdarray *fda, short revents,
37 void (*entry_destructor)(struct fdarray *fda, int fd));
38int fdarray__grow(struct fdarray *fda, int extra);
39int fdarray__fprintf(struct fdarray *fda, FILE *fp);
40
41static inline int fdarray__available_entries(struct fdarray *fda)
42{
43 return fda->nr_alloc - fda->nr;
44}
45
46#endif /* __API_FD_ARRAY__ */
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 782d86e961b9..717221e98450 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -15,6 +15,7 @@ perf.data
15perf.data.old 15perf.data.old
16output.svg 16output.svg
17perf-archive 17perf-archive
18perf-with-kcore
18tags 19tags
19TAGS 20TAGS
20cscope* 21cscope*
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index b3b8abae62b8..e463caa3eb49 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -196,10 +196,10 @@ If specified the 'Weighted diff' column is displayed with value 'd' computed as:
196 196
197 - period being the hist entry period value 197 - period being the hist entry period value
198 198
199 - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option 199 - WEIGHT-A/WEIGHT-B being user supplied weights in the the '-c' option
200 behind ':' separator like '-c wdiff:1,2'. 200 behind ':' separator like '-c wdiff:1,2'.
201 - WIEGHT-A being the weight of the data file 201 - WEIGHT-A being the weight of the data file
202 - WIEGHT-B being the weight of the baseline data file 202 - WEIGHT-B being the weight of the baseline data file
203 203
204SEE ALSO 204SEE ALSO
205-------- 205--------
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index 6e689dc89a2f..6252e776009c 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -100,7 +100,7 @@ OPTIONS
100STAT REPORT OPTIONS 100STAT REPORT OPTIONS
101------------------- 101-------------------
102--vcpu=<value>:: 102--vcpu=<value>::
103 analyze events which occures on this vcpu. (default: all vcpus) 103 analyze events which occur on this vcpu. (default: all vcpus)
104 104
105--event=<value>:: 105--event=<value>::
106 event to be analyzed. Possible values: vmexit, mmio (x86 only), 106 event to be analyzed. Possible values: vmexit, mmio (x86 only),
@@ -134,7 +134,7 @@ STAT LIVE OPTIONS
134 Analyze events only for given process ID(s) (comma separated list). 134 Analyze events only for given process ID(s) (comma separated list).
135 135
136--vcpu=<value>:: 136--vcpu=<value>::
137 analyze events which occures on this vcpu. (default: all vcpus) 137 analyze events which occur on this vcpu. (default: all vcpus)
138 138
139 139
140--event=<value>:: 140--event=<value>::
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 6fce6a622206..cbb4f743d921 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -19,7 +19,7 @@ various perf commands with the -e option.
19EVENT MODIFIERS 19EVENT MODIFIERS
20--------------- 20---------------
21 21
22Events can optionally have a modifer by appending a colon and one or 22Events can optionally have a modifier by appending a colon and one or
23more modifiers. Modifiers allow the user to restrict the events to be 23more modifiers. Modifiers allow the user to restrict the events to be
24counted. The following modifiers exist: 24counted. The following modifiers exist:
25 25
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 1513935c399b..aaa869be3dc1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -104,6 +104,9 @@ OPTIONS
104 Specify path to the executable or shared library file for user 104 Specify path to the executable or shared library file for user
105 space tracing. Can also be used with --funcs option. 105 space tracing. Can also be used with --funcs option.
106 106
107--demangle-kernel::
108 Demangle kernel symbols.
109
107In absence of -m/-x options, perf probe checks if the first argument after 110In absence of -m/-x options, perf probe checks if the first argument after
108the options is an absolute path name. If its an absolute path, perf probe 111the options is an absolute path name. If its an absolute path, perf probe
109uses it as a target module/target user space binary to probe. 112uses it as a target module/target user space binary to probe.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index d460049cae8e..398f8d53bd6d 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -146,7 +146,7 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
146 146
147-N:: 147-N::
148--no-buildid-cache:: 148--no-buildid-cache::
149Do not update the builid cache. This saves some overhead in situations 149Do not update the buildid cache. This saves some overhead in situations
150where the information in the perf.data file (which includes buildids) 150where the information in the perf.data file (which includes buildids)
151is sufficient. 151is sufficient.
152 152
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index d2b59af62bc0..0927bf4e6c2a 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -147,7 +147,7 @@ OPTIONS
147-w:: 147-w::
148--column-widths=<width[,width...]>:: 148--column-widths=<width[,width...]>::
149 Force each column width to the provided list, for large terminal 149 Force each column width to the provided list, for large terminal
150 readability. 150 readability. 0 means no limit (default behavior).
151 151
152-t:: 152-t::
153--field-separator=:: 153--field-separator=::
@@ -276,6 +276,9 @@ OPTIONS
276 Demangle symbol names to human readable form. It's enabled by default, 276 Demangle symbol names to human readable form. It's enabled by default,
277 disable with --no-demangle. 277 disable with --no-demangle.
278 278
279--demangle-kernel::
280 Demangle kernel symbol names to human readable form (for C++ kernels).
281
279--mem-mode:: 282--mem-mode::
280 Use the data addresses of samples in addition to instruction addresses 283 Use the data addresses of samples in addition to instruction addresses
281 to build the histograms. To generate meaningful output, the perf.data 284 to build the histograms. To generate meaningful output, the perf.data
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index d00bef231340..dfbb506d2c34 100644
--- a/tools/perf/Documentation/perf-script-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -181,8 +181,8 @@ strings for flag and symbolic fields. These correspond to the strings
181and values parsed from the 'print fmt' fields of the event format 181and values parsed from the 'print fmt' fields of the event format
182files: 182files:
183 183
184 flag_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the flag field $field_name of event $event_name 184 flag_str($event_name, $field_name, $field_value) - returns the string representation corresponding to $field_value for the flag field $field_name of event $event_name
185 symbol_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the symbolic field $field_name of event $event_name 185 symbol_str($event_name, $field_name, $field_value) - returns the string representation corresponding to $field_value for the symbolic field $field_name of event $event_name
186 186
187Perf::Trace::Context Module 187Perf::Trace::Context Module
188~~~~~~~~~~~~~~~~~~~~~~~~~~~ 188~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 9f1f054b8432..54acba221558 100644
--- a/tools/perf/Documentation/perf-script-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -263,7 +263,7 @@ and having the counts we've tallied as values.
263 263
264The print_syscall_totals() function iterates over the entries in the 264The print_syscall_totals() function iterates over the entries in the
265dictionary and displays a line for each entry containing the syscall 265dictionary and displays a line for each entry containing the syscall
266name (the dictonary keys contain the syscall ids, which are passed to 266name (the dictionary keys contain the syscall ids, which are passed to
267the Util function syscall_name(), which translates the raw syscall 267the Util function syscall_name(), which translates the raw syscall
268numbers to the corresponding syscall name strings). The output is 268numbers to the corresponding syscall name strings). The output is
269displayed after all the events in the trace have been processed, by 269displayed after all the events in the trace have been processed, by
@@ -576,8 +576,8 @@ strings for flag and symbolic fields. These correspond to the strings
576and values parsed from the 'print fmt' fields of the event format 576and values parsed from the 'print fmt' fields of the event format
577files: 577files:
578 578
579 flag_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the flag field field_name of event event_name 579 flag_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the flag field field_name of event event_name
580 symbol_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the symbolic field field_name of event event_name 580 symbol_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the symbolic field field_name of event event_name
581 581
582The *autodict* function returns a special kind of Python 582The *autodict* function returns a special kind of Python
583dictionary that implements Perl's 'autovivifying' hashes in Python 583dictionary that implements Perl's 'autovivifying' hashes in Python
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 05f9a0a6784c..21494806c0ab 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,7 +115,7 @@ OPTIONS
115-f:: 115-f::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline. 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline, period.
119 Field list can be prepended with the type, trace, sw or hw, 119 Field list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -140,7 +140,7 @@ OPTIONS
140 140
141 "Overriding previous field request for all events." 141 "Overriding previous field request for all events."
142 142
143 Alternativey, consider the order: 143 Alternatively, consider the order:
144 144
145 -f comm,tid,time,ip,sym -f trace: 145 -f comm,tid,time,ip,sym -f trace:
146 146
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index d1d3e5121f89..31a5c3ea7f74 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -25,7 +25,7 @@ OPTIONS
25------- 25-------
26-s:: 26-s::
27--skip:: 27--skip::
28 Tests to skip (comma separater numeric list). 28 Tests to skip (comma separated numeric list).
29 29
30-v:: 30-v::
31--verbose:: 31--verbose::
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 180ae02137a5..3265b1070518 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -98,6 +98,9 @@ Default is to monitor all CPUS.
98--hide_user_symbols:: 98--hide_user_symbols::
99 Hide user symbols. 99 Hide user symbols.
100 100
101--demangle-kernel::
102 Demangle kernel symbols.
103
101-D:: 104-D::
102--dump-symtab:: 105--dump-symtab::
103 Dump the symbol table used for profiling. 106 Dump the symbol table used for profiling.
@@ -193,6 +196,12 @@ Default is to monitor all CPUS.
193 sum of shown entries will be always 100%. "absolute" means it retains 196 sum of shown entries will be always 100%. "absolute" means it retains
194 the original value before and after the filter is applied. 197 the original value before and after the filter is applied.
195 198
199-w::
200--column-widths=<width[,width...]>::
201 Force each column width to the provided list, for large terminal
202 readability. 0 means no limit (default behavior).
203
204
196INTERACTIVE PROMPTING KEYS 205INTERACTIVE PROMPTING KEYS
197-------------------------- 206--------------------------
198 207
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 02aac831bdd9..7e1b1f2bb83c 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -20,7 +20,7 @@ scheduling events, etc.
20This is a live mode tool in addition to working with perf.data files like 20This is a live mode tool in addition to working with perf.data files like
21the other perf tools. Files can be generated using the 'perf record' command 21the other perf tools. Files can be generated using the 'perf record' command
22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*'). 22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*').
23Alernatively, the 'perf trace record' can be used as a shortcut to 23Alternatively, 'perf trace record' can be used as a shortcut to
24automatically include the raw_syscalls events when writing events to a file. 24automatically include the raw_syscalls events when writing events to a file.
25 25
26The following options apply to perf trace; options to perf trace record are 26The following options apply to perf trace; options to perf trace record are
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2240974b7745..262916f4a377 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -126,6 +126,7 @@ PYRF_OBJS =
126SCRIPT_SH = 126SCRIPT_SH =
127 127
128SCRIPT_SH += perf-archive.sh 128SCRIPT_SH += perf-archive.sh
129SCRIPT_SH += perf-with-kcore.sh
129 130
130grep-libs = $(filter -l%,$(1)) 131grep-libs = $(filter -l%,$(1))
131strip-libs = $(filter-out -l%,$(1)) 132strip-libs = $(filter-out -l%,$(1))
@@ -263,6 +264,7 @@ LIB_H += util/xyarray.h
263LIB_H += util/header.h 264LIB_H += util/header.h
264LIB_H += util/help.h 265LIB_H += util/help.h
265LIB_H += util/session.h 266LIB_H += util/session.h
267LIB_H += util/ordered-events.h
266LIB_H += util/strbuf.h 268LIB_H += util/strbuf.h
267LIB_H += util/strlist.h 269LIB_H += util/strlist.h
268LIB_H += util/strfilter.h 270LIB_H += util/strfilter.h
@@ -347,6 +349,7 @@ LIB_OBJS += $(OUTPUT)util/machine.o
347LIB_OBJS += $(OUTPUT)util/map.o 349LIB_OBJS += $(OUTPUT)util/map.o
348LIB_OBJS += $(OUTPUT)util/pstack.o 350LIB_OBJS += $(OUTPUT)util/pstack.o
349LIB_OBJS += $(OUTPUT)util/session.o 351LIB_OBJS += $(OUTPUT)util/session.o
352LIB_OBJS += $(OUTPUT)util/ordered-events.o
350LIB_OBJS += $(OUTPUT)util/comm.o 353LIB_OBJS += $(OUTPUT)util/comm.o
351LIB_OBJS += $(OUTPUT)util/thread.o 354LIB_OBJS += $(OUTPUT)util/thread.o
352LIB_OBJS += $(OUTPUT)util/thread_map.o 355LIB_OBJS += $(OUTPUT)util/thread_map.o
@@ -399,6 +402,7 @@ LIB_OBJS += $(OUTPUT)tests/perf-record.o
399LIB_OBJS += $(OUTPUT)tests/rdpmc.o 402LIB_OBJS += $(OUTPUT)tests/rdpmc.o
400LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o 403LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
401LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o 404LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
405LIB_OBJS += $(OUTPUT)tests/fdarray.o
402LIB_OBJS += $(OUTPUT)tests/pmu.o 406LIB_OBJS += $(OUTPUT)tests/pmu.o
403LIB_OBJS += $(OUTPUT)tests/hists_common.o 407LIB_OBJS += $(OUTPUT)tests/hists_common.o
404LIB_OBJS += $(OUTPUT)tests/hists_link.o 408LIB_OBJS += $(OUTPUT)tests/hists_link.o
@@ -423,6 +427,7 @@ endif
423endif 427endif
424LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o 428LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
425LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o 429LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
430LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
426 431
427BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 432BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
428BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 433BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -765,7 +770,7 @@ $(LIBTRACEEVENT)-clean:
765install-traceevent-plugins: $(LIBTRACEEVENT) 770install-traceevent-plugins: $(LIBTRACEEVENT)
766 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins 771 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
767 772
768LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch]) 773LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch] $(LIB_PATH)fd/*.[ch])
769 774
770# if subdir is set, we've been called from above so target has been built 775# if subdir is set, we've been called from above so target has been built
771# already 776# already
@@ -875,6 +880,8 @@ install-bin: all install-gtk
875 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 880 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
876 $(call QUIET_INSTALL, perf-archive) \ 881 $(call QUIET_INSTALL, perf-archive) \
877 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 882 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
883 $(call QUIET_INSTALL, perf-with-kcore) \
884 $(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
878ifndef NO_LIBPERL 885ifndef NO_LIBPERL
879 $(call QUIET_INSTALL, perl-scripts) \ 886 $(call QUIET_INSTALL, perl-scripts) \
880 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \ 887 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
@@ -920,7 +927,7 @@ config-clean:
920 @$(MAKE) -C config/feature-checks clean >/dev/null 927 @$(MAKE) -C config/feature-checks clean >/dev/null
921 928
922clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 929clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
923 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 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)
924 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 931 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
925 $(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* 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*
926 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 933 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
diff --git a/tools/perf/arch/arm/tests/dwarf-unwind.c b/tools/perf/arch/arm/tests/dwarf-unwind.c
index 9f870d27cb39..62eff847f91c 100644
--- a/tools/perf/arch/arm/tests/dwarf-unwind.c
+++ b/tools/perf/arch/arm/tests/dwarf-unwind.c
@@ -3,6 +3,7 @@
3#include "thread.h" 3#include "thread.h"
4#include "map.h" 4#include "map.h"
5#include "event.h" 5#include "event.h"
6#include "debug.h"
6#include "tests/tests.h" 7#include "tests/tests.h"
7 8
8#define STACK_SIZE 8192 9#define STACK_SIZE 8192
diff --git a/tools/perf/arch/arm/util/unwind-libunwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c
index 729ed69a6664..62c397ed3d97 100644
--- a/tools/perf/arch/arm/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7int libunwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
8{ 9{
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
index e9441b9e2a30..1d3f39c3aa56 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -6,6 +6,8 @@
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1) 8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_ARM64_MAX
10
9#define PERF_REG_IP PERF_REG_ARM64_PC 11#define PERF_REG_IP PERF_REG_ARM64_PC
10#define PERF_REG_SP PERF_REG_ARM64_SP 12#define PERF_REG_SP PERF_REG_ARM64_SP
11 13
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c
index 436ee43859dc..a87afa91a99e 100644
--- a/tools/perf/arch/arm64/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm64/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7int libunwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
8{ 9{
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 42faf369211c..49776f190abf 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -12,6 +12,11 @@ const char *const arm_triplets[] = {
12 NULL 12 NULL
13}; 13};
14 14
15const char *const arm64_triplets[] = {
16 "aarch64-linux-android-",
17 NULL
18};
19
15const char *const powerpc_triplets[] = { 20const char *const powerpc_triplets[] = {
16 "powerpc-unknown-linux-gnu-", 21 "powerpc-unknown-linux-gnu-",
17 "powerpc64-unknown-linux-gnu-", 22 "powerpc64-unknown-linux-gnu-",
@@ -105,6 +110,8 @@ static const char *normalize_arch(char *arch)
105 return "x86"; 110 return "x86";
106 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5)) 111 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5))
107 return "sparc"; 112 return "sparc";
113 if (!strcmp(arch, "aarch64") || !strcmp(arch, "arm64"))
114 return "arm64";
108 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110")) 115 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110"))
109 return "arm"; 116 return "arm";
110 if (!strncmp(arch, "s390", 4)) 117 if (!strncmp(arch, "s390", 4))
@@ -159,6 +166,8 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
159 166
160 if (!strcmp(arch, "arm")) 167 if (!strcmp(arch, "arm"))
161 path_list = arm_triplets; 168 path_list = arm_triplets;
169 else if (!strcmp(arch, "arm64"))
170 path_list = arm64_triplets;
162 else if (!strcmp(arch, "powerpc")) 171 else if (!strcmp(arch, "powerpc"))
163 path_list = powerpc_triplets; 172 path_list = powerpc_triplets;
164 else if (!strcmp(arch, "sh")) 173 else if (!strcmp(arch, "sh"))
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index b92219b1900d..6f7782bea5dd 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -1,6 +1,6 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
4endif 5endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o 6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index a7c23a4b3778..d73ef8bb08c7 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -15,6 +15,7 @@
15 15
16#include "util/thread.h" 16#include "util/thread.h"
17#include "util/callchain.h" 17#include "util/callchain.h"
18#include "util/debug.h"
18 19
19/* 20/*
20 * When saving the callchain on Power, the kernel conservatively saves 21 * When saving the callchain on Power, the kernel conservatively saves
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index a84206e9c4aa..fc9bebd2cca0 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -26,6 +26,7 @@ static unsigned int nsecs = 10;
26/* amount of futexes per thread */ 26/* amount of futexes per thread */
27static unsigned int nfutexes = 1024; 27static unsigned int nfutexes = 1024;
28static bool fshared = false, done = false, silent = false; 28static bool fshared = false, done = false, silent = false;
29static int futex_flag = 0;
29 30
30struct timeval start, end, runtime; 31struct timeval start, end, runtime;
31static pthread_mutex_t thread_lock; 32static pthread_mutex_t thread_lock;
@@ -75,8 +76,7 @@ static void *workerfn(void *arg)
75 * such as internal waitqueue handling, thus enlarging 76 * such as internal waitqueue handling, thus enlarging
76 * the critical region protected by hb->lock. 77 * the critical region protected by hb->lock.
77 */ 78 */
78 ret = futex_wait(&w->futex[i], 1234, NULL, 79 ret = futex_wait(&w->futex[i], 1234, NULL, futex_flag);
79 fshared ? 0 : FUTEX_PRIVATE_FLAG);
80 if (!silent && 80 if (!silent &&
81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK)) 81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK))
82 warn("Non-expected futex return call"); 82 warn("Non-expected futex return call");
@@ -135,6 +135,9 @@ int bench_futex_hash(int argc, const char **argv,
135 if (!worker) 135 if (!worker)
136 goto errmem; 136 goto errmem;
137 137
138 if (!fshared)
139 futex_flag = FUTEX_PRIVATE_FLAG;
140
138 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n", 141 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n",
139 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs); 142 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs);
140 143
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 732403bfd31a..bedff6b5b3cf 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -30,16 +30,18 @@ static u_int32_t futex1 = 0, futex2 = 0;
30static unsigned int nrequeue = 1; 30static unsigned int nrequeue = 1;
31 31
32static pthread_t *worker; 32static pthread_t *worker;
33static bool done = 0, silent = 0; 33static bool done = false, silent = false, fshared = false;
34static pthread_mutex_t thread_lock; 34static pthread_mutex_t thread_lock;
35static pthread_cond_t thread_parent, thread_worker; 35static pthread_cond_t thread_parent, thread_worker;
36static struct stats requeuetime_stats, requeued_stats; 36static struct stats requeuetime_stats, requeued_stats;
37static unsigned int ncpus, threads_starting, nthreads = 0; 37static unsigned int ncpus, threads_starting, nthreads = 0;
38static int futex_flag = 0;
38 39
39static const struct option options[] = { 40static const struct option options[] = {
40 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 41 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
41 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"), 42 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"),
42 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"), 43 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
44 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
43 OPT_END() 45 OPT_END()
44}; 46};
45 47
@@ -70,7 +72,7 @@ static void *workerfn(void *arg __maybe_unused)
70 pthread_cond_wait(&thread_worker, &thread_lock); 72 pthread_cond_wait(&thread_worker, &thread_lock);
71 pthread_mutex_unlock(&thread_lock); 73 pthread_mutex_unlock(&thread_lock);
72 74
73 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG); 75 futex_wait(&futex1, 0, NULL, futex_flag);
74 return NULL; 76 return NULL;
75} 77}
76 78
@@ -127,9 +129,12 @@ int bench_futex_requeue(int argc, const char **argv,
127 if (!worker) 129 if (!worker)
128 err(EXIT_FAILURE, "calloc"); 130 err(EXIT_FAILURE, "calloc");
129 131
130 printf("Run summary [PID %d]: Requeuing %d threads (from %p to %p), " 132 if (!fshared)
131 "%d at a time.\n\n", 133 futex_flag = FUTEX_PRIVATE_FLAG;
132 getpid(), nthreads, &futex1, &futex2, nrequeue); 134
135 printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
136 "%d at a time.\n\n", getpid(), nthreads,
137 fshared ? "shared":"private", &futex1, &futex2, nrequeue);
133 138
134 init_stats(&requeued_stats); 139 init_stats(&requeued_stats);
135 init_stats(&requeuetime_stats); 140 init_stats(&requeuetime_stats);
@@ -156,16 +161,20 @@ int bench_futex_requeue(int argc, const char **argv,
156 161
157 /* Ok, all threads are patiently blocked, start requeueing */ 162 /* Ok, all threads are patiently blocked, start requeueing */
158 gettimeofday(&start, NULL); 163 gettimeofday(&start, NULL);
159 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) 164 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) {
160 /* 165 /*
161 * Do not wakeup any tasks blocked on futex1, allowing 166 * Do not wakeup any tasks blocked on futex1, allowing
162 * us to really measure futex_wait functionality. 167 * us to really measure futex_wait functionality.
163 */ 168 */
164 futex_cmp_requeue(&futex1, 0, &futex2, 0, nrequeue, 169 futex_cmp_requeue(&futex1, 0, &futex2, 0,
165 FUTEX_PRIVATE_FLAG); 170 nrequeue, futex_flag);
171 }
166 gettimeofday(&end, NULL); 172 gettimeofday(&end, NULL);
167 timersub(&end, &start, &runtime); 173 timersub(&end, &start, &runtime);
168 174
175 if (nrequeued > nthreads)
176 nrequeued = nthreads;
177
169 update_stats(&requeued_stats, nrequeued); 178 update_stats(&requeued_stats, nrequeued);
170 update_stats(&requeuetime_stats, runtime.tv_usec); 179 update_stats(&requeuetime_stats, runtime.tv_usec);
171 180
@@ -175,7 +184,7 @@ int bench_futex_requeue(int argc, const char **argv,
175 } 184 }
176 185
177 /* everybody should be blocked on futex2, wake'em up */ 186 /* everybody should be blocked on futex2, wake'em up */
178 nrequeued = futex_wake(&futex2, nthreads, FUTEX_PRIVATE_FLAG); 187 nrequeued = futex_wake(&futex2, nthreads, futex_flag);
179 if (nthreads != nrequeued) 188 if (nthreads != nrequeued)
180 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads); 189 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
181 190
@@ -184,7 +193,6 @@ int bench_futex_requeue(int argc, const char **argv,
184 if (ret) 193 if (ret)
185 err(EXIT_FAILURE, "pthread_join"); 194 err(EXIT_FAILURE, "pthread_join");
186 } 195 }
187
188 } 196 }
189 197
190 /* cleanup & report results */ 198 /* cleanup & report results */
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 50022cbce87e..929f762be47e 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -31,16 +31,18 @@ static u_int32_t futex1 = 0;
31static unsigned int nwakes = 1; 31static unsigned int nwakes = 1;
32 32
33pthread_t *worker; 33pthread_t *worker;
34static bool done = false, silent = false; 34static bool done = false, silent = false, fshared = false;
35static pthread_mutex_t thread_lock; 35static pthread_mutex_t thread_lock;
36static pthread_cond_t thread_parent, thread_worker; 36static pthread_cond_t thread_parent, thread_worker;
37static struct stats waketime_stats, wakeup_stats; 37static struct stats waketime_stats, wakeup_stats;
38static unsigned int ncpus, threads_starting, nthreads = 0; 38static unsigned int ncpus, threads_starting, nthreads = 0;
39static int futex_flag = 0;
39 40
40static const struct option options[] = { 41static const struct option options[] = {
41 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 42 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
42 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"), 43 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"),
43 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"), 44 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
45 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
44 OPT_END() 46 OPT_END()
45}; 47};
46 48
@@ -58,7 +60,7 @@ static void *workerfn(void *arg __maybe_unused)
58 pthread_cond_wait(&thread_worker, &thread_lock); 60 pthread_cond_wait(&thread_worker, &thread_lock);
59 pthread_mutex_unlock(&thread_lock); 61 pthread_mutex_unlock(&thread_lock);
60 62
61 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG); 63 futex_wait(&futex1, 0, NULL, futex_flag);
62 return NULL; 64 return NULL;
63} 65}
64 66
@@ -130,9 +132,12 @@ int bench_futex_wake(int argc, const char **argv,
130 if (!worker) 132 if (!worker)
131 err(EXIT_FAILURE, "calloc"); 133 err(EXIT_FAILURE, "calloc");
132 134
133 printf("Run summary [PID %d]: blocking on %d threads (at futex %p), " 135 if (!fshared)
136 futex_flag = FUTEX_PRIVATE_FLAG;
137
138 printf("Run summary [PID %d]: blocking on %d threads (at [%s] futex %p), "
134 "waking up %d at a time.\n\n", 139 "waking up %d at a time.\n\n",
135 getpid(), nthreads, &futex1, nwakes); 140 getpid(), nthreads, fshared ? "shared":"private", &futex1, nwakes);
136 141
137 init_stats(&wakeup_stats); 142 init_stats(&wakeup_stats);
138 init_stats(&waketime_stats); 143 init_stats(&waketime_stats);
@@ -160,7 +165,7 @@ int bench_futex_wake(int argc, const char **argv,
160 /* Ok, all threads are patiently blocked, start waking folks up */ 165 /* Ok, all threads are patiently blocked, start waking folks up */
161 gettimeofday(&start, NULL); 166 gettimeofday(&start, NULL);
162 while (nwoken != nthreads) 167 while (nwoken != nthreads)
163 nwoken += futex_wake(&futex1, nwakes, FUTEX_PRIVATE_FLAG); 168 nwoken += futex_wake(&futex1, nwakes, futex_flag);
164 gettimeofday(&end, NULL); 169 gettimeofday(&end, NULL);
165 timersub(&end, &start, &runtime); 170 timersub(&end, &start, &runtime);
166 171
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index 52a56599a543..d7f281c2828d 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -26,7 +26,7 @@
26#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/wait.h> 27#include <sys/wait.h>
28#include <sys/time.h> 28#include <sys/time.h>
29#include <sys/poll.h> 29#include <poll.h>
30#include <limits.h> 30#include <limits.h>
31#include <err.h> 31#include <err.h>
32 32
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec429fef2be..e7417fe97a97 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -36,7 +36,8 @@
36 36
37struct perf_annotate { 37struct perf_annotate {
38 struct perf_tool tool; 38 struct perf_tool tool;
39 bool force, use_tui, use_stdio, use_gtk; 39 struct perf_session *session;
40 bool use_tui, use_stdio, use_gtk;
40 bool full_paths; 41 bool full_paths;
41 bool print_line; 42 bool print_line;
42 bool skip_missing; 43 bool skip_missing;
@@ -50,6 +51,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
50 struct addr_location *al, 51 struct addr_location *al,
51 struct perf_annotate *ann) 52 struct perf_annotate *ann)
52{ 53{
54 struct hists *hists = evsel__hists(evsel);
53 struct hist_entry *he; 55 struct hist_entry *he;
54 int ret; 56 int ret;
55 57
@@ -65,13 +67,12 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
65 return 0; 67 return 0;
66 } 68 }
67 69
68 he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0, 70 he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0, true);
69 true);
70 if (he == NULL) 71 if (he == NULL)
71 return -ENOMEM; 72 return -ENOMEM;
72 73
73 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 74 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
74 hists__inc_nr_samples(&evsel->hists, true); 75 hists__inc_nr_samples(hists, true);
75 return ret; 76 return ret;
76} 77}
77 78
@@ -188,18 +189,9 @@ find_next:
188static int __cmd_annotate(struct perf_annotate *ann) 189static int __cmd_annotate(struct perf_annotate *ann)
189{ 190{
190 int ret; 191 int ret;
191 struct perf_session *session; 192 struct perf_session *session = ann->session;
192 struct perf_evsel *pos; 193 struct perf_evsel *pos;
193 u64 total_nr_samples; 194 u64 total_nr_samples;
194 struct perf_data_file file = {
195 .path = input_name,
196 .mode = PERF_DATA_MODE_READ,
197 .force = ann->force,
198 };
199
200 session = perf_session__new(&file, false, &ann->tool);
201 if (session == NULL)
202 return -ENOMEM;
203 195
204 machines__set_symbol_filter(&session->machines, symbol__annotate_init); 196 machines__set_symbol_filter(&session->machines, symbol__annotate_init);
205 197
@@ -207,22 +199,23 @@ static int __cmd_annotate(struct perf_annotate *ann)
207 ret = perf_session__cpu_bitmap(session, ann->cpu_list, 199 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
208 ann->cpu_bitmap); 200 ann->cpu_bitmap);
209 if (ret) 201 if (ret)
210 goto out_delete; 202 goto out;
211 } 203 }
212 204
213 if (!objdump_path) { 205 if (!objdump_path) {
214 ret = perf_session_env__lookup_objdump(&session->header.env); 206 ret = perf_session_env__lookup_objdump(&session->header.env);
215 if (ret) 207 if (ret)
216 goto out_delete; 208 goto out;
217 } 209 }
218 210
219 ret = perf_session__process_events(session, &ann->tool); 211 ret = perf_session__process_events(session, &ann->tool);
220 if (ret) 212 if (ret)
221 goto out_delete; 213 goto out;
222 214
223 if (dump_trace) { 215 if (dump_trace) {
224 perf_session__fprintf_nr_events(session, stdout); 216 perf_session__fprintf_nr_events(session, stdout);
225 goto out_delete; 217 perf_evlist__fprintf_nr_events(session->evlist, stdout);
218 goto out;
226 } 219 }
227 220
228 if (verbose > 3) 221 if (verbose > 3)
@@ -233,7 +226,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
233 226
234 total_nr_samples = 0; 227 total_nr_samples = 0;
235 evlist__for_each(session->evlist, pos) { 228 evlist__for_each(session->evlist, pos) {
236 struct hists *hists = &pos->hists; 229 struct hists *hists = evsel__hists(pos);
237 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 230 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
238 231
239 if (nr_samples > 0) { 232 if (nr_samples > 0) {
@@ -250,8 +243,8 @@ static int __cmd_annotate(struct perf_annotate *ann)
250 } 243 }
251 244
252 if (total_nr_samples == 0) { 245 if (total_nr_samples == 0) {
253 ui__error("The %s file has no samples!\n", file.path); 246 ui__error("The %s file has no samples!\n", session->file->path);
254 goto out_delete; 247 goto out;
255 } 248 }
256 249
257 if (use_browser == 2) { 250 if (use_browser == 2) {
@@ -261,24 +254,12 @@ static int __cmd_annotate(struct perf_annotate *ann)
261 "perf_gtk__show_annotations"); 254 "perf_gtk__show_annotations");
262 if (show_annotations == NULL) { 255 if (show_annotations == NULL) {
263 ui__error("GTK browser not found!\n"); 256 ui__error("GTK browser not found!\n");
264 goto out_delete; 257 goto out;
265 } 258 }
266 show_annotations(); 259 show_annotations();
267 } 260 }
268 261
269out_delete: 262out:
270 /*
271 * Speed up the exit process, for large files this can
272 * take quite a while.
273 *
274 * XXX Enable this when using valgrind or if we ever
275 * librarize this command.
276 *
277 * Also experiment with obstacks to see how much speed
278 * up we'll get here.
279 *
280 * perf_session__delete(session);
281 */
282 return ret; 263 return ret;
283} 264}
284 265
@@ -297,10 +278,14 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
297 .comm = perf_event__process_comm, 278 .comm = perf_event__process_comm,
298 .exit = perf_event__process_exit, 279 .exit = perf_event__process_exit,
299 .fork = perf_event__process_fork, 280 .fork = perf_event__process_fork,
300 .ordered_samples = true, 281 .ordered_events = true,
301 .ordering_requires_timestamps = true, 282 .ordering_requires_timestamps = true,
302 }, 283 },
303 }; 284 };
285 struct perf_data_file file = {
286 .path = input_name,
287 .mode = PERF_DATA_MODE_READ,
288 };
304 const struct option options[] = { 289 const struct option options[] = {
305 OPT_STRING('i', "input", &input_name, "file", 290 OPT_STRING('i', "input", &input_name, "file",
306 "input file name"), 291 "input file name"),
@@ -308,7 +293,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
308 "only consider symbols in these dsos"), 293 "only consider symbols in these dsos"),
309 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", 294 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
310 "symbol to annotate"), 295 "symbol to annotate"),
311 OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"), 296 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
312 OPT_INCR('v', "verbose", &verbose, 297 OPT_INCR('v', "verbose", &verbose,
313 "be more verbose (show symbol address, etc)"), 298 "be more verbose (show symbol address, etc)"),
314 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 299 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
@@ -341,6 +326,10 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
341 "Show event group information together"), 326 "Show event group information together"),
342 OPT_END() 327 OPT_END()
343 }; 328 };
329 int ret = hists__init();
330
331 if (ret < 0)
332 return ret;
344 333
345 argc = parse_options(argc, argv, options, annotate_usage, 0); 334 argc = parse_options(argc, argv, options, annotate_usage, 0);
346 335
@@ -353,11 +342,16 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
353 342
354 setup_browser(true); 343 setup_browser(true);
355 344
345 annotate.session = perf_session__new(&file, false, &annotate.tool);
346 if (annotate.session == NULL)
347 return -1;
348
356 symbol_conf.priv_size = sizeof(struct annotation); 349 symbol_conf.priv_size = sizeof(struct annotation);
357 symbol_conf.try_vmlinux_path = true; 350 symbol_conf.try_vmlinux_path = true;
358 351
359 if (symbol__init() < 0) 352 ret = symbol__init(&annotate.session->header.env);
360 return -1; 353 if (ret < 0)
354 goto out_delete;
361 355
362 if (setup_sorting() < 0) 356 if (setup_sorting() < 0)
363 usage_with_options(annotate_usage, options); 357 usage_with_options(annotate_usage, options);
@@ -373,5 +367,20 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
373 annotate.sym_hist_filter = argv[0]; 367 annotate.sym_hist_filter = argv[0];
374 } 368 }
375 369
376 return __cmd_annotate(&annotate); 370 ret = __cmd_annotate(&annotate);
371
372out_delete:
373 /*
374 * Speed up the exit process, for large files this can
375 * take quite a while.
376 *
377 * XXX Enable this when using valgrind or if we ever
378 * librarize this command.
379 *
380 * Also experiment with obstacks to see how much speed
381 * up we'll get here.
382 *
383 * perf_session__delete(session);
384 */
385 return ret;
377} 386}
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 2a2c78f80876..70385756da63 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -246,20 +246,9 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
246 return true; 246 return true;
247} 247}
248 248
249static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) 249static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *fp)
250{ 250{
251 struct perf_data_file file = {
252 .path = filename,
253 .mode = PERF_DATA_MODE_READ,
254 .force = force,
255 };
256 struct perf_session *session = perf_session__new(&file, false, NULL);
257 if (session == NULL)
258 return -1;
259
260 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0); 251 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
261 perf_session__delete(session);
262
263 return 0; 252 return 0;
264} 253}
265 254
@@ -302,6 +291,12 @@ int cmd_buildid_cache(int argc, const char **argv,
302 *missing_filename = NULL, 291 *missing_filename = NULL,
303 *update_name_list_str = NULL, 292 *update_name_list_str = NULL,
304 *kcore_filename; 293 *kcore_filename;
294 char sbuf[STRERR_BUFSIZE];
295
296 struct perf_data_file file = {
297 .mode = PERF_DATA_MODE_READ,
298 };
299 struct perf_session *session = NULL;
305 300
306 const struct option buildid_cache_options[] = { 301 const struct option buildid_cache_options[] = {
307 OPT_STRING('a', "add", &add_name_list_str, 302 OPT_STRING('a', "add", &add_name_list_str,
@@ -326,8 +321,17 @@ int cmd_buildid_cache(int argc, const char **argv,
326 argc = parse_options(argc, argv, buildid_cache_options, 321 argc = parse_options(argc, argv, buildid_cache_options,
327 buildid_cache_usage, 0); 322 buildid_cache_usage, 0);
328 323
329 if (symbol__init() < 0) 324 if (missing_filename) {
330 return -1; 325 file.path = missing_filename;
326 file.force = force;
327
328 session = perf_session__new(&file, false, NULL);
329 if (session == NULL)
330 return -1;
331 }
332
333 if (symbol__init(session ? &session->header.env : NULL) < 0)
334 goto out;
331 335
332 setup_pager(); 336 setup_pager();
333 337
@@ -344,7 +348,7 @@ int cmd_buildid_cache(int argc, const char **argv,
344 continue; 348 continue;
345 } 349 }
346 pr_warning("Couldn't add %s: %s\n", 350 pr_warning("Couldn't add %s: %s\n",
347 pos->s, strerror(errno)); 351 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
348 } 352 }
349 353
350 strlist__delete(list); 354 strlist__delete(list);
@@ -362,7 +366,7 @@ int cmd_buildid_cache(int argc, const char **argv,
362 continue; 366 continue;
363 } 367 }
364 pr_warning("Couldn't remove %s: %s\n", 368 pr_warning("Couldn't remove %s: %s\n",
365 pos->s, strerror(errno)); 369 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
366 } 370 }
367 371
368 strlist__delete(list); 372 strlist__delete(list);
@@ -370,7 +374,7 @@ int cmd_buildid_cache(int argc, const char **argv,
370 } 374 }
371 375
372 if (missing_filename) 376 if (missing_filename)
373 ret = build_id_cache__fprintf_missing(missing_filename, force, stdout); 377 ret = build_id_cache__fprintf_missing(session, stdout);
374 378
375 if (update_name_list_str) { 379 if (update_name_list_str) {
376 list = strlist__new(true, update_name_list_str); 380 list = strlist__new(true, update_name_list_str);
@@ -383,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv,
383 continue; 387 continue;
384 } 388 }
385 pr_warning("Couldn't update %s: %s\n", 389 pr_warning("Couldn't update %s: %s\n",
386 pos->s, strerror(errno)); 390 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
387 } 391 }
388 392
389 strlist__delete(list); 393 strlist__delete(list);
@@ -394,5 +398,9 @@ int cmd_buildid_cache(int argc, const char **argv,
394 build_id_cache__add_kcore(kcore_filename, debugdir, force)) 398 build_id_cache__add_kcore(kcore_filename, debugdir, force))
395 pr_warning("Couldn't add %s\n", kcore_filename); 399 pr_warning("Couldn't add %s\n", kcore_filename);
396 400
401out:
402 if (session)
403 perf_session__delete(session);
404
397 return ret; 405 return ret;
398} 406}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 9a5a035cb426..25114c9a6801 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -327,6 +327,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
327 struct machine *machine) 327 struct machine *machine)
328{ 328{
329 struct addr_location al; 329 struct addr_location al;
330 struct hists *hists = evsel__hists(evsel);
330 331
331 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 332 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
332 pr_warning("problem processing %d event, skipping it.\n", 333 pr_warning("problem processing %d event, skipping it.\n",
@@ -334,7 +335,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
334 return -1; 335 return -1;
335 } 336 }
336 337
337 if (hists__add_entry(&evsel->hists, &al, sample->period, 338 if (hists__add_entry(hists, &al, sample->period,
338 sample->weight, sample->transaction)) { 339 sample->weight, sample->transaction)) {
339 pr_warning("problem incrementing symbol period, skipping event\n"); 340 pr_warning("problem incrementing symbol period, skipping event\n");
340 return -1; 341 return -1;
@@ -346,9 +347,9 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
346 * hists__output_resort() and precompute needs the total 347 * hists__output_resort() and precompute needs the total
347 * period in order to sort entries by percentage delta. 348 * period in order to sort entries by percentage delta.
348 */ 349 */
349 evsel->hists.stats.total_period += sample->period; 350 hists->stats.total_period += sample->period;
350 if (!al.filtered) 351 if (!al.filtered)
351 evsel->hists.stats.total_non_filtered_period += sample->period; 352 hists->stats.total_non_filtered_period += sample->period;
352 353
353 return 0; 354 return 0;
354} 355}
@@ -360,7 +361,7 @@ static struct perf_tool tool = {
360 .exit = perf_event__process_exit, 361 .exit = perf_event__process_exit,
361 .fork = perf_event__process_fork, 362 .fork = perf_event__process_fork,
362 .lost = perf_event__process_lost, 363 .lost = perf_event__process_lost,
363 .ordered_samples = true, 364 .ordered_events = true,
364 .ordering_requires_timestamps = true, 365 .ordering_requires_timestamps = true,
365}; 366};
366 367
@@ -382,7 +383,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
382 struct perf_evsel *evsel; 383 struct perf_evsel *evsel;
383 384
384 evlist__for_each(evlist, evsel) { 385 evlist__for_each(evlist, evsel) {
385 struct hists *hists = &evsel->hists; 386 struct hists *hists = evsel__hists(evsel);
386 387
387 hists__collapse_resort(hists, NULL); 388 hists__collapse_resort(hists, NULL);
388 } 389 }
@@ -631,24 +632,26 @@ static void data_process(void)
631 bool first = true; 632 bool first = true;
632 633
633 evlist__for_each(evlist_base, evsel_base) { 634 evlist__for_each(evlist_base, evsel_base) {
635 struct hists *hists_base = evsel__hists(evsel_base);
634 struct data__file *d; 636 struct data__file *d;
635 int i; 637 int i;
636 638
637 data__for_each_file_new(i, d) { 639 data__for_each_file_new(i, d) {
638 struct perf_evlist *evlist = d->session->evlist; 640 struct perf_evlist *evlist = d->session->evlist;
639 struct perf_evsel *evsel; 641 struct perf_evsel *evsel;
642 struct hists *hists;
640 643
641 evsel = evsel_match(evsel_base, evlist); 644 evsel = evsel_match(evsel_base, evlist);
642 if (!evsel) 645 if (!evsel)
643 continue; 646 continue;
644 647
645 d->hists = &evsel->hists; 648 hists = evsel__hists(evsel);
649 d->hists = hists;
646 650
647 hists__match(&evsel_base->hists, &evsel->hists); 651 hists__match(hists_base, hists);
648 652
649 if (!show_baseline_only) 653 if (!show_baseline_only)
650 hists__link(&evsel_base->hists, 654 hists__link(hists_base, hists);
651 &evsel->hists);
652 } 655 }
653 656
654 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", 657 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
@@ -659,7 +662,7 @@ static void data_process(void)
659 if (verbose || data__files_cnt > 2) 662 if (verbose || data__files_cnt > 2)
660 data__fprintf(); 663 data__fprintf();
661 664
662 hists__process(&evsel_base->hists); 665 hists__process(hists_base);
663 } 666 }
664} 667}
665 668
@@ -683,7 +686,7 @@ static int __cmd_diff(void)
683 d->session = perf_session__new(&d->file, false, &tool); 686 d->session = perf_session__new(&d->file, false, &tool);
684 if (!d->session) { 687 if (!d->session) {
685 pr_err("Failed to open %s\n", d->file.path); 688 pr_err("Failed to open %s\n", d->file.path);
686 ret = -ENOMEM; 689 ret = -1;
687 goto out_delete; 690 goto out_delete;
688 } 691 }
689 692
@@ -1139,11 +1142,16 @@ static int data_init(int argc, const char **argv)
1139 1142
1140int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 1143int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1141{ 1144{
1145 int ret = hists__init();
1146
1147 if (ret < 0)
1148 return ret;
1149
1142 perf_config(perf_default_config, NULL); 1150 perf_config(perf_default_config, NULL);
1143 1151
1144 argc = parse_options(argc, argv, options, diff_usage, 0); 1152 argc = parse_options(argc, argv, options, diff_usage, 0);
1145 1153
1146 if (symbol__init() < 0) 1154 if (symbol__init(NULL) < 0)
1147 return -1; 1155 return -1;
1148 1156
1149 if (data_init(argc, argv) < 0) 1157 if (data_init(argc, argv) < 0)
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 66e12f55c052..0f93f859b782 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -28,7 +28,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
28 28
29 session = perf_session__new(&file, 0, NULL); 29 session = perf_session__new(&file, 0, NULL);
30 if (session == NULL) 30 if (session == NULL)
31 return -ENOMEM; 31 return -1;
32 32
33 evlist__for_each(session->evlist, pos) 33 evlist__for_each(session->evlist, pos)
34 perf_evsel__fprintf(pos, details, stdout); 34 perf_evsel__fprintf(pos, details, stdout);
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 0384d930480b..25d20628212e 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -103,6 +103,8 @@ static int check_emacsclient_version(void)
103 103
104static void exec_woman_emacs(const char *path, const char *page) 104static void exec_woman_emacs(const char *path, const char *page)
105{ 105{
106 char sbuf[STRERR_BUFSIZE];
107
106 if (!check_emacsclient_version()) { 108 if (!check_emacsclient_version()) {
107 /* This works only with emacsclient version >= 22. */ 109 /* This works only with emacsclient version >= 22. */
108 struct strbuf man_page = STRBUF_INIT; 110 struct strbuf man_page = STRBUF_INIT;
@@ -111,16 +113,19 @@ static void exec_woman_emacs(const char *path, const char *page)
111 path = "emacsclient"; 113 path = "emacsclient";
112 strbuf_addf(&man_page, "(woman \"%s\")", page); 114 strbuf_addf(&man_page, "(woman \"%s\")", page);
113 execlp(path, "emacsclient", "-e", man_page.buf, NULL); 115 execlp(path, "emacsclient", "-e", man_page.buf, NULL);
114 warning("failed to exec '%s': %s", path, strerror(errno)); 116 warning("failed to exec '%s': %s", path,
117 strerror_r(errno, sbuf, sizeof(sbuf)));
115 } 118 }
116} 119}
117 120
118static void exec_man_konqueror(const char *path, const char *page) 121static void exec_man_konqueror(const char *path, const char *page)
119{ 122{
120 const char *display = getenv("DISPLAY"); 123 const char *display = getenv("DISPLAY");
124
121 if (display && *display) { 125 if (display && *display) {
122 struct strbuf man_page = STRBUF_INIT; 126 struct strbuf man_page = STRBUF_INIT;
123 const char *filename = "kfmclient"; 127 const char *filename = "kfmclient";
128 char sbuf[STRERR_BUFSIZE];
124 129
125 /* It's simpler to launch konqueror using kfmclient. */ 130 /* It's simpler to launch konqueror using kfmclient. */
126 if (path) { 131 if (path) {
@@ -139,24 +144,31 @@ static void exec_man_konqueror(const char *path, const char *page)
139 path = "kfmclient"; 144 path = "kfmclient";
140 strbuf_addf(&man_page, "man:%s(1)", page); 145 strbuf_addf(&man_page, "man:%s(1)", page);
141 execlp(path, filename, "newTab", man_page.buf, NULL); 146 execlp(path, filename, "newTab", man_page.buf, NULL);
142 warning("failed to exec '%s': %s", path, strerror(errno)); 147 warning("failed to exec '%s': %s", path,
148 strerror_r(errno, sbuf, sizeof(sbuf)));
143 } 149 }
144} 150}
145 151
146static void exec_man_man(const char *path, const char *page) 152static void exec_man_man(const char *path, const char *page)
147{ 153{
154 char sbuf[STRERR_BUFSIZE];
155
148 if (!path) 156 if (!path)
149 path = "man"; 157 path = "man";
150 execlp(path, "man", page, NULL); 158 execlp(path, "man", page, NULL);
151 warning("failed to exec '%s': %s", path, strerror(errno)); 159 warning("failed to exec '%s': %s", path,
160 strerror_r(errno, sbuf, sizeof(sbuf)));
152} 161}
153 162
154static void exec_man_cmd(const char *cmd, const char *page) 163static void exec_man_cmd(const char *cmd, const char *page)
155{ 164{
156 struct strbuf shell_cmd = STRBUF_INIT; 165 struct strbuf shell_cmd = STRBUF_INIT;
166 char sbuf[STRERR_BUFSIZE];
167
157 strbuf_addf(&shell_cmd, "%s %s", cmd, page); 168 strbuf_addf(&shell_cmd, "%s %s", cmd, page);
158 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL); 169 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL);
159 warning("failed to exec '%s': %s", cmd, strerror(errno)); 170 warning("failed to exec '%s': %s", cmd,
171 strerror_r(errno, sbuf, sizeof(sbuf)));
160} 172}
161 173
162static void add_man_viewer(const char *name) 174static void add_man_viewer(const char *name)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9a02807387d6..de99ca1bb942 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -23,6 +23,7 @@
23 23
24struct perf_inject { 24struct perf_inject {
25 struct perf_tool tool; 25 struct perf_tool tool;
26 struct perf_session *session;
26 bool build_ids; 27 bool build_ids;
27 bool sched_stat; 28 bool sched_stat;
28 const char *input_name; 29 const char *input_name;
@@ -340,12 +341,8 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
340 341
341static int __cmd_inject(struct perf_inject *inject) 342static int __cmd_inject(struct perf_inject *inject)
342{ 343{
343 struct perf_session *session;
344 int ret = -EINVAL; 344 int ret = -EINVAL;
345 struct perf_data_file file = { 345 struct perf_session *session = inject->session;
346 .path = inject->input_name,
347 .mode = PERF_DATA_MODE_READ,
348 };
349 struct perf_data_file *file_out = &inject->output; 346 struct perf_data_file *file_out = &inject->output;
350 347
351 signal(SIGINT, sig_handler); 348 signal(SIGINT, sig_handler);
@@ -357,16 +354,12 @@ static int __cmd_inject(struct perf_inject *inject)
357 inject->tool.tracing_data = perf_event__repipe_tracing_data; 354 inject->tool.tracing_data = perf_event__repipe_tracing_data;
358 } 355 }
359 356
360 session = perf_session__new(&file, true, &inject->tool);
361 if (session == NULL)
362 return -ENOMEM;
363
364 if (inject->build_ids) { 357 if (inject->build_ids) {
365 inject->tool.sample = perf_event__inject_buildid; 358 inject->tool.sample = perf_event__inject_buildid;
366 } else if (inject->sched_stat) { 359 } else if (inject->sched_stat) {
367 struct perf_evsel *evsel; 360 struct perf_evsel *evsel;
368 361
369 inject->tool.ordered_samples = true; 362 inject->tool.ordered_events = true;
370 363
371 evlist__for_each(session->evlist, evsel) { 364 evlist__for_each(session->evlist, evsel) {
372 const char *name = perf_evsel__name(evsel); 365 const char *name = perf_evsel__name(evsel);
@@ -396,8 +389,6 @@ static int __cmd_inject(struct perf_inject *inject)
396 perf_session__write_header(session, session->evlist, file_out->fd, true); 389 perf_session__write_header(session, session->evlist, file_out->fd, true);
397 } 390 }
398 391
399 perf_session__delete(session);
400
401 return ret; 392 return ret;
402} 393}
403 394
@@ -427,6 +418,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
427 .mode = PERF_DATA_MODE_WRITE, 418 .mode = PERF_DATA_MODE_WRITE,
428 }, 419 },
429 }; 420 };
421 struct perf_data_file file = {
422 .mode = PERF_DATA_MODE_READ,
423 };
424 int ret;
425
430 const struct option options[] = { 426 const struct option options[] = {
431 OPT_BOOLEAN('b', "build-ids", &inject.build_ids, 427 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
432 "Inject build-ids into the output stream"), 428 "Inject build-ids into the output stream"),
@@ -461,8 +457,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
461 return -1; 457 return -1;
462 } 458 }
463 459
464 if (symbol__init() < 0) 460 file.path = inject.input_name;
461 inject.session = perf_session__new(&file, true, &inject.tool);
462 if (inject.session == NULL)
463 return -1;
464
465 if (symbol__init(&inject.session->header.env) < 0)
465 return -1; 466 return -1;
466 467
467 return __cmd_inject(&inject); 468 ret = __cmd_inject(&inject);
469
470 perf_session__delete(inject.session);
471
472 return ret;
468} 473}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bef3376bfaf3..f295141025bc 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -256,7 +256,9 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
256static struct perf_tool perf_kmem = { 256static struct perf_tool perf_kmem = {
257 .sample = process_sample_event, 257 .sample = process_sample_event,
258 .comm = perf_event__process_comm, 258 .comm = perf_event__process_comm,
259 .ordered_samples = true, 259 .mmap = perf_event__process_mmap,
260 .mmap2 = perf_event__process_mmap2,
261 .ordered_events = true,
260}; 262};
261 263
262static double fragmentation(unsigned long n_req, unsigned long n_alloc) 264static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -403,10 +405,9 @@ static void sort_result(void)
403 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 405 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
404} 406}
405 407
406static int __cmd_kmem(void) 408static int __cmd_kmem(struct perf_session *session)
407{ 409{
408 int err = -EINVAL; 410 int err = -EINVAL;
409 struct perf_session *session;
410 const struct perf_evsel_str_handler kmem_tracepoints[] = { 411 const struct perf_evsel_str_handler kmem_tracepoints[] = {
411 { "kmem:kmalloc", perf_evsel__process_alloc_event, }, 412 { "kmem:kmalloc", perf_evsel__process_alloc_event, },
412 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, 413 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, },
@@ -415,34 +416,22 @@ static int __cmd_kmem(void)
415 { "kmem:kfree", perf_evsel__process_free_event, }, 416 { "kmem:kfree", perf_evsel__process_free_event, },
416 { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, 417 { "kmem:kmem_cache_free", perf_evsel__process_free_event, },
417 }; 418 };
418 struct perf_data_file file = {
419 .path = input_name,
420 .mode = PERF_DATA_MODE_READ,
421 };
422
423 session = perf_session__new(&file, false, &perf_kmem);
424 if (session == NULL)
425 return -ENOMEM;
426
427 if (perf_session__create_kernel_maps(session) < 0)
428 goto out_delete;
429 419
430 if (!perf_session__has_traces(session, "kmem record")) 420 if (!perf_session__has_traces(session, "kmem record"))
431 goto out_delete; 421 goto out;
432 422
433 if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) { 423 if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) {
434 pr_err("Initializing perf session tracepoint handlers failed\n"); 424 pr_err("Initializing perf session tracepoint handlers failed\n");
435 return -1; 425 goto out;
436 } 426 }
437 427
438 setup_pager(); 428 setup_pager();
439 err = perf_session__process_events(session, &perf_kmem); 429 err = perf_session__process_events(session, &perf_kmem);
440 if (err != 0) 430 if (err != 0)
441 goto out_delete; 431 goto out;
442 sort_result(); 432 sort_result();
443 print_result(session); 433 print_result(session);
444out_delete: 434out:
445 perf_session__delete(session);
446 return err; 435 return err;
447} 436}
448 437
@@ -689,29 +678,46 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
689 NULL, 678 NULL,
690 NULL 679 NULL
691 }; 680 };
681 struct perf_session *session;
682 struct perf_data_file file = {
683 .path = input_name,
684 .mode = PERF_DATA_MODE_READ,
685 };
686 int ret = -1;
687
692 argc = parse_options_subcommand(argc, argv, kmem_options, 688 argc = parse_options_subcommand(argc, argv, kmem_options,
693 kmem_subcommands, kmem_usage, 0); 689 kmem_subcommands, kmem_usage, 0);
694 690
695 if (!argc) 691 if (!argc)
696 usage_with_options(kmem_usage, kmem_options); 692 usage_with_options(kmem_usage, kmem_options);
697 693
698 symbol__init();
699
700 if (!strncmp(argv[0], "rec", 3)) { 694 if (!strncmp(argv[0], "rec", 3)) {
695 symbol__init(NULL);
701 return __cmd_record(argc, argv); 696 return __cmd_record(argc, argv);
702 } else if (!strcmp(argv[0], "stat")) { 697 }
698
699 session = perf_session__new(&file, false, &perf_kmem);
700 if (session == NULL)
701 return -1;
702
703 symbol__init(&session->header.env);
704
705 if (!strcmp(argv[0], "stat")) {
703 if (cpu__setup_cpunode_map()) 706 if (cpu__setup_cpunode_map())
704 return -1; 707 goto out_delete;
705 708
706 if (list_empty(&caller_sort)) 709 if (list_empty(&caller_sort))
707 setup_sorting(&caller_sort, default_sort_order); 710 setup_sorting(&caller_sort, default_sort_order);
708 if (list_empty(&alloc_sort)) 711 if (list_empty(&alloc_sort))
709 setup_sorting(&alloc_sort, default_sort_order); 712 setup_sorting(&alloc_sort, default_sort_order);
710 713
711 return __cmd_kmem(); 714 ret = __cmd_kmem(session);
712 } else 715 } else
713 usage_with_options(kmem_usage, kmem_options); 716 usage_with_options(kmem_usage, kmem_options);
714 717
715 return 0; 718out_delete:
719 perf_session__delete(session);
720
721 return ret;
716} 722}
717 723
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 43367eb00510..b65eb0507b38 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -376,7 +376,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
376 struct perf_sample *sample) 376 struct perf_sample *sample)
377{ 377{
378 /* Only kvm_entry records vcpu id. */ 378 /* Only kvm_entry records vcpu id. */
379 if (!thread->priv && kvm_entry_event(evsel)) { 379 if (!thread__priv(thread) && kvm_entry_event(evsel)) {
380 struct vcpu_event_record *vcpu_record; 380 struct vcpu_event_record *vcpu_record;
381 381
382 vcpu_record = zalloc(sizeof(*vcpu_record)); 382 vcpu_record = zalloc(sizeof(*vcpu_record));
@@ -386,10 +386,10 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
386 } 386 }
387 387
388 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID); 388 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID);
389 thread->priv = vcpu_record; 389 thread__set_priv(thread, vcpu_record);
390 } 390 }
391 391
392 return thread->priv; 392 return thread__priv(thread);
393} 393}
394 394
395static bool handle_kvm_event(struct perf_kvm_stat *kvm, 395static bool handle_kvm_event(struct perf_kvm_stat *kvm,
@@ -543,14 +543,12 @@ static void print_vcpu_info(struct perf_kvm_stat *kvm)
543 543
544 pr_info("Analyze events for "); 544 pr_info("Analyze events for ");
545 545
546 if (kvm->live) { 546 if (kvm->opts.target.system_wide)
547 if (kvm->opts.target.system_wide) 547 pr_info("all VMs, ");
548 pr_info("all VMs, "); 548 else if (kvm->opts.target.pid)
549 else if (kvm->opts.target.pid) 549 pr_info("pid(s) %s, ", kvm->opts.target.pid);
550 pr_info("pid(s) %s, ", kvm->opts.target.pid); 550 else
551 else 551 pr_info("dazed and confused on what is monitored, ");
552 pr_info("dazed and confused on what is monitored, ");
553 }
554 552
555 if (vcpu == -1) 553 if (vcpu == -1)
556 pr_info("all VCPUs:\n\n"); 554 pr_info("all VCPUs:\n\n");
@@ -592,8 +590,8 @@ static void print_result(struct perf_kvm_stat *kvm)
592 pr_info("%9s ", "Samples%"); 590 pr_info("%9s ", "Samples%");
593 591
594 pr_info("%9s ", "Time%"); 592 pr_info("%9s ", "Time%");
595 pr_info("%10s ", "Min Time"); 593 pr_info("%11s ", "Min Time");
596 pr_info("%10s ", "Max Time"); 594 pr_info("%11s ", "Max Time");
597 pr_info("%16s ", "Avg time"); 595 pr_info("%16s ", "Avg time");
598 pr_info("\n\n"); 596 pr_info("\n\n");
599 597
@@ -610,8 +608,8 @@ static void print_result(struct perf_kvm_stat *kvm)
610 pr_info("%10llu ", (unsigned long long)ecount); 608 pr_info("%10llu ", (unsigned long long)ecount);
611 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 609 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
612 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 610 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
613 pr_info("%8" PRIu64 "us ", min / 1000); 611 pr_info("%9.2fus ", (double)min / 1e3);
614 pr_info("%8" PRIu64 "us ", max / 1000); 612 pr_info("%9.2fus ", (double)max / 1e3);
615 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 613 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
616 kvm_event_rel_stddev(vcpu, event)); 614 kvm_event_rel_stddev(vcpu, event));
617 pr_info("\n"); 615 pr_info("\n");
@@ -732,7 +730,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
732 return -1; 730 return -1;
733 } 731 }
734 732
735 err = perf_session_queue_event(kvm->session, event, &sample, 0); 733 err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0);
736 /* 734 /*
737 * FIXME: Here we can't consume the event, as perf_session_queue_event will 735 * FIXME: Here we can't consume the event, as perf_session_queue_event will
738 * point to it, and it'll get possibly overwritten by the kernel. 736 * point to it, and it'll get possibly overwritten by the kernel.
@@ -785,7 +783,7 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
785 783
786 /* flush queue after each round in which we processed events */ 784 /* flush queue after each round in which we processed events */
787 if (ntotal) { 785 if (ntotal) {
788 kvm->session->ordered_samples.next_flush = flush_time; 786 kvm->session->ordered_events.next_flush = flush_time;
789 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session); 787 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
790 if (err) { 788 if (err) {
791 if (kvm->lost_events) 789 if (kvm->lost_events)
@@ -885,15 +883,11 @@ static int fd_set_nonblock(int fd)
885 return 0; 883 return 0;
886} 884}
887 885
888static 886static int perf_kvm__handle_stdin(void)
889int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
890{ 887{
891 int c; 888 int c;
892 889
893 tcsetattr(0, TCSANOW, tc_now);
894 c = getc(stdin); 890 c = getc(stdin);
895 tcsetattr(0, TCSAFLUSH, tc_save);
896
897 if (c == 'q') 891 if (c == 'q')
898 return 1; 892 return 1;
899 893
@@ -902,9 +896,8 @@ int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
902 896
903static int kvm_events_live_report(struct perf_kvm_stat *kvm) 897static int kvm_events_live_report(struct perf_kvm_stat *kvm)
904{ 898{
905 struct pollfd *pollfds = NULL; 899 int nr_stdin, ret, err = -EINVAL;
906 int nr_fds, nr_stdin, ret, err = -EINVAL; 900 struct termios save;
907 struct termios tc, save;
908 901
909 /* live flag must be set first */ 902 /* live flag must be set first */
910 kvm->live = true; 903 kvm->live = true;
@@ -919,41 +912,25 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
919 goto out; 912 goto out;
920 } 913 }
921 914
915 set_term_quiet_input(&save);
922 init_kvm_event_record(kvm); 916 init_kvm_event_record(kvm);
923 917
924 tcgetattr(0, &save);
925 tc = save;
926 tc.c_lflag &= ~(ICANON | ECHO);
927 tc.c_cc[VMIN] = 0;
928 tc.c_cc[VTIME] = 0;
929
930 signal(SIGINT, sig_handler); 918 signal(SIGINT, sig_handler);
931 signal(SIGTERM, sig_handler); 919 signal(SIGTERM, sig_handler);
932 920
933 /* copy pollfds -- need to add timerfd and stdin */
934 nr_fds = kvm->evlist->nr_fds;
935 pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
936 if (!pollfds) {
937 err = -ENOMEM;
938 goto out;
939 }
940 memcpy(pollfds, kvm->evlist->pollfd,
941 sizeof(struct pollfd) * kvm->evlist->nr_fds);
942
943 /* add timer fd */ 921 /* add timer fd */
944 if (perf_kvm__timerfd_create(kvm) < 0) { 922 if (perf_kvm__timerfd_create(kvm) < 0) {
945 err = -1; 923 err = -1;
946 goto out; 924 goto out;
947 } 925 }
948 926
949 pollfds[nr_fds].fd = kvm->timerfd; 927 if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0)
950 pollfds[nr_fds].events = POLLIN; 928 goto out;
951 nr_fds++; 929
930 nr_stdin = perf_evlist__add_pollfd(kvm->evlist, fileno(stdin));
931 if (nr_stdin < 0)
932 goto out;
952 933
953 pollfds[nr_fds].fd = fileno(stdin);
954 pollfds[nr_fds].events = POLLIN;
955 nr_stdin = nr_fds;
956 nr_fds++;
957 if (fd_set_nonblock(fileno(stdin)) != 0) 934 if (fd_set_nonblock(fileno(stdin)) != 0)
958 goto out; 935 goto out;
959 936
@@ -961,6 +938,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
961 perf_evlist__enable(kvm->evlist); 938 perf_evlist__enable(kvm->evlist);
962 939
963 while (!done) { 940 while (!done) {
941 struct fdarray *fda = &kvm->evlist->pollfd;
964 int rc; 942 int rc;
965 943
966 rc = perf_kvm__mmap_read(kvm); 944 rc = perf_kvm__mmap_read(kvm);
@@ -971,11 +949,11 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
971 if (err) 949 if (err)
972 goto out; 950 goto out;
973 951
974 if (pollfds[nr_stdin].revents & POLLIN) 952 if (fda->entries[nr_stdin].revents & POLLIN)
975 done = perf_kvm__handle_stdin(&tc, &save); 953 done = perf_kvm__handle_stdin();
976 954
977 if (!rc && !done) 955 if (!rc && !done)
978 err = poll(pollfds, nr_fds, 100); 956 err = fdarray__poll(fda, 100);
979 } 957 }
980 958
981 perf_evlist__disable(kvm->evlist); 959 perf_evlist__disable(kvm->evlist);
@@ -989,7 +967,7 @@ out:
989 if (kvm->timerfd >= 0) 967 if (kvm->timerfd >= 0)
990 close(kvm->timerfd); 968 close(kvm->timerfd);
991 969
992 free(pollfds); 970 tcsetattr(0, TCSAFLUSH, &save);
993 return err; 971 return err;
994} 972}
995 973
@@ -998,6 +976,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
998 int err, rc = -1; 976 int err, rc = -1;
999 struct perf_evsel *pos; 977 struct perf_evsel *pos;
1000 struct perf_evlist *evlist = kvm->evlist; 978 struct perf_evlist *evlist = kvm->evlist;
979 char sbuf[STRERR_BUFSIZE];
1001 980
1002 perf_evlist__config(evlist, &kvm->opts); 981 perf_evlist__config(evlist, &kvm->opts);
1003 982
@@ -1034,12 +1013,14 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1034 1013
1035 err = perf_evlist__open(evlist); 1014 err = perf_evlist__open(evlist);
1036 if (err < 0) { 1015 if (err < 0) {
1037 printf("Couldn't create the events: %s\n", strerror(errno)); 1016 printf("Couldn't create the events: %s\n",
1017 strerror_r(errno, sbuf, sizeof(sbuf)));
1038 goto out; 1018 goto out;
1039 } 1019 }
1040 1020
1041 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { 1021 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
1042 ui__error("Failed to mmap the events: %s\n", strerror(errno)); 1022 ui__error("Failed to mmap the events: %s\n",
1023 strerror_r(errno, sbuf, sizeof(sbuf)));
1043 perf_evlist__close(evlist); 1024 perf_evlist__close(evlist);
1044 goto out; 1025 goto out;
1045 } 1026 }
@@ -1058,7 +1039,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1058 struct perf_tool eops = { 1039 struct perf_tool eops = {
1059 .sample = process_sample_event, 1040 .sample = process_sample_event,
1060 .comm = perf_event__process_comm, 1041 .comm = perf_event__process_comm,
1061 .ordered_samples = true, 1042 .ordered_events = true,
1062 }; 1043 };
1063 struct perf_data_file file = { 1044 struct perf_data_file file = {
1064 .path = kvm->file_name, 1045 .path = kvm->file_name,
@@ -1069,9 +1050,11 @@ static int read_events(struct perf_kvm_stat *kvm)
1069 kvm->session = perf_session__new(&file, false, &kvm->tool); 1050 kvm->session = perf_session__new(&file, false, &kvm->tool);
1070 if (!kvm->session) { 1051 if (!kvm->session) {
1071 pr_err("Initializing perf session failed\n"); 1052 pr_err("Initializing perf session failed\n");
1072 return -EINVAL; 1053 return -1;
1073 } 1054 }
1074 1055
1056 symbol__init(&kvm->session->header.env);
1057
1075 if (!perf_session__has_traces(kvm->session, "kvm record")) 1058 if (!perf_session__has_traces(kvm->session, "kvm record"))
1076 return -EINVAL; 1059 return -EINVAL;
1077 1060
@@ -1088,8 +1071,8 @@ static int read_events(struct perf_kvm_stat *kvm)
1088 1071
1089static int parse_target_str(struct perf_kvm_stat *kvm) 1072static int parse_target_str(struct perf_kvm_stat *kvm)
1090{ 1073{
1091 if (kvm->pid_str) { 1074 if (kvm->opts.target.pid) {
1092 kvm->pid_list = intlist__new(kvm->pid_str); 1075 kvm->pid_list = intlist__new(kvm->opts.target.pid);
1093 if (kvm->pid_list == NULL) { 1076 if (kvm->pid_list == NULL) {
1094 pr_err("Error parsing process id string\n"); 1077 pr_err("Error parsing process id string\n");
1095 return -EINVAL; 1078 return -EINVAL;
@@ -1191,7 +1174,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1191 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1174 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
1192 "key for sorting: sample(sort by samples number)" 1175 "key for sorting: sample(sort by samples number)"
1193 " time (sort by avg time)"), 1176 " time (sort by avg time)"),
1194 OPT_STRING('p', "pid", &kvm->pid_str, "pid", 1177 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1195 "analyze events only for given process id(s)"), 1178 "analyze events only for given process id(s)"),
1196 OPT_END() 1179 OPT_END()
1197 }; 1180 };
@@ -1201,8 +1184,6 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1201 NULL 1184 NULL
1202 }; 1185 };
1203 1186
1204 symbol__init();
1205
1206 if (argc) { 1187 if (argc) {
1207 argc = parse_options(argc, argv, 1188 argc = parse_options(argc, argv,
1208 kvm_events_report_options, 1189 kvm_events_report_options,
@@ -1212,6 +1193,9 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1212 kvm_events_report_options); 1193 kvm_events_report_options);
1213 } 1194 }
1214 1195
1196 if (!kvm->opts.target.pid)
1197 kvm->opts.target.system_wide = true;
1198
1215 return kvm_events_report_vcpu(kvm); 1199 return kvm_events_report_vcpu(kvm);
1216} 1200}
1217 1201
@@ -1311,7 +1295,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1311 kvm->tool.exit = perf_event__process_exit; 1295 kvm->tool.exit = perf_event__process_exit;
1312 kvm->tool.fork = perf_event__process_fork; 1296 kvm->tool.fork = perf_event__process_fork;
1313 kvm->tool.lost = process_lost_event; 1297 kvm->tool.lost = process_lost_event;
1314 kvm->tool.ordered_samples = true; 1298 kvm->tool.ordered_events = true;
1315 perf_tool__fill_defaults(&kvm->tool); 1299 perf_tool__fill_defaults(&kvm->tool);
1316 1300
1317 /* set defaults */ 1301 /* set defaults */
@@ -1322,7 +1306,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1322 kvm->opts.target.uid_str = NULL; 1306 kvm->opts.target.uid_str = NULL;
1323 kvm->opts.target.uid = UINT_MAX; 1307 kvm->opts.target.uid = UINT_MAX;
1324 1308
1325 symbol__init(); 1309 symbol__init(NULL);
1326 disable_buildid_cache(); 1310 disable_buildid_cache();
1327 1311
1328 use_browser = 0; 1312 use_browser = 0;
@@ -1369,11 +1353,12 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1369 */ 1353 */
1370 kvm->session = perf_session__new(&file, false, &kvm->tool); 1354 kvm->session = perf_session__new(&file, false, &kvm->tool);
1371 if (kvm->session == NULL) { 1355 if (kvm->session == NULL) {
1372 err = -ENOMEM; 1356 err = -1;
1373 goto out; 1357 goto out;
1374 } 1358 }
1375 kvm->session->evlist = kvm->evlist; 1359 kvm->session->evlist = kvm->evlist;
1376 perf_session__set_id_hdr_size(kvm->session); 1360 perf_session__set_id_hdr_size(kvm->session);
1361 ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
1377 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, 1362 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
1378 kvm->evlist->threads, false); 1363 kvm->evlist->threads, false);
1379 err = kvm_live_open_events(kvm); 1364 err = kvm_live_open_events(kvm);
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6148afc995c6..e7ec71589da6 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -852,7 +852,7 @@ static int __cmd_report(bool display_info)
852 struct perf_tool eops = { 852 struct perf_tool eops = {
853 .sample = process_sample_event, 853 .sample = process_sample_event,
854 .comm = perf_event__process_comm, 854 .comm = perf_event__process_comm,
855 .ordered_samples = true, 855 .ordered_events = true,
856 }; 856 };
857 struct perf_data_file file = { 857 struct perf_data_file file = {
858 .path = input_name, 858 .path = input_name,
@@ -862,9 +862,11 @@ static int __cmd_report(bool display_info)
862 session = perf_session__new(&file, false, &eops); 862 session = perf_session__new(&file, false, &eops);
863 if (!session) { 863 if (!session) {
864 pr_err("Initializing perf session failed\n"); 864 pr_err("Initializing perf session failed\n");
865 return -ENOMEM; 865 return -1;
866 } 866 }
867 867
868 symbol__init(&session->header.env);
869
868 if (!perf_session__has_traces(session, "lock record")) 870 if (!perf_session__has_traces(session, "lock record"))
869 goto out_delete; 871 goto out_delete;
870 872
@@ -974,7 +976,6 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
974 unsigned int i; 976 unsigned int i;
975 int rc = 0; 977 int rc = 0;
976 978
977 symbol__init();
978 for (i = 0; i < LOCKHASH_SIZE; i++) 979 for (i = 0; i < LOCKHASH_SIZE; i++)
979 INIT_LIST_HEAD(lockhash_table + i); 980 INIT_LIST_HEAD(lockhash_table + i);
980 981
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 4a1a6c94a5eb..24db6ffe2957 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -124,7 +124,7 @@ static int report_raw_events(struct perf_mem *mem)
124 &mem->tool); 124 &mem->tool);
125 125
126 if (session == NULL) 126 if (session == NULL)
127 return -ENOMEM; 127 return -1;
128 128
129 if (mem->cpu_list) { 129 if (mem->cpu_list) {
130 ret = perf_session__cpu_bitmap(session, mem->cpu_list, 130 ret = perf_session__cpu_bitmap(session, mem->cpu_list,
@@ -133,7 +133,7 @@ static int report_raw_events(struct perf_mem *mem)
133 goto out_delete; 133 goto out_delete;
134 } 134 }
135 135
136 if (symbol__init() < 0) 136 if (symbol__init(&session->header.env) < 0)
137 return -1; 137 return -1;
138 138
139 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 139 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
@@ -194,7 +194,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
194 .lost = perf_event__process_lost, 194 .lost = perf_event__process_lost,
195 .fork = perf_event__process_fork, 195 .fork = perf_event__process_fork,
196 .build_id = perf_event__process_build_id, 196 .build_id = perf_event__process_build_id,
197 .ordered_samples = true, 197 .ordered_events = true,
198 }, 198 },
199 .input_name = "perf.data", 199 .input_name = "perf.data",
200 }; 200 };
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c63fa2925075..7af26acf06d9 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -290,8 +290,11 @@ static void cleanup_params(void)
290 290
291static void pr_err_with_code(const char *msg, int err) 291static void pr_err_with_code(const char *msg, int err)
292{ 292{
293 char sbuf[STRERR_BUFSIZE];
294
293 pr_err("%s", msg); 295 pr_err("%s", msg);
294 pr_debug(" Reason: %s (Code: %d)", strerror(-err), err); 296 pr_debug(" Reason: %s (Code: %d)",
297 strerror_r(-err, sbuf, sizeof(sbuf)), err);
295 pr_err("\n"); 298 pr_err("\n");
296} 299}
297 300
@@ -372,7 +375,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
372 OPT_CALLBACK('x', "exec", NULL, "executable|path", 375 OPT_CALLBACK('x', "exec", NULL, "executable|path",
373 "target executable name or path", opt_set_target), 376 "target executable name or path", opt_set_target),
374 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 377 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
375 "Disable symbol demangling"), 378 "Enable symbol demangling"),
379 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
380 "Enable kernel symbol demangling"),
376 OPT_END() 381 OPT_END()
377 }; 382 };
378 int ret; 383 int ret;
@@ -467,7 +472,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
467 usage_with_options(probe_usage, options); 472 usage_with_options(probe_usage, options);
468 } 473 }
469 474
470 ret = show_line_range(&params.line_range, params.target); 475 ret = show_line_range(&params.line_range, params.target,
476 params.uprobes);
471 if (ret < 0) 477 if (ret < 0)
472 pr_err_with_code(" Error: Failed to show lines.", ret); 478 pr_err_with_code(" Error: Failed to show lines.", ret);
473 return ret; 479 return ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4869050e7194..2583a9b04317 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -14,6 +14,8 @@
14#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16 16
17#include "util/callchain.h"
18#include "util/cgroup.h"
17#include "util/header.h" 19#include "util/header.h"
18#include "util/event.h" 20#include "util/event.h"
19#include "util/evlist.h" 21#include "util/evlist.h"
@@ -65,8 +67,9 @@ static int process_synthesized_event(struct perf_tool *tool,
65 return record__write(rec, event, event->header.size); 67 return record__write(rec, event, event->header.size);
66} 68}
67 69
68static int record__mmap_read(struct record *rec, struct perf_mmap *md) 70static int record__mmap_read(struct record *rec, int idx)
69{ 71{
72 struct perf_mmap *md = &rec->evlist->mmap[idx];
70 unsigned int head = perf_mmap__read_head(md); 73 unsigned int head = perf_mmap__read_head(md);
71 unsigned int old = md->prev; 74 unsigned int old = md->prev;
72 unsigned char *data = md->base + page_size; 75 unsigned char *data = md->base + page_size;
@@ -102,8 +105,7 @@ static int record__mmap_read(struct record *rec, struct perf_mmap *md)
102 } 105 }
103 106
104 md->prev = old; 107 md->prev = old;
105 perf_mmap__write_tail(md, old); 108 perf_evlist__mmap_consume(rec->evlist, idx);
106
107out: 109out:
108 return rc; 110 return rc;
109} 111}
@@ -161,7 +163,7 @@ try_again:
161 163
162 if (perf_evlist__apply_filters(evlist)) { 164 if (perf_evlist__apply_filters(evlist)) {
163 error("failed to set filter with %d (%s)\n", errno, 165 error("failed to set filter with %d (%s)\n", errno,
164 strerror(errno)); 166 strerror_r(errno, msg, sizeof(msg)));
165 rc = -1; 167 rc = -1;
166 goto out; 168 goto out;
167 } 169 }
@@ -175,7 +177,8 @@ try_again:
175 "(current value: %u)\n", opts->mmap_pages); 177 "(current value: %u)\n", opts->mmap_pages);
176 rc = -errno; 178 rc = -errno;
177 } else { 179 } else {
178 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 180 pr_err("failed to mmap with %d (%s)\n", errno,
181 strerror_r(errno, msg, sizeof(msg)));
179 rc = -errno; 182 rc = -errno;
180 } 183 }
181 goto out; 184 goto out;
@@ -244,7 +247,7 @@ static int record__mmap_read_all(struct record *rec)
244 247
245 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 248 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
246 if (rec->evlist->mmap[i].base) { 249 if (rec->evlist->mmap[i].base) {
247 if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 250 if (record__mmap_read(rec, i) != 0) {
248 rc = -1; 251 rc = -1;
249 goto out; 252 goto out;
250 } 253 }
@@ -307,7 +310,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
307 struct record_opts *opts = &rec->opts; 310 struct record_opts *opts = &rec->opts;
308 struct perf_data_file *file = &rec->file; 311 struct perf_data_file *file = &rec->file;
309 struct perf_session *session; 312 struct perf_session *session;
310 bool disabled = false; 313 bool disabled = false, draining = false;
311 314
312 rec->progname = argv[0]; 315 rec->progname = argv[0];
313 316
@@ -456,9 +459,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
456 } 459 }
457 460
458 if (hits == rec->samples) { 461 if (hits == rec->samples) {
459 if (done) 462 if (done || draining)
460 break; 463 break;
461 err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1); 464 err = perf_evlist__poll(rec->evlist, -1);
462 /* 465 /*
463 * Propagate error, only if there's any. Ignore positive 466 * Propagate error, only if there's any. Ignore positive
464 * number of returned events and interrupt error. 467 * number of returned events and interrupt error.
@@ -466,6 +469,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
466 if (err > 0 || (err < 0 && errno == EINTR)) 469 if (err > 0 || (err < 0 && errno == EINTR))
467 err = 0; 470 err = 0;
468 waking++; 471 waking++;
472
473 if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
474 draining = true;
469 } 475 }
470 476
471 /* 477 /*
@@ -480,7 +486,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
480 } 486 }
481 487
482 if (forks && workload_exec_errno) { 488 if (forks && workload_exec_errno) {
483 char msg[512]; 489 char msg[STRERR_BUFSIZE];
484 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 490 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
485 pr_err("Workload failed: %s\n", emsg); 491 pr_err("Workload failed: %s\n", emsg);
486 err = -1; 492 err = -1;
@@ -620,145 +626,56 @@ error:
620 return ret; 626 return ret;
621} 627}
622 628
623#ifdef HAVE_DWARF_UNWIND_SUPPORT 629static void callchain_debug(void)
624static int get_stack_size(char *str, unsigned long *_size)
625{
626 char *endptr;
627 unsigned long size;
628 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
629
630 size = strtoul(str, &endptr, 0);
631
632 do {
633 if (*endptr)
634 break;
635
636 size = round_up(size, sizeof(u64));
637 if (!size || size > max_size)
638 break;
639
640 *_size = size;
641 return 0;
642
643 } while (0);
644
645 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
646 max_size, str);
647 return -1;
648}
649#endif /* HAVE_DWARF_UNWIND_SUPPORT */
650
651int record_parse_callchain(const char *arg, struct record_opts *opts)
652{
653 char *tok, *name, *saveptr = NULL;
654 char *buf;
655 int ret = -1;
656
657 /* We need buffer that we know we can write to. */
658 buf = malloc(strlen(arg) + 1);
659 if (!buf)
660 return -ENOMEM;
661
662 strcpy(buf, arg);
663
664 tok = strtok_r((char *)buf, ",", &saveptr);
665 name = tok ? : (char *)buf;
666
667 do {
668 /* Framepointer style */
669 if (!strncmp(name, "fp", sizeof("fp"))) {
670 if (!strtok_r(NULL, ",", &saveptr)) {
671 opts->call_graph = CALLCHAIN_FP;
672 ret = 0;
673 } else
674 pr_err("callchain: No more arguments "
675 "needed for -g fp\n");
676 break;
677
678#ifdef HAVE_DWARF_UNWIND_SUPPORT
679 /* Dwarf style */
680 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
681 const unsigned long default_stack_dump_size = 8192;
682
683 ret = 0;
684 opts->call_graph = CALLCHAIN_DWARF;
685 opts->stack_dump_size = default_stack_dump_size;
686
687 tok = strtok_r(NULL, ",", &saveptr);
688 if (tok) {
689 unsigned long size = 0;
690
691 ret = get_stack_size(tok, &size);
692 opts->stack_dump_size = size;
693 }
694#endif /* HAVE_DWARF_UNWIND_SUPPORT */
695 } else {
696 pr_err("callchain: Unknown --call-graph option "
697 "value: %s\n", arg);
698 break;
699 }
700
701 } while (0);
702
703 free(buf);
704 return ret;
705}
706
707static void callchain_debug(struct record_opts *opts)
708{ 630{
709 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" }; 631 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
710 632
711 pr_debug("callchain: type %s\n", str[opts->call_graph]); 633 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
712 634
713 if (opts->call_graph == CALLCHAIN_DWARF) 635 if (callchain_param.record_mode == CALLCHAIN_DWARF)
714 pr_debug("callchain: stack dump size %d\n", 636 pr_debug("callchain: stack dump size %d\n",
715 opts->stack_dump_size); 637 callchain_param.dump_size);
716} 638}
717 639
718int record_parse_callchain_opt(const struct option *opt, 640int record_parse_callchain_opt(const struct option *opt __maybe_unused,
719 const char *arg, 641 const char *arg,
720 int unset) 642 int unset)
721{ 643{
722 struct record_opts *opts = opt->value;
723 int ret; 644 int ret;
724 645
725 opts->call_graph_enabled = !unset; 646 callchain_param.enabled = !unset;
726 647
727 /* --no-call-graph */ 648 /* --no-call-graph */
728 if (unset) { 649 if (unset) {
729 opts->call_graph = CALLCHAIN_NONE; 650 callchain_param.record_mode = CALLCHAIN_NONE;
730 pr_debug("callchain: disabled\n"); 651 pr_debug("callchain: disabled\n");
731 return 0; 652 return 0;
732 } 653 }
733 654
734 ret = record_parse_callchain(arg, opts); 655 ret = parse_callchain_record_opt(arg);
735 if (!ret) 656 if (!ret)
736 callchain_debug(opts); 657 callchain_debug();
737 658
738 return ret; 659 return ret;
739} 660}
740 661
741int record_callchain_opt(const struct option *opt, 662int record_callchain_opt(const struct option *opt __maybe_unused,
742 const char *arg __maybe_unused, 663 const char *arg __maybe_unused,
743 int unset __maybe_unused) 664 int unset __maybe_unused)
744{ 665{
745 struct record_opts *opts = opt->value; 666 callchain_param.enabled = true;
746 667
747 opts->call_graph_enabled = !unset; 668 if (callchain_param.record_mode == CALLCHAIN_NONE)
669 callchain_param.record_mode = CALLCHAIN_FP;
748 670
749 if (opts->call_graph == CALLCHAIN_NONE) 671 callchain_debug();
750 opts->call_graph = CALLCHAIN_FP;
751
752 callchain_debug(opts);
753 return 0; 672 return 0;
754} 673}
755 674
756static int perf_record_config(const char *var, const char *value, void *cb) 675static int perf_record_config(const char *var, const char *value, void *cb)
757{ 676{
758 struct record *rec = cb;
759
760 if (!strcmp(var, "record.call-graph")) 677 if (!strcmp(var, "record.call-graph"))
761 return record_parse_callchain(value, &rec->opts); 678 var = "call-graph.record-mode"; /* fall-through */
762 679
763 return perf_default_config(var, value, cb); 680 return perf_default_config(var, value, cb);
764} 681}
@@ -781,6 +698,7 @@ static const char * const record_usage[] = {
781 */ 698 */
782static struct record record = { 699static struct record record = {
783 .opts = { 700 .opts = {
701 .sample_time = true,
784 .mmap_pages = UINT_MAX, 702 .mmap_pages = UINT_MAX,
785 .user_freq = UINT_MAX, 703 .user_freq = UINT_MAX,
786 .user_interval = ULLONG_MAX, 704 .user_interval = ULLONG_MAX,
@@ -907,7 +825,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
907 usage_with_options(record_usage, record_options); 825 usage_with_options(record_usage, record_options);
908 } 826 }
909 827
910 symbol__init(); 828 symbol__init(NULL);
911 829
912 if (symbol_conf.kptr_restrict) 830 if (symbol_conf.kptr_restrict)
913 pr_warning( 831 pr_warning(
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 21d830bafff3..140a6cd88351 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -58,17 +58,19 @@ struct report {
58 const char *symbol_filter_str; 58 const char *symbol_filter_str;
59 float min_percent; 59 float min_percent;
60 u64 nr_entries; 60 u64 nr_entries;
61 u64 queue_size;
61 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 62 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
62}; 63};
63 64
64static int report__config(const char *var, const char *value, void *cb) 65static int report__config(const char *var, const char *value, void *cb)
65{ 66{
67 struct report *rep = cb;
68
66 if (!strcmp(var, "report.group")) { 69 if (!strcmp(var, "report.group")) {
67 symbol_conf.event_group = perf_config_bool(var, value); 70 symbol_conf.event_group = perf_config_bool(var, value);
68 return 0; 71 return 0;
69 } 72 }
70 if (!strcmp(var, "report.percent-limit")) { 73 if (!strcmp(var, "report.percent-limit")) {
71 struct report *rep = cb;
72 rep->min_percent = strtof(value, NULL); 74 rep->min_percent = strtof(value, NULL);
73 return 0; 75 return 0;
74 } 76 }
@@ -76,6 +78,10 @@ static int report__config(const char *var, const char *value, void *cb)
76 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 78 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
77 return 0; 79 return 0;
78 } 80 }
81 if (!strcmp(var, "report.queue-size")) {
82 rep->queue_size = perf_config_u64(var, value);
83 return 0;
84 }
79 85
80 return perf_default_config(var, value, cb); 86 return perf_default_config(var, value, cb);
81} 87}
@@ -251,6 +257,13 @@ static int report__setup_sample_type(struct report *rep)
251 } 257 }
252 } 258 }
253 259
260 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
261 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
262 (sample_type & PERF_SAMPLE_STACK_USER))
263 callchain_param.record_mode = CALLCHAIN_DWARF;
264 else
265 callchain_param.record_mode = CALLCHAIN_FP;
266 }
254 return 0; 267 return 0;
255} 268}
256 269
@@ -282,12 +295,14 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
282 evname = buf; 295 evname = buf;
283 296
284 for_each_group_member(pos, evsel) { 297 for_each_group_member(pos, evsel) {
298 const struct hists *pos_hists = evsel__hists(pos);
299
285 if (symbol_conf.filter_relative) { 300 if (symbol_conf.filter_relative) {
286 nr_samples += pos->hists.stats.nr_non_filtered_samples; 301 nr_samples += pos_hists->stats.nr_non_filtered_samples;
287 nr_events += pos->hists.stats.total_non_filtered_period; 302 nr_events += pos_hists->stats.total_non_filtered_period;
288 } else { 303 } else {
289 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 304 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
290 nr_events += pos->hists.stats.total_period; 305 nr_events += pos_hists->stats.total_period;
291 } 306 }
292 } 307 }
293 } 308 }
@@ -312,7 +327,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
312 struct perf_evsel *pos; 327 struct perf_evsel *pos;
313 328
314 evlist__for_each(evlist, pos) { 329 evlist__for_each(evlist, pos) {
315 struct hists *hists = &pos->hists; 330 struct hists *hists = evsel__hists(pos);
316 const char *evname = perf_evsel__name(pos); 331 const char *evname = perf_evsel__name(pos);
317 332
318 if (symbol_conf.event_group && 333 if (symbol_conf.event_group &&
@@ -421,7 +436,7 @@ static void report__collapse_hists(struct report *rep)
421 ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); 436 ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
422 437
423 evlist__for_each(rep->session->evlist, pos) { 438 evlist__for_each(rep->session->evlist, pos) {
424 struct hists *hists = &pos->hists; 439 struct hists *hists = evsel__hists(pos);
425 440
426 if (pos->idx == 0) 441 if (pos->idx == 0)
427 hists->symbol_filter_str = rep->symbol_filter_str; 442 hists->symbol_filter_str = rep->symbol_filter_str;
@@ -431,7 +446,7 @@ static void report__collapse_hists(struct report *rep)
431 /* Non-group events are considered as leader */ 446 /* Non-group events are considered as leader */
432 if (symbol_conf.event_group && 447 if (symbol_conf.event_group &&
433 !perf_evsel__is_group_leader(pos)) { 448 !perf_evsel__is_group_leader(pos)) {
434 struct hists *leader_hists = &pos->leader->hists; 449 struct hists *leader_hists = evsel__hists(pos->leader);
435 450
436 hists__match(leader_hists, hists); 451 hists__match(leader_hists, hists);
437 hists__link(leader_hists, hists); 452 hists__link(leader_hists, hists);
@@ -479,6 +494,7 @@ static int __cmd_report(struct report *rep)
479 494
480 if (dump_trace) { 495 if (dump_trace) {
481 perf_session__fprintf_nr_events(session, stdout); 496 perf_session__fprintf_nr_events(session, stdout);
497 perf_evlist__fprintf_nr_events(session->evlist, stdout);
482 return 0; 498 return 0;
483 } 499 }
484 } 500 }
@@ -494,7 +510,7 @@ static int __cmd_report(struct report *rep)
494 } 510 }
495 511
496 evlist__for_each(session->evlist, pos) 512 evlist__for_each(session->evlist, pos)
497 hists__output_resort(&pos->hists); 513 hists__output_resort(evsel__hists(pos));
498 514
499 return report__browse_hists(rep); 515 return report__browse_hists(rep);
500} 516}
@@ -559,7 +575,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
559 struct stat st; 575 struct stat st;
560 bool has_br_stack = false; 576 bool has_br_stack = false;
561 int branch_mode = -1; 577 int branch_mode = -1;
562 int ret = -1;
563 char callchain_default_opt[] = "fractal,0.5,callee"; 578 char callchain_default_opt[] = "fractal,0.5,callee";
564 const char * const report_usage[] = { 579 const char * const report_usage[] = {
565 "perf report [<options>]", 580 "perf report [<options>]",
@@ -578,7 +593,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
578 .attr = perf_event__process_attr, 593 .attr = perf_event__process_attr,
579 .tracing_data = perf_event__process_tracing_data, 594 .tracing_data = perf_event__process_tracing_data,
580 .build_id = perf_event__process_build_id, 595 .build_id = perf_event__process_build_id,
581 .ordered_samples = true, 596 .ordered_events = true,
582 .ordering_requires_timestamps = true, 597 .ordering_requires_timestamps = true,
583 }, 598 },
584 .max_stack = PERF_MAX_STACK_DEPTH, 599 .max_stack = PERF_MAX_STACK_DEPTH,
@@ -674,6 +689,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
674 "objdump binary to use for disassembly and annotations"), 689 "objdump binary to use for disassembly and annotations"),
675 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 690 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
676 "Disable symbol demangling"), 691 "Disable symbol demangling"),
692 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
693 "Enable kernel symbol demangling"),
677 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 694 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
678 OPT_CALLBACK(0, "percent-limit", &report, "percent", 695 OPT_CALLBACK(0, "percent-limit", &report, "percent",
679 "Don't show entries under that percent", parse_percent_limit), 696 "Don't show entries under that percent", parse_percent_limit),
@@ -684,6 +701,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
684 struct perf_data_file file = { 701 struct perf_data_file file = {
685 .mode = PERF_DATA_MODE_READ, 702 .mode = PERF_DATA_MODE_READ,
686 }; 703 };
704 int ret = hists__init();
705
706 if (ret < 0)
707 return ret;
687 708
688 perf_config(report__config, &report); 709 perf_config(report__config, &report);
689 710
@@ -712,14 +733,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
712repeat: 733repeat:
713 session = perf_session__new(&file, false, &report.tool); 734 session = perf_session__new(&file, false, &report.tool);
714 if (session == NULL) 735 if (session == NULL)
715 return -ENOMEM; 736 return -1;
737
738 if (report.queue_size) {
739 ordered_events__set_alloc_size(&session->ordered_events,
740 report.queue_size);
741 }
716 742
717 report.session = session; 743 report.session = session;
718 744
719 has_br_stack = perf_header__has_feat(&session->header, 745 has_br_stack = perf_header__has_feat(&session->header,
720 HEADER_BRANCH_STACK); 746 HEADER_BRANCH_STACK);
721 747
722 if (branch_mode == -1 && has_br_stack) { 748 if ((branch_mode == -1 && has_br_stack) || branch_mode == 1) {
723 sort__mode = SORT_MODE__BRANCH; 749 sort__mode = SORT_MODE__BRANCH;
724 symbol_conf.cumulate_callchain = false; 750 symbol_conf.cumulate_callchain = false;
725 } 751 }
@@ -787,7 +813,7 @@ repeat:
787 } 813 }
788 } 814 }
789 815
790 if (symbol__init() < 0) 816 if (symbol__init(&session->header.env) < 0)
791 goto error; 817 goto error;
792 818
793 if (argc) { 819 if (argc) {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index f83c08c0dd87..891c3930080e 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -428,6 +428,7 @@ static u64 get_cpu_usage_nsec_parent(void)
428static int self_open_counters(void) 428static int self_open_counters(void)
429{ 429{
430 struct perf_event_attr attr; 430 struct perf_event_attr attr;
431 char sbuf[STRERR_BUFSIZE];
431 int fd; 432 int fd;
432 433
433 memset(&attr, 0, sizeof(attr)); 434 memset(&attr, 0, sizeof(attr));
@@ -440,7 +441,8 @@ static int self_open_counters(void)
440 441
441 if (fd < 0) 442 if (fd < 0)
442 pr_err("Error: sys_perf_event_open() syscall returned " 443 pr_err("Error: sys_perf_event_open() syscall returned "
443 "with %d (%s)\n", fd, strerror(errno)); 444 "with %d (%s)\n", fd,
445 strerror_r(errno, sbuf, sizeof(sbuf)));
444 return fd; 446 return fd;
445} 447}
446 448
@@ -1429,9 +1431,6 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1429{ 1431{
1430 int err = 0; 1432 int err = 0;
1431 1433
1432 evsel->hists.stats.total_period += sample->period;
1433 hists__inc_nr_samples(&evsel->hists, true);
1434
1435 if (evsel->handler != NULL) { 1434 if (evsel->handler != NULL) {
1436 tracepoint_handler f = evsel->handler; 1435 tracepoint_handler f = evsel->handler;
1437 err = f(tool, evsel, sample, machine); 1436 err = f(tool, evsel, sample, machine);
@@ -1462,6 +1461,8 @@ static int perf_sched__read_events(struct perf_sched *sched,
1462 return -1; 1461 return -1;
1463 } 1462 }
1464 1463
1464 symbol__init(&session->header.env);
1465
1465 if (perf_session__set_tracepoints_handlers(session, handlers)) 1466 if (perf_session__set_tracepoints_handlers(session, handlers))
1466 goto out_delete; 1467 goto out_delete;
1467 1468
@@ -1662,7 +1663,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1662 .comm = perf_event__process_comm, 1663 .comm = perf_event__process_comm,
1663 .lost = perf_event__process_lost, 1664 .lost = perf_event__process_lost,
1664 .fork = perf_sched__process_fork_event, 1665 .fork = perf_sched__process_fork_event,
1665 .ordered_samples = true, 1666 .ordered_events = true,
1666 }, 1667 },
1667 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), 1668 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1668 .sort_list = LIST_HEAD_INIT(sched.sort_list), 1669 .sort_list = LIST_HEAD_INIT(sched.sort_list),
@@ -1747,7 +1748,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1747 if (!strcmp(argv[0], "script")) 1748 if (!strcmp(argv[0], "script"))
1748 return cmd_script(argc, argv, prefix); 1749 return cmd_script(argc, argv, prefix);
1749 1750
1750 symbol__init();
1751 if (!strncmp(argv[0], "rec", 3)) { 1751 if (!strncmp(argv[0], "rec", 3)) {
1752 return __cmd_record(argc, argv); 1752 return __cmd_record(argc, argv);
1753 } else if (!strncmp(argv[0], "lat", 3)) { 1753 } else if (!strncmp(argv[0], "lat", 3)) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index f57035b89c15..9708a1290571 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -44,6 +44,7 @@ enum perf_output_field {
44 PERF_OUTPUT_ADDR = 1U << 10, 44 PERF_OUTPUT_ADDR = 1U << 10,
45 PERF_OUTPUT_SYMOFFSET = 1U << 11, 45 PERF_OUTPUT_SYMOFFSET = 1U << 11,
46 PERF_OUTPUT_SRCLINE = 1U << 12, 46 PERF_OUTPUT_SRCLINE = 1U << 12,
47 PERF_OUTPUT_PERIOD = 1U << 13,
47}; 48};
48 49
49struct output_option { 50struct output_option {
@@ -63,6 +64,7 @@ struct output_option {
63 {.str = "addr", .field = PERF_OUTPUT_ADDR}, 64 {.str = "addr", .field = PERF_OUTPUT_ADDR},
64 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, 65 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
65 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 66 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
67 {.str = "period", .field = PERF_OUTPUT_PERIOD},
66}; 68};
67 69
68/* default set to maintain compatibility with current format */ 70/* default set to maintain compatibility with current format */
@@ -80,7 +82,8 @@ static struct {
80 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 82 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
81 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 83 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
82 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 84 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
83 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 85 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
86 PERF_OUTPUT_PERIOD,
84 87
85 .invalid_fields = PERF_OUTPUT_TRACE, 88 .invalid_fields = PERF_OUTPUT_TRACE,
86 }, 89 },
@@ -91,7 +94,8 @@ static struct {
91 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 94 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
92 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 95 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
93 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 96 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
94 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 97 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
98 PERF_OUTPUT_PERIOD,
95 99
96 .invalid_fields = PERF_OUTPUT_TRACE, 100 .invalid_fields = PERF_OUTPUT_TRACE,
97 }, 101 },
@@ -110,7 +114,8 @@ static struct {
110 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 114 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
111 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 115 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
112 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 116 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
113 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 117 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
118 PERF_OUTPUT_PERIOD,
114 119
115 .invalid_fields = PERF_OUTPUT_TRACE, 120 .invalid_fields = PERF_OUTPUT_TRACE,
116 }, 121 },
@@ -184,10 +189,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", 189 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
185 PERF_OUTPUT_IP)) 190 PERF_OUTPUT_IP))
186 return -EINVAL; 191 return -EINVAL;
187
188 if (!no_callchain &&
189 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
190 symbol_conf.use_callchain = false;
191 } 192 }
192 193
193 if (PRINT_FIELD(ADDR) && 194 if (PRINT_FIELD(ADDR) &&
@@ -233,6 +234,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
233 PERF_OUTPUT_CPU)) 234 PERF_OUTPUT_CPU))
234 return -EINVAL; 235 return -EINVAL;
235 236
237 if (PRINT_FIELD(PERIOD) &&
238 perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD",
239 PERF_OUTPUT_PERIOD))
240 return -EINVAL;
241
236 return 0; 242 return 0;
237} 243}
238 244
@@ -290,6 +296,19 @@ static int perf_session__check_output_opt(struct perf_session *session)
290 set_print_ip_opts(&evsel->attr); 296 set_print_ip_opts(&evsel->attr);
291 } 297 }
292 298
299 if (!no_callchain) {
300 bool use_callchain = false;
301
302 evlist__for_each(session->evlist, evsel) {
303 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
304 use_callchain = true;
305 break;
306 }
307 }
308 if (!use_callchain)
309 symbol_conf.use_callchain = false;
310 }
311
293 /* 312 /*
294 * set default for tracepoints to print symbols only 313 * set default for tracepoints to print symbols only
295 * if callchains are present 314 * if callchains are present
@@ -439,6 +458,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
439 458
440 print_sample_start(sample, thread, evsel); 459 print_sample_start(sample, thread, evsel);
441 460
461 if (PRINT_FIELD(PERIOD))
462 printf("%10" PRIu64 " ", sample->period);
463
442 if (PRINT_FIELD(EVNAME)) { 464 if (PRINT_FIELD(EVNAME)) {
443 const char *evname = perf_evsel__name(evsel); 465 const char *evname = perf_evsel__name(evsel);
444 printf("%s: ", evname ? evname : "[unknown]"); 466 printf("%s: ", evname ? evname : "[unknown]");
@@ -476,6 +498,11 @@ static int default_start_script(const char *script __maybe_unused,
476 return 0; 498 return 0;
477} 499}
478 500
501static int default_flush_script(void)
502{
503 return 0;
504}
505
479static int default_stop_script(void) 506static int default_stop_script(void)
480{ 507{
481 return 0; 508 return 0;
@@ -489,6 +516,7 @@ static int default_generate_script(struct pevent *pevent __maybe_unused,
489 516
490static struct scripting_ops default_scripting_ops = { 517static struct scripting_ops default_scripting_ops = {
491 .start_script = default_start_script, 518 .start_script = default_start_script,
519 .flush_script = default_flush_script,
492 .stop_script = default_stop_script, 520 .stop_script = default_stop_script,
493 .process_event = process_event, 521 .process_event = process_event,
494 .generate_script = default_generate_script, 522 .generate_script = default_generate_script,
@@ -504,6 +532,11 @@ static void setup_scripting(void)
504 scripting_ops = &default_scripting_ops; 532 scripting_ops = &default_scripting_ops;
505} 533}
506 534
535static int flush_scripting(void)
536{
537 return scripting_ops->flush_script();
538}
539
507static int cleanup_scripting(void) 540static int cleanup_scripting(void)
508{ 541{
509 pr_debug("\nperf script stopped\n"); 542 pr_debug("\nperf script stopped\n");
@@ -552,7 +585,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
552 585
553 scripting_ops->process_event(event, sample, evsel, thread, &al); 586 scripting_ops->process_event(event, sample, evsel, thread, &al);
554 587
555 evsel->hists.stats.total_period += sample->period;
556 return 0; 588 return 0;
557} 589}
558 590
@@ -1471,12 +1503,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1471 bool show_full_info = false; 1503 bool show_full_info = false;
1472 bool header = false; 1504 bool header = false;
1473 bool header_only = false; 1505 bool header_only = false;
1506 bool script_started = false;
1474 char *rec_script_path = NULL; 1507 char *rec_script_path = NULL;
1475 char *rep_script_path = NULL; 1508 char *rep_script_path = NULL;
1476 struct perf_session *session; 1509 struct perf_session *session;
1477 char *script_path = NULL; 1510 char *script_path = NULL;
1478 const char **__argv; 1511 const char **__argv;
1479 int i, j, err; 1512 int i, j, err = 0;
1480 struct perf_script script = { 1513 struct perf_script script = {
1481 .tool = { 1514 .tool = {
1482 .sample = process_sample_event, 1515 .sample = process_sample_event,
@@ -1488,7 +1521,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1488 .attr = process_attr, 1521 .attr = process_attr,
1489 .tracing_data = perf_event__process_tracing_data, 1522 .tracing_data = perf_event__process_tracing_data,
1490 .build_id = perf_event__process_build_id, 1523 .build_id = perf_event__process_build_id,
1491 .ordered_samples = true, 1524 .ordered_events = true,
1492 .ordering_requires_timestamps = true, 1525 .ordering_requires_timestamps = true,
1493 }, 1526 },
1494 }; 1527 };
@@ -1523,7 +1556,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1523 "comma separated output fields prepend with 'type:'. " 1556 "comma separated output fields prepend with 'type:'. "
1524 "Valid types: hw,sw,trace,raw. " 1557 "Valid types: hw,sw,trace,raw. "
1525 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1558 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1526 "addr,symoff", parse_output_fields), 1559 "addr,symoff,period", parse_output_fields),
1527 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1560 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1528 "system-wide collection from all CPUs"), 1561 "system-wide collection from all CPUs"),
1529 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1562 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -1718,26 +1751,28 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1718 exit(-1); 1751 exit(-1);
1719 } 1752 }
1720 1753
1721 if (symbol__init() < 0)
1722 return -1;
1723 if (!script_name) 1754 if (!script_name)
1724 setup_pager(); 1755 setup_pager();
1725 1756
1726 session = perf_session__new(&file, false, &script.tool); 1757 session = perf_session__new(&file, false, &script.tool);
1727 if (session == NULL) 1758 if (session == NULL)
1728 return -ENOMEM; 1759 return -1;
1729 1760
1730 if (header || header_only) { 1761 if (header || header_only) {
1731 perf_session__fprintf_info(session, stdout, show_full_info); 1762 perf_session__fprintf_info(session, stdout, show_full_info);
1732 if (header_only) 1763 if (header_only)
1733 return 0; 1764 goto out_delete;
1734 } 1765 }
1735 1766
1767 if (symbol__init(&session->header.env) < 0)
1768 goto out_delete;
1769
1736 script.session = session; 1770 script.session = session;
1737 1771
1738 if (cpu_list) { 1772 if (cpu_list) {
1739 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1773 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
1740 return -1; 1774 if (err < 0)
1775 goto out_delete;
1741 } 1776 }
1742 1777
1743 if (!no_callchain) 1778 if (!no_callchain)
@@ -1752,53 +1787,62 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1752 if (output_set_by_user()) { 1787 if (output_set_by_user()) {
1753 fprintf(stderr, 1788 fprintf(stderr,
1754 "custom fields not supported for generated scripts"); 1789 "custom fields not supported for generated scripts");
1755 return -1; 1790 err = -EINVAL;
1791 goto out_delete;
1756 } 1792 }
1757 1793
1758 input = open(file.path, O_RDONLY); /* input_name */ 1794 input = open(file.path, O_RDONLY); /* input_name */
1759 if (input < 0) { 1795 if (input < 0) {
1796 err = -errno;
1760 perror("failed to open file"); 1797 perror("failed to open file");
1761 return -1; 1798 goto out_delete;
1762 } 1799 }
1763 1800
1764 err = fstat(input, &perf_stat); 1801 err = fstat(input, &perf_stat);
1765 if (err < 0) { 1802 if (err < 0) {
1766 perror("failed to stat file"); 1803 perror("failed to stat file");
1767 return -1; 1804 goto out_delete;
1768 } 1805 }
1769 1806
1770 if (!perf_stat.st_size) { 1807 if (!perf_stat.st_size) {
1771 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1808 fprintf(stderr, "zero-sized file, nothing to do!\n");
1772 return 0; 1809 goto out_delete;
1773 } 1810 }
1774 1811
1775 scripting_ops = script_spec__lookup(generate_script_lang); 1812 scripting_ops = script_spec__lookup(generate_script_lang);
1776 if (!scripting_ops) { 1813 if (!scripting_ops) {
1777 fprintf(stderr, "invalid language specifier"); 1814 fprintf(stderr, "invalid language specifier");
1778 return -1; 1815 err = -ENOENT;
1816 goto out_delete;
1779 } 1817 }
1780 1818
1781 err = scripting_ops->generate_script(session->tevent.pevent, 1819 err = scripting_ops->generate_script(session->tevent.pevent,
1782 "perf-script"); 1820 "perf-script");
1783 goto out; 1821 goto out_delete;
1784 } 1822 }
1785 1823
1786 if (script_name) { 1824 if (script_name) {
1787 err = scripting_ops->start_script(script_name, argc, argv); 1825 err = scripting_ops->start_script(script_name, argc, argv);
1788 if (err) 1826 if (err)
1789 goto out; 1827 goto out_delete;
1790 pr_debug("perf script started with script %s\n\n", script_name); 1828 pr_debug("perf script started with script %s\n\n", script_name);
1829 script_started = true;
1791 } 1830 }
1792 1831
1793 1832
1794 err = perf_session__check_output_opt(session); 1833 err = perf_session__check_output_opt(session);
1795 if (err < 0) 1834 if (err < 0)
1796 goto out; 1835 goto out_delete;
1797 1836
1798 err = __cmd_script(&script); 1837 err = __cmd_script(&script);
1799 1838
1839 flush_scripting();
1840
1841out_delete:
1800 perf_session__delete(session); 1842 perf_session__delete(session);
1801 cleanup_scripting(); 1843
1844 if (script_started)
1845 cleanup_scripting();
1802out: 1846out:
1803 return err; 1847 return err;
1804} 1848}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3e80aa10cfd8..055ce9232c9e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,6 +43,7 @@
43 43
44#include "perf.h" 44#include "perf.h"
45#include "builtin.h" 45#include "builtin.h"
46#include "util/cgroup.h"
46#include "util/util.h" 47#include "util/util.h"
47#include "util/parse-options.h" 48#include "util/parse-options.h"
48#include "util/parse-events.h" 49#include "util/parse-events.h"
@@ -593,7 +594,7 @@ static int __run_perf_stat(int argc, const char **argv)
593 594
594 if (perf_evlist__apply_filters(evsel_list)) { 595 if (perf_evlist__apply_filters(evsel_list)) {
595 error("failed to set filter with %d (%s)\n", errno, 596 error("failed to set filter with %d (%s)\n", errno,
596 strerror(errno)); 597 strerror_r(errno, msg, sizeof(msg)));
597 return -1; 598 return -1;
598 } 599 }
599 600
@@ -732,7 +733,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
732 } 733 }
733} 734}
734 735
735static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 736static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
736{ 737{
737 double msecs = avg / 1e6; 738 double msecs = avg / 1e6;
738 const char *fmt_v, *fmt_n; 739 const char *fmt_v, *fmt_n;
@@ -741,7 +742,7 @@ static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
741 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s"; 742 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
742 fmt_n = csv_output ? "%s" : "%-25s"; 743 fmt_n = csv_output ? "%s" : "%-25s";
743 744
744 aggr_printout(evsel, cpu, nr); 745 aggr_printout(evsel, id, nr);
745 746
746 scnprintf(name, sizeof(name), "%s%s", 747 scnprintf(name, sizeof(name), "%s%s",
747 perf_evsel__name(evsel), csv_output ? "" : " (msec)"); 748 perf_evsel__name(evsel), csv_output ? "" : " (msec)");
@@ -947,11 +948,12 @@ static void print_ll_cache_misses(int cpu,
947 fprintf(output, " of all LL-cache hits "); 948 fprintf(output, " of all LL-cache hits ");
948} 949}
949 950
950static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 951static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
951{ 952{
952 double total, ratio = 0.0, total2; 953 double total, ratio = 0.0, total2;
953 double sc = evsel->scale; 954 double sc = evsel->scale;
954 const char *fmt; 955 const char *fmt;
956 int cpu = cpu_map__id_to_cpu(id);
955 957
956 if (csv_output) { 958 if (csv_output) {
957 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; 959 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
@@ -962,7 +964,7 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
962 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s"; 964 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
963 } 965 }
964 966
965 aggr_printout(evsel, cpu, nr); 967 aggr_printout(evsel, id, nr);
966 968
967 if (aggr_mode == AGGR_GLOBAL) 969 if (aggr_mode == AGGR_GLOBAL)
968 cpu = 0; 970 cpu = 0;
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 2f1a5220c090..35b425b6293f 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1605,7 +1605,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1605 int ret = -EINVAL; 1605 int ret = -EINVAL;
1606 1606
1607 if (session == NULL) 1607 if (session == NULL)
1608 return -ENOMEM; 1608 return -1;
1609
1610 symbol__init(&session->header.env);
1609 1611
1610 (void)perf_header__process_sections(&session->header, 1612 (void)perf_header__process_sections(&session->header,
1611 perf_data_file__fd(session->file), 1613 perf_data_file__fd(session->file),
@@ -1920,7 +1922,7 @@ int cmd_timechart(int argc, const char **argv,
1920 .fork = process_fork_event, 1922 .fork = process_fork_event,
1921 .exit = process_exit_event, 1923 .exit = process_exit_event,
1922 .sample = process_sample_event, 1924 .sample = process_sample_event,
1923 .ordered_samples = true, 1925 .ordered_events = true,
1924 }, 1926 },
1925 .proc_num = 15, 1927 .proc_num = 15,
1926 .min_time = 1000000, 1928 .min_time = 1000000,
@@ -1982,8 +1984,6 @@ int cmd_timechart(int argc, const char **argv,
1982 return -1; 1984 return -1;
1983 } 1985 }
1984 1986
1985 symbol__init();
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, record_options, record_usage,
1989 PARSE_OPT_STOP_AT_NON_OPTION); 1989 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 377971dc89a3..0aa7747ff139 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -59,7 +59,7 @@
59 59
60#include <sys/syscall.h> 60#include <sys/syscall.h>
61#include <sys/ioctl.h> 61#include <sys/ioctl.h>
62#include <sys/poll.h> 62#include <poll.h>
63#include <sys/prctl.h> 63#include <sys/prctl.h>
64#include <sys/wait.h> 64#include <sys/wait.h>
65#include <sys/uio.h> 65#include <sys/uio.h>
@@ -251,6 +251,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
251 char bf[160]; 251 char bf[160];
252 int printed = 0; 252 int printed = 0;
253 const int win_width = top->winsize.ws_col - 1; 253 const int win_width = top->winsize.ws_col - 1;
254 struct hists *hists = evsel__hists(top->sym_evsel);
254 255
255 puts(CONSOLE_CLEAR); 256 puts(CONSOLE_CLEAR);
256 257
@@ -261,13 +262,13 @@ static void perf_top__print_sym_table(struct perf_top *top)
261 262
262 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 263 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
263 264
264 if (top->sym_evsel->hists.stats.nr_lost_warned != 265 if (hists->stats.nr_lost_warned !=
265 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) { 266 hists->stats.nr_events[PERF_RECORD_LOST]) {
266 top->sym_evsel->hists.stats.nr_lost_warned = 267 hists->stats.nr_lost_warned =
267 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 268 hists->stats.nr_events[PERF_RECORD_LOST];
268 color_fprintf(stdout, PERF_COLOR_RED, 269 color_fprintf(stdout, PERF_COLOR_RED,
269 "WARNING: LOST %d chunks, Check IO/CPU overload", 270 "WARNING: LOST %d chunks, Check IO/CPU overload",
270 top->sym_evsel->hists.stats.nr_lost_warned); 271 hists->stats.nr_lost_warned);
271 ++printed; 272 ++printed;
272 } 273 }
273 274
@@ -276,16 +277,19 @@ static void perf_top__print_sym_table(struct perf_top *top)
276 return; 277 return;
277 } 278 }
278 279
279 hists__collapse_resort(&top->sym_evsel->hists, NULL); 280 if (top->zero) {
280 hists__output_resort(&top->sym_evsel->hists); 281 hists__delete_entries(hists);
281 hists__decay_entries(&top->sym_evsel->hists, 282 } else {
282 top->hide_user_symbols, 283 hists__decay_entries(hists, top->hide_user_symbols,
283 top->hide_kernel_symbols); 284 top->hide_kernel_symbols);
284 hists__output_recalc_col_len(&top->sym_evsel->hists, 285 }
285 top->print_entries - printed); 286
287 hists__collapse_resort(hists, NULL);
288 hists__output_resort(hists);
289
290 hists__output_recalc_col_len(hists, top->print_entries - printed);
286 putchar('\n'); 291 putchar('\n');
287 hists__fprintf(&top->sym_evsel->hists, false, 292 hists__fprintf(hists, false, top->print_entries - printed, win_width,
288 top->print_entries - printed, win_width,
289 top->min_percent, stdout); 293 top->min_percent, stdout);
290} 294}
291 295
@@ -328,6 +332,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
328{ 332{
329 char *buf = malloc(0), *p; 333 char *buf = malloc(0), *p;
330 struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL; 334 struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
335 struct hists *hists = evsel__hists(top->sym_evsel);
331 struct rb_node *next; 336 struct rb_node *next;
332 size_t dummy = 0; 337 size_t dummy = 0;
333 338
@@ -345,7 +350,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
345 if (p) 350 if (p)
346 *p = 0; 351 *p = 0;
347 352
348 next = rb_first(&top->sym_evsel->hists.entries); 353 next = rb_first(&hists->entries);
349 while (next) { 354 while (next) {
350 n = rb_entry(next, struct hist_entry, rb_node); 355 n = rb_entry(next, struct hist_entry, rb_node);
351 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) { 356 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
@@ -427,18 +432,13 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
427 432
428 if (!perf_top__key_mapped(top, c)) { 433 if (!perf_top__key_mapped(top, c)) {
429 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 434 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
430 struct termios tc, save; 435 struct termios save;
431 436
432 perf_top__print_mapped_keys(top); 437 perf_top__print_mapped_keys(top);
433 fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 438 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
434 fflush(stdout); 439 fflush(stdout);
435 440
436 tcgetattr(0, &save); 441 set_term_quiet_input(&save);
437 tc = save;
438 tc.c_lflag &= ~(ICANON | ECHO);
439 tc.c_cc[VMIN] = 0;
440 tc.c_cc[VTIME] = 0;
441 tcsetattr(0, TCSANOW, &tc);
442 442
443 poll(&stdin_poll, 1, -1); 443 poll(&stdin_poll, 1, -1);
444 c = getc(stdin); 444 c = getc(stdin);
@@ -537,16 +537,24 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
537static void perf_top__sort_new_samples(void *arg) 537static void perf_top__sort_new_samples(void *arg)
538{ 538{
539 struct perf_top *t = arg; 539 struct perf_top *t = arg;
540 struct hists *hists;
541
540 perf_top__reset_sample_counters(t); 542 perf_top__reset_sample_counters(t);
541 543
542 if (t->evlist->selected != NULL) 544 if (t->evlist->selected != NULL)
543 t->sym_evsel = t->evlist->selected; 545 t->sym_evsel = t->evlist->selected;
544 546
545 hists__collapse_resort(&t->sym_evsel->hists, NULL); 547 hists = evsel__hists(t->sym_evsel);
546 hists__output_resort(&t->sym_evsel->hists); 548
547 hists__decay_entries(&t->sym_evsel->hists, 549 if (t->zero) {
548 t->hide_user_symbols, 550 hists__delete_entries(hists);
549 t->hide_kernel_symbols); 551 } else {
552 hists__decay_entries(hists, t->hide_user_symbols,
553 t->hide_kernel_symbols);
554 }
555
556 hists__collapse_resort(hists, NULL);
557 hists__output_resort(hists);
550} 558}
551 559
552static void *display_thread_tui(void *arg) 560static void *display_thread_tui(void *arg)
@@ -567,8 +575,10 @@ static void *display_thread_tui(void *arg)
567 * Zooming in/out UIDs. For now juse use whatever the user passed 575 * Zooming in/out UIDs. For now juse use whatever the user passed
568 * via --uid. 576 * via --uid.
569 */ 577 */
570 evlist__for_each(top->evlist, pos) 578 evlist__for_each(top->evlist, pos) {
571 pos->hists.uid_filter_str = top->record_opts.target.uid_str; 579 struct hists *hists = evsel__hists(pos);
580 hists->uid_filter_str = top->record_opts.target.uid_str;
581 }
572 582
573 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, 583 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent,
574 &top->session->header.env); 584 &top->session->header.env);
@@ -577,23 +587,32 @@ static void *display_thread_tui(void *arg)
577 return NULL; 587 return NULL;
578} 588}
579 589
590static void display_sig(int sig __maybe_unused)
591{
592 done = 1;
593}
594
595static void display_setup_sig(void)
596{
597 signal(SIGSEGV, display_sig);
598 signal(SIGFPE, display_sig);
599 signal(SIGINT, display_sig);
600 signal(SIGQUIT, display_sig);
601 signal(SIGTERM, display_sig);
602}
603
580static void *display_thread(void *arg) 604static void *display_thread(void *arg)
581{ 605{
582 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 606 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
583 struct termios tc, save; 607 struct termios save;
584 struct perf_top *top = arg; 608 struct perf_top *top = arg;
585 int delay_msecs, c; 609 int delay_msecs, c;
586 610
587 tcgetattr(0, &save); 611 display_setup_sig();
588 tc = save;
589 tc.c_lflag &= ~(ICANON | ECHO);
590 tc.c_cc[VMIN] = 0;
591 tc.c_cc[VTIME] = 0;
592
593 pthread__unblock_sigwinch(); 612 pthread__unblock_sigwinch();
594repeat: 613repeat:
595 delay_msecs = top->delay_secs * 1000; 614 delay_msecs = top->delay_secs * 1000;
596 tcsetattr(0, TCSANOW, &tc); 615 set_term_quiet_input(&save);
597 /* trash return*/ 616 /* trash return*/
598 getc(stdin); 617 getc(stdin);
599 618
@@ -620,13 +639,16 @@ repeat:
620 } 639 }
621 } 640 }
622 641
642 tcsetattr(0, TCSAFLUSH, &save);
623 return NULL; 643 return NULL;
624} 644}
625 645
626static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) 646static int symbol_filter(struct map *map, struct symbol *sym)
627{ 647{
628 const char *name = sym->name; 648 const char *name = sym->name;
629 649
650 if (!map->dso->kernel)
651 return 0;
630 /* 652 /*
631 * ppc64 uses function descriptors and appends a '.' to the 653 * ppc64 uses function descriptors and appends a '.' to the
632 * start of every instruction address. Remove it. 654 * start of every instruction address. Remove it.
@@ -750,6 +772,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
750 } 772 }
751 773
752 if (al.sym == NULL || !al.sym->ignore) { 774 if (al.sym == NULL || !al.sym->ignore) {
775 struct hists *hists = evsel__hists(evsel);
753 struct hist_entry_iter iter = { 776 struct hist_entry_iter iter = {
754 .add_entry_cb = hist_iter__top_callback, 777 .add_entry_cb = hist_iter__top_callback,
755 }; 778 };
@@ -759,14 +782,14 @@ static void perf_event__process_sample(struct perf_tool *tool,
759 else 782 else
760 iter.ops = &hist_iter_normal; 783 iter.ops = &hist_iter_normal;
761 784
762 pthread_mutex_lock(&evsel->hists.lock); 785 pthread_mutex_lock(&hists->lock);
763 786
764 err = hist_entry_iter__add(&iter, &al, evsel, sample, 787 err = hist_entry_iter__add(&iter, &al, evsel, sample,
765 top->max_stack, top); 788 top->max_stack, top);
766 if (err < 0) 789 if (err < 0)
767 pr_err("Problem incrementing symbol period, skipping event\n"); 790 pr_err("Problem incrementing symbol period, skipping event\n");
768 791
769 pthread_mutex_unlock(&evsel->hists.lock); 792 pthread_mutex_unlock(&hists->lock);
770 } 793 }
771 794
772 return; 795 return;
@@ -831,7 +854,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
831 perf_event__process_sample(&top->tool, event, evsel, 854 perf_event__process_sample(&top->tool, event, evsel,
832 &sample, machine); 855 &sample, machine);
833 } else if (event->header.type < PERF_RECORD_MAX) { 856 } else if (event->header.type < PERF_RECORD_MAX) {
834 hists__inc_nr_events(&evsel->hists, event->header.type); 857 hists__inc_nr_events(evsel__hists(evsel), event->header.type);
835 machine__process_event(machine, event, &sample); 858 machine__process_event(machine, event, &sample);
836 } else 859 } else
837 ++session->stats.nr_unknown_events; 860 ++session->stats.nr_unknown_events;
@@ -876,7 +899,7 @@ try_again:
876 899
877 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 900 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
878 ui__error("Failed to mmap with %d (%s)\n", 901 ui__error("Failed to mmap with %d (%s)\n",
879 errno, strerror(errno)); 902 errno, strerror_r(errno, msg, sizeof(msg)));
880 goto out_err; 903 goto out_err;
881 } 904 }
882 905
@@ -911,7 +934,7 @@ static int __cmd_top(struct perf_top *top)
911 934
912 top->session = perf_session__new(NULL, false, NULL); 935 top->session = perf_session__new(NULL, false, NULL);
913 if (top->session == NULL) 936 if (top->session == NULL)
914 return -ENOMEM; 937 return -1;
915 938
916 machines__set_symbol_filter(&top->session->machines, symbol_filter); 939 machines__set_symbol_filter(&top->session->machines, symbol_filter);
917 940
@@ -946,7 +969,7 @@ static int __cmd_top(struct perf_top *top)
946 perf_evlist__enable(top->evlist); 969 perf_evlist__enable(top->evlist);
947 970
948 /* Wait for a minimal set of events before starting the snapshot */ 971 /* Wait for a minimal set of events before starting the snapshot */
949 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 972 perf_evlist__poll(top->evlist, 100);
950 973
951 perf_top__mmap_read(top); 974 perf_top__mmap_read(top);
952 975
@@ -963,7 +986,7 @@ static int __cmd_top(struct perf_top *top)
963 param.sched_priority = top->realtime_prio; 986 param.sched_priority = top->realtime_prio;
964 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 987 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
965 ui__error("Could not set realtime priority.\n"); 988 ui__error("Could not set realtime priority.\n");
966 goto out_delete; 989 goto out_join;
967 } 990 }
968 } 991 }
969 992
@@ -973,10 +996,12 @@ static int __cmd_top(struct perf_top *top)
973 perf_top__mmap_read(top); 996 perf_top__mmap_read(top);
974 997
975 if (hits == top->samples) 998 if (hits == top->samples)
976 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 999 ret = perf_evlist__poll(top->evlist, 100);
977 } 1000 }
978 1001
979 ret = 0; 1002 ret = 0;
1003out_join:
1004 pthread_join(thread, NULL);
980out_delete: 1005out_delete:
981 perf_session__delete(top->session); 1006 perf_session__delete(top->session);
982 top->session = NULL; 1007 top->session = NULL;
@@ -1000,10 +1025,8 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1000 1025
1001static int perf_top_config(const char *var, const char *value, void *cb) 1026static int perf_top_config(const char *var, const char *value, void *cb)
1002{ 1027{
1003 struct perf_top *top = cb;
1004
1005 if (!strcmp(var, "top.call-graph")) 1028 if (!strcmp(var, "top.call-graph"))
1006 return record_parse_callchain(value, &top->record_opts); 1029 var = "call-graph.record-mode"; /* fall-through */
1007 if (!strcmp(var, "top.children")) { 1030 if (!strcmp(var, "top.children")) {
1008 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 1031 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1009 return 0; 1032 return 0;
@@ -1024,7 +1047,6 @@ parse_percent_limit(const struct option *opt, const char *arg,
1024 1047
1025int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1048int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1026{ 1049{
1027 int status = -1;
1028 char errbuf[BUFSIZ]; 1050 char errbuf[BUFSIZ];
1029 struct perf_top top = { 1051 struct perf_top top = {
1030 .count_filter = 5, 1052 .count_filter = 5,
@@ -1122,6 +1144,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1122 "Interleave source code with assembly code (default)"), 1144 "Interleave source code with assembly code (default)"),
1123 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 1145 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
1124 "Display raw encoding of assembly instructions (default)"), 1146 "Display raw encoding of assembly instructions (default)"),
1147 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1148 "Enable kernel symbol demangling"),
1125 OPT_STRING(0, "objdump", &objdump_path, "path", 1149 OPT_STRING(0, "objdump", &objdump_path, "path",
1126 "objdump binary to use for disassembly and annotations"), 1150 "objdump binary to use for disassembly and annotations"),
1127 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1151 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
@@ -1131,12 +1155,19 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1131 "Don't show entries under that percent", parse_percent_limit), 1155 "Don't show entries under that percent", parse_percent_limit),
1132 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 1156 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1133 "How to display percentage of filtered entries", parse_filter_percentage), 1157 "How to display percentage of filtered entries", parse_filter_percentage),
1158 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
1159 "width[,width...]",
1160 "don't try to adjust column width, use these fixed values"),
1134 OPT_END() 1161 OPT_END()
1135 }; 1162 };
1136 const char * const top_usage[] = { 1163 const char * const top_usage[] = {
1137 "perf top [<options>]", 1164 "perf top [<options>]",
1138 NULL 1165 NULL
1139 }; 1166 };
1167 int status = hists__init();
1168
1169 if (status < 0)
1170 return status;
1140 1171
1141 top.evlist = perf_evlist__new(); 1172 top.evlist = perf_evlist__new();
1142 if (top.evlist == NULL) 1173 if (top.evlist == NULL)
@@ -1217,7 +1248,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1217 symbol_conf.priv_size = sizeof(struct annotation); 1248 symbol_conf.priv_size = sizeof(struct annotation);
1218 1249
1219 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1250 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1220 if (symbol__init() < 0) 1251 if (symbol__init(NULL) < 0)
1221 return -1; 1252 return -1;
1222 1253
1223 sort__setup_elide(stdout); 1254 sort__setup_elide(stdout);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a6c375224f46..fb126459b134 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -402,6 +402,31 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
402 402
403#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 403#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
404 404
405static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
406 struct syscall_arg *arg)
407{
408 int printed = 0, flags = arg->val;
409
410#define P_MREMAP_FLAG(n) \
411 if (flags & MREMAP_##n) { \
412 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
413 flags &= ~MREMAP_##n; \
414 }
415
416 P_MREMAP_FLAG(MAYMOVE);
417#ifdef MREMAP_FIXED
418 P_MREMAP_FLAG(FIXED);
419#endif
420#undef P_MREMAP_FLAG
421
422 if (flags)
423 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
424
425 return printed;
426}
427
428#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
429
405static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 430static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
406 struct syscall_arg *arg) 431 struct syscall_arg *arg)
407{ 432{
@@ -1004,6 +1029,7 @@ static struct syscall_fmt {
1004 [2] = SCA_MMAP_PROT, /* prot */ }, }, 1029 [2] = SCA_MMAP_PROT, /* prot */ }, },
1005 { .name = "mremap", .hexret = true, 1030 { .name = "mremap", .hexret = true,
1006 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 1031 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
1032 [3] = SCA_MREMAP_FLAGS, /* flags */
1007 [4] = SCA_HEX, /* new_addr */ }, }, 1033 [4] = SCA_HEX, /* new_addr */ }, },
1008 { .name = "munlock", .errmsg = true, 1034 { .name = "munlock", .errmsg = true,
1009 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1035 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
@@ -1163,13 +1189,13 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
1163 if (thread == NULL) 1189 if (thread == NULL)
1164 goto fail; 1190 goto fail;
1165 1191
1166 if (thread->priv == NULL) 1192 if (thread__priv(thread) == NULL)
1167 thread->priv = thread_trace__new(); 1193 thread__set_priv(thread, thread_trace__new());
1168 1194
1169 if (thread->priv == NULL) 1195 if (thread__priv(thread) == NULL)
1170 goto fail; 1196 goto fail;
1171 1197
1172 ttrace = thread->priv; 1198 ttrace = thread__priv(thread);
1173 ++ttrace->nr_events; 1199 ++ttrace->nr_events;
1174 1200
1175 return ttrace; 1201 return ttrace;
@@ -1222,7 +1248,7 @@ struct trace {
1222 1248
1223static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 1249static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1224{ 1250{
1225 struct thread_trace *ttrace = thread->priv; 1251 struct thread_trace *ttrace = thread__priv(thread);
1226 1252
1227 if (fd > ttrace->paths.max) { 1253 if (fd > ttrace->paths.max) {
1228 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *)); 1254 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
@@ -1275,7 +1301,7 @@ static int thread__read_fd_path(struct thread *thread, int fd)
1275static const char *thread__fd_path(struct thread *thread, int fd, 1301static const char *thread__fd_path(struct thread *thread, int fd,
1276 struct trace *trace) 1302 struct trace *trace)
1277{ 1303{
1278 struct thread_trace *ttrace = thread->priv; 1304 struct thread_trace *ttrace = thread__priv(thread);
1279 1305
1280 if (ttrace == NULL) 1306 if (ttrace == NULL)
1281 return NULL; 1307 return NULL;
@@ -1312,7 +1338,7 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1312{ 1338{
1313 int fd = arg->val; 1339 int fd = arg->val;
1314 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); 1340 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1315 struct thread_trace *ttrace = arg->thread->priv; 1341 struct thread_trace *ttrace = thread__priv(arg->thread);
1316 1342
1317 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) 1343 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1318 zfree(&ttrace->paths.table[fd]); 1344 zfree(&ttrace->paths.table[fd]);
@@ -1385,7 +1411,7 @@ static int trace__tool_process(struct perf_tool *tool,
1385 1411
1386static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1412static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1387{ 1413{
1388 int err = symbol__init(); 1414 int err = symbol__init(NULL);
1389 1415
1390 if (err) 1416 if (err)
1391 return err; 1417 return err;
@@ -1669,7 +1695,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1669 union perf_event *event __maybe_unused, 1695 union perf_event *event __maybe_unused,
1670 struct perf_sample *sample) 1696 struct perf_sample *sample)
1671{ 1697{
1672 int ret; 1698 long ret;
1673 u64 duration = 0; 1699 u64 duration = 0;
1674 struct thread *thread; 1700 struct thread *thread;
1675 int id = perf_evsel__sc_tp_uint(evsel, id, sample); 1701 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
@@ -1722,9 +1748,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1722 1748
1723 if (sc->fmt == NULL) { 1749 if (sc->fmt == NULL) {
1724signed_print: 1750signed_print:
1725 fprintf(trace->output, ") = %d", ret); 1751 fprintf(trace->output, ") = %ld", ret);
1726 } else if (ret < 0 && sc->fmt->errmsg) { 1752 } else if (ret < 0 && sc->fmt->errmsg) {
1727 char bf[256]; 1753 char bf[STRERR_BUFSIZE];
1728 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 1754 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1729 *e = audit_errno_to_name(-ret); 1755 *e = audit_errno_to_name(-ret);
1730 1756
@@ -1732,7 +1758,7 @@ signed_print:
1732 } else if (ret == 0 && sc->fmt->timeout) 1758 } else if (ret == 0 && sc->fmt->timeout)
1733 fprintf(trace->output, ") = 0 Timeout"); 1759 fprintf(trace->output, ") = 0 Timeout");
1734 else if (sc->fmt->hexret) 1760 else if (sc->fmt->hexret)
1735 fprintf(trace->output, ") = %#x", ret); 1761 fprintf(trace->output, ") = %#lx", ret);
1736 else 1762 else
1737 goto signed_print; 1763 goto signed_print;
1738 1764
@@ -2018,6 +2044,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2018 int err = -1, i; 2044 int err = -1, i;
2019 unsigned long before; 2045 unsigned long before;
2020 const bool forks = argc > 0; 2046 const bool forks = argc > 0;
2047 bool draining = false;
2048 char sbuf[STRERR_BUFSIZE];
2021 2049
2022 trace->live = true; 2050 trace->live = true;
2023 2051
@@ -2079,7 +2107,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2079 2107
2080 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2108 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
2081 if (err < 0) { 2109 if (err < 0) {
2082 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); 2110 fprintf(trace->output, "Couldn't mmap the events: %s\n",
2111 strerror_r(errno, sbuf, sizeof(sbuf)));
2083 goto out_delete_evlist; 2112 goto out_delete_evlist;
2084 } 2113 }
2085 2114
@@ -2143,8 +2172,12 @@ next_event:
2143 if (trace->nr_events == before) { 2172 if (trace->nr_events == before) {
2144 int timeout = done ? 100 : -1; 2173 int timeout = done ? 100 : -1;
2145 2174
2146 if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0) 2175 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2176 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2177 draining = true;
2178
2147 goto again; 2179 goto again;
2180 }
2148 } else { 2181 } else {
2149 goto again; 2182 goto again;
2150 } 2183 }
@@ -2209,18 +2242,18 @@ static int trace__replay(struct trace *trace)
2209 trace->tool.tracing_data = perf_event__process_tracing_data; 2242 trace->tool.tracing_data = perf_event__process_tracing_data;
2210 trace->tool.build_id = perf_event__process_build_id; 2243 trace->tool.build_id = perf_event__process_build_id;
2211 2244
2212 trace->tool.ordered_samples = true; 2245 trace->tool.ordered_events = true;
2213 trace->tool.ordering_requires_timestamps = true; 2246 trace->tool.ordering_requires_timestamps = true;
2214 2247
2215 /* add tid to output */ 2248 /* add tid to output */
2216 trace->multiple_threads = true; 2249 trace->multiple_threads = true;
2217 2250
2218 if (symbol__init() < 0)
2219 return -1;
2220
2221 session = perf_session__new(&file, false, &trace->tool); 2251 session = perf_session__new(&file, false, &trace->tool);
2222 if (session == NULL) 2252 if (session == NULL)
2223 return -ENOMEM; 2253 return -1;
2254
2255 if (symbol__init(&session->header.env) < 0)
2256 goto out;
2224 2257
2225 trace->host = &session->machines.host; 2258 trace->host = &session->machines.host;
2226 2259
@@ -2348,7 +2381,7 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2348 FILE *fp = data->fp; 2381 FILE *fp = data->fp;
2349 size_t printed = data->printed; 2382 size_t printed = data->printed;
2350 struct trace *trace = data->trace; 2383 struct trace *trace = data->trace;
2351 struct thread_trace *ttrace = thread->priv; 2384 struct thread_trace *ttrace = thread__priv(thread);
2352 double ratio; 2385 double ratio;
2353 2386
2354 if (ttrace == NULL) 2387 if (ttrace == NULL)
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 1f67aa02d240..58f609198c6d 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -48,10 +48,6 @@ ifneq ($(ARCH),$(filter $(ARCH),x86 arm))
48 NO_LIBDW_DWARF_UNWIND := 1 48 NO_LIBDW_DWARF_UNWIND := 1
49endif 49endif
50 50
51ifeq ($(ARCH),powerpc)
52 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
53endif
54
55ifeq ($(LIBUNWIND_LIBS),) 51ifeq ($(LIBUNWIND_LIBS),)
56 NO_LIBUNWIND := 1 52 NO_LIBUNWIND := 1
57else 53else
@@ -120,6 +116,29 @@ ifdef PARSER_DEBUG
120 CFLAGS += -DPARSER_DEBUG 116 CFLAGS += -DPARSER_DEBUG
121endif 117endif
122 118
119ifndef NO_LIBPYTHON
120 # Try different combinations to accommodate systems that only have
121 # python[2][-config] in weird combinations but always preferring
122 # python2 and python2-config as per pep-0394. If we catch a
123 # python[-config] in version 3, the version check will kill it.
124 PYTHON2 := $(if $(call get-executable,python2),python2,python)
125 override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2))
126 PYTHON2_CONFIG := \
127 $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config)
128 override PYTHON_CONFIG := \
129 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
130
131 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
132
133 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
134 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
135
136 FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
137 FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
138 FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
139 FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
140endif
141
123CFLAGS += -fno-omit-frame-pointer 142CFLAGS += -fno-omit-frame-pointer
124CFLAGS += -ggdb3 143CFLAGS += -ggdb3
125CFLAGS += -funwind-tables 144CFLAGS += -funwind-tables
@@ -355,6 +374,12 @@ ifndef NO_LIBELF
355 endif # NO_DWARF 374 endif # NO_DWARF
356endif # NO_LIBELF 375endif # NO_LIBELF
357 376
377ifeq ($(ARCH),powerpc)
378 ifndef NO_DWARF
379 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
380 endif
381endif
382
358ifndef NO_LIBUNWIND 383ifndef NO_LIBUNWIND
359 ifneq ($(feature-libunwind), 1) 384 ifneq ($(feature-libunwind), 1)
360 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); 385 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
@@ -482,21 +507,14 @@ define disable-python_code
482 NO_LIBPYTHON := 1 507 NO_LIBPYTHON := 1
483endef 508endef
484 509
485override PYTHON := \ 510ifdef NO_LIBPYTHON
486 $(call get-executable-or-default,PYTHON,python) 511 $(call disable-python)
487
488ifndef PYTHON
489 $(call disable-python,python interpreter)
490else 512else
491 513
492 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 514 ifndef PYTHON
493 515 $(call disable-python,python interpreter)
494 ifdef NO_LIBPYTHON
495 $(call disable-python)
496 else 516 else
497 517 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
498 override PYTHON_CONFIG := \
499 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config)
500 518
501 ifndef PYTHON_CONFIG 519 ifndef PYTHON_CONFIG
502 $(call disable-python,python-config tool) 520 $(call disable-python,python-config tool)
@@ -635,11 +653,13 @@ else
635sysconfdir = $(prefix)/etc 653sysconfdir = $(prefix)/etc
636ETC_PERFCONFIG = etc/perfconfig 654ETC_PERFCONFIG = etc/perfconfig
637endif 655endif
656ifndef lib
638ifeq ($(IS_X86_64),1) 657ifeq ($(IS_X86_64),1)
639lib = lib64 658lib = lib64
640else 659else
641lib = lib 660lib = lib
642endif 661endif
662endif # lib
643libdir = $(prefix)/$(lib) 663libdir = $(prefix)/$(lib)
644 664
645# Shell quote (do not use $(call) to accommodate ancient setups); 665# Shell quote (do not use $(call) to accommodate ancient setups);
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 6088f8d8a434..72ab2984718e 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -101,25 +101,11 @@ FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
101test-libperl.bin: 101test-libperl.bin:
102 $(BUILD) $(FLAGS_PERL_EMBED) 102 $(BUILD) $(FLAGS_PERL_EMBED)
103 103
104override PYTHON := python
105override PYTHON_CONFIG := python-config
106
107escape-for-shell-sq = $(subst ','\'',$(1))
108shell-sq = '$(escape-for-shell-sq)'
109
110PYTHON_CONFIG_SQ = $(call shell-sq,$(PYTHON_CONFIG))
111
112PYTHON_EMBED_LDOPTS = $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
113PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
114PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
115PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
116FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
117
118test-libpython.bin: 104test-libpython.bin:
119 $(BUILD) $(FLAGS_PYTHON_EMBED) 105 $(BUILD)
120 106
121test-libpython-version.bin: 107test-libpython-version.bin:
122 $(BUILD) $(FLAGS_PYTHON_EMBED) 108 $(BUILD)
123 109
124test-libbfd.bin: 110test-libbfd.bin:
125 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 111 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 4d985e0f03f5..7076a62d0ff7 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -132,7 +132,7 @@ endef
132# 132#
133# Usage: bool-value = $(call is-absolute,path) 133# Usage: bool-value = $(call is-absolute,path)
134# 134#
135is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y) 135is-absolute = $(shell echo $(shell-sq) | grep -q ^/ && echo y)
136 136
137# lookup 137# lookup
138# 138#
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index 937e4324ad94..a3b13d7dc1d4 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -13,7 +13,7 @@
13#define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 13#define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
14#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 14#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
15#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 15#define cpu_relax() asm volatile("rep; nop" ::: "memory");
16#define CPUINFO_PROC "model name" 16#define CPUINFO_PROC {"model name"}
17#ifndef __NR_perf_event_open 17#ifndef __NR_perf_event_open
18# define __NR_perf_event_open 336 18# define __NR_perf_event_open 336
19#endif 19#endif
@@ -30,7 +30,7 @@
30#define wmb() asm volatile("sfence" ::: "memory") 30#define wmb() asm volatile("sfence" ::: "memory")
31#define rmb() asm volatile("lfence" ::: "memory") 31#define rmb() asm volatile("lfence" ::: "memory")
32#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 32#define cpu_relax() asm volatile("rep; nop" ::: "memory");
33#define CPUINFO_PROC "model name" 33#define CPUINFO_PROC {"model name"}
34#ifndef __NR_perf_event_open 34#ifndef __NR_perf_event_open
35# define __NR_perf_event_open 298 35# define __NR_perf_event_open 298
36#endif 36#endif
@@ -47,14 +47,14 @@
47#define mb() asm volatile ("sync" ::: "memory") 47#define mb() asm volatile ("sync" ::: "memory")
48#define wmb() asm volatile ("sync" ::: "memory") 48#define wmb() asm volatile ("sync" ::: "memory")
49#define rmb() asm volatile ("sync" ::: "memory") 49#define rmb() asm volatile ("sync" ::: "memory")
50#define CPUINFO_PROC "cpu" 50#define CPUINFO_PROC {"cpu"}
51#endif 51#endif
52 52
53#ifdef __s390__ 53#ifdef __s390__
54#define mb() asm volatile("bcr 15,0" ::: "memory") 54#define mb() asm volatile("bcr 15,0" ::: "memory")
55#define wmb() asm volatile("bcr 15,0" ::: "memory") 55#define wmb() asm volatile("bcr 15,0" ::: "memory")
56#define rmb() asm volatile("bcr 15,0" ::: "memory") 56#define rmb() asm volatile("bcr 15,0" ::: "memory")
57#define CPUINFO_PROC "vendor_id" 57#define CPUINFO_PROC {"vendor_id"}
58#endif 58#endif
59 59
60#ifdef __sh__ 60#ifdef __sh__
@@ -67,14 +67,14 @@
67# define wmb() asm volatile("" ::: "memory") 67# define wmb() asm volatile("" ::: "memory")
68# define rmb() asm volatile("" ::: "memory") 68# define rmb() asm volatile("" ::: "memory")
69#endif 69#endif
70#define CPUINFO_PROC "cpu type" 70#define CPUINFO_PROC {"cpu type"}
71#endif 71#endif
72 72
73#ifdef __hppa__ 73#ifdef __hppa__
74#define mb() asm volatile("" ::: "memory") 74#define mb() asm volatile("" ::: "memory")
75#define wmb() asm volatile("" ::: "memory") 75#define wmb() asm volatile("" ::: "memory")
76#define rmb() asm volatile("" ::: "memory") 76#define rmb() asm volatile("" ::: "memory")
77#define CPUINFO_PROC "cpu" 77#define CPUINFO_PROC {"cpu"}
78#endif 78#endif
79 79
80#ifdef __sparc__ 80#ifdef __sparc__
@@ -87,14 +87,14 @@
87#endif 87#endif
88#define wmb() asm volatile("":::"memory") 88#define wmb() asm volatile("":::"memory")
89#define rmb() asm volatile("":::"memory") 89#define rmb() asm volatile("":::"memory")
90#define CPUINFO_PROC "cpu" 90#define CPUINFO_PROC {"cpu"}
91#endif 91#endif
92 92
93#ifdef __alpha__ 93#ifdef __alpha__
94#define mb() asm volatile("mb" ::: "memory") 94#define mb() asm volatile("mb" ::: "memory")
95#define wmb() asm volatile("wmb" ::: "memory") 95#define wmb() asm volatile("wmb" ::: "memory")
96#define rmb() asm volatile("mb" ::: "memory") 96#define rmb() asm volatile("mb" ::: "memory")
97#define CPUINFO_PROC "cpu model" 97#define CPUINFO_PROC {"cpu model"}
98#endif 98#endif
99 99
100#ifdef __ia64__ 100#ifdef __ia64__
@@ -102,7 +102,7 @@
102#define wmb() asm volatile ("mf" ::: "memory") 102#define wmb() asm volatile ("mf" ::: "memory")
103#define rmb() asm volatile ("mf" ::: "memory") 103#define rmb() asm volatile ("mf" ::: "memory")
104#define cpu_relax() asm volatile ("hint @pause" ::: "memory") 104#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
105#define CPUINFO_PROC "model name" 105#define CPUINFO_PROC {"model name"}
106#endif 106#endif
107 107
108#ifdef __arm__ 108#ifdef __arm__
@@ -113,7 +113,7 @@
113#define mb() ((void(*)(void))0xffff0fa0)() 113#define mb() ((void(*)(void))0xffff0fa0)()
114#define wmb() ((void(*)(void))0xffff0fa0)() 114#define wmb() ((void(*)(void))0xffff0fa0)()
115#define rmb() ((void(*)(void))0xffff0fa0)() 115#define rmb() ((void(*)(void))0xffff0fa0)()
116#define CPUINFO_PROC "Processor" 116#define CPUINFO_PROC {"model name", "Processor"}
117#endif 117#endif
118 118
119#ifdef __aarch64__ 119#ifdef __aarch64__
@@ -133,28 +133,28 @@
133 : "memory") 133 : "memory")
134#define wmb() mb() 134#define wmb() mb()
135#define rmb() mb() 135#define rmb() mb()
136#define CPUINFO_PROC "cpu model" 136#define CPUINFO_PROC {"cpu model"}
137#endif 137#endif
138 138
139#ifdef __arc__ 139#ifdef __arc__
140#define mb() asm volatile("" ::: "memory") 140#define mb() asm volatile("" ::: "memory")
141#define wmb() asm volatile("" ::: "memory") 141#define wmb() asm volatile("" ::: "memory")
142#define rmb() asm volatile("" ::: "memory") 142#define rmb() asm volatile("" ::: "memory")
143#define CPUINFO_PROC "Processor" 143#define CPUINFO_PROC {"Processor"}
144#endif 144#endif
145 145
146#ifdef __metag__ 146#ifdef __metag__
147#define mb() asm volatile("" ::: "memory") 147#define mb() asm volatile("" ::: "memory")
148#define wmb() asm volatile("" ::: "memory") 148#define wmb() asm volatile("" ::: "memory")
149#define rmb() asm volatile("" ::: "memory") 149#define rmb() asm volatile("" ::: "memory")
150#define CPUINFO_PROC "CPU" 150#define CPUINFO_PROC {"CPU"}
151#endif 151#endif
152 152
153#ifdef __xtensa__ 153#ifdef __xtensa__
154#define mb() asm volatile("memw" ::: "memory") 154#define mb() asm volatile("memw" ::: "memory")
155#define wmb() asm volatile("memw" ::: "memory") 155#define wmb() asm volatile("memw" ::: "memory")
156#define rmb() asm volatile("" ::: "memory") 156#define rmb() asm volatile("" ::: "memory")
157#define CPUINFO_PROC "core ID" 157#define CPUINFO_PROC {"core ID"}
158#endif 158#endif
159 159
160#ifdef __tile__ 160#ifdef __tile__
@@ -162,7 +162,7 @@
162#define wmb() asm volatile ("mf" ::: "memory") 162#define wmb() asm volatile ("mf" ::: "memory")
163#define rmb() asm volatile ("mf" ::: "memory") 163#define rmb() asm volatile ("mf" ::: "memory")
164#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory") 164#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory")
165#define CPUINFO_PROC "model name" 165#define CPUINFO_PROC {"model name"}
166#endif 166#endif
167 167
168#define barrier() asm volatile ("" ::: "memory") 168#define barrier() asm volatile ("" ::: "memory")
diff --git a/tools/perf/perf-with-kcore.sh b/tools/perf/perf-with-kcore.sh
new file mode 100644
index 000000000000..c7ff90a90e4e
--- /dev/null
+++ b/tools/perf/perf-with-kcore.sh
@@ -0,0 +1,259 @@
1#!/bin/bash
2# perf-with-kcore: use perf with a copy of kcore
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
14set -e
15
16usage()
17{
18 echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
19 echo " <perf sub-command> can be record, script, report or inject" >&2
20 echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2
21 exit 1
22}
23
24find_perf()
25{
26 if [ -n "$PERF" ] ; then
27 return
28 fi
29 PERF=`which perf || true`
30 if [ -z "$PERF" ] ; then
31 echo "Failed to find perf" >&2
32 exit 1
33 fi
34 if [ ! -x "$PERF" ] ; then
35 echo "Failed to find perf" >&2
36 exit 1
37 fi
38 echo "Using $PERF"
39 "$PERF" version
40}
41
42copy_kcore()
43{
44 echo "Copying kcore"
45
46 if [ $EUID -eq 0 ] ; then
47 SUDO=""
48 else
49 SUDO="sudo"
50 fi
51
52 rm -f perf.data.junk
53 ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null &
54 PERF_PID=$!
55
56 # Need to make sure that perf has started
57 sleep 1
58
59 KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
60 case "$KCORE" in
61 "kcore added to build-id cache directory "*)
62 KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
63 ;;
64 *)
65 kill $PERF_PID
66 wait >/dev/null 2>/dev/null || true
67 rm perf.data.junk
68 echo "$KCORE"
69 echo "Failed to find kcore" >&2
70 exit 1
71 ;;
72 esac
73
74 kill $PERF_PID
75 wait >/dev/null 2>/dev/null || true
76 rm perf.data.junk
77
78 $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
79 $SUDO rm -f "$KCORE_DIR/kcore"
80 $SUDO rm -f "$KCORE_DIR/kallsyms"
81 $SUDO rm -f "$KCORE_DIR/modules"
82 $SUDO rmdir "$KCORE_DIR"
83
84 KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
85 KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
86
87 $SUDO chown $UID "$KCORE_DIR"
88 $SUDO chown $UID "$KCORE_DIR/kcore"
89 $SUDO chown $UID "$KCORE_DIR/kallsyms"
90 $SUDO chown $UID "$KCORE_DIR/modules"
91
92 $SUDO chgrp $GROUPS "$KCORE_DIR"
93 $SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
94 $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
95 $SUDO chgrp $GROUPS "$KCORE_DIR/modules"
96
97 ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
98}
99
100fix_buildid_cache_permissions()
101{
102 if [ $EUID -ne 0 ] ; then
103 echo "This script must be run as root via sudo " >&2
104 exit 1
105 fi
106
107 if [ -z "$SUDO_USER" ] ; then
108 echo "This script must be run via sudo" >&2
109 exit 1
110 fi
111
112 USER_HOME=$(bash <<< "echo ~$SUDO_USER")
113
114 if [ "$HOME" != "$USER_HOME" ] ; then
115 echo "Fix unnecessary because root has a home: $HOME" >&2
116 exit 1
117 fi
118
119 echo "Fixing buildid cache permissions"
120
121 find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
122 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
123 find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
124
125 if [ -n "$SUDO_GID" ] ; then
126 find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
127 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
128 find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
129 fi
130
131 echo "Done"
132}
133
134check_buildid_cache_permissions()
135{
136 if [ $EUID -eq 0 ] ; then
137 return
138 fi
139
140 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit)
141 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
142 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit)
143
144 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit)
145 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
146 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit)
147
148 if [ -n "$PERMISSIONS_OK" ] ; then
149 echo "*** WARNING *** buildid cache permissions may need fixing" >&2
150 fi
151}
152
153record()
154{
155 echo "Recording"
156
157 if [ $EUID -ne 0 ] ; then
158
159 if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
160 echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
161 fi
162
163 if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
164 echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
165 fi
166
167 if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
168 if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
169 echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
170 fi
171
172 if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
173 true
174 elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
175 true
176 elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
177 echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
178 fi
179 fi
180 fi
181
182 if [ -z "$1" ] ; then
183 echo "Workload is required for recording" >&2
184 usage
185 fi
186
187 if [ -e "$PERF_DATA_DIR" ] ; then
188 echo "'$PERF_DATA_DIR' exists" >&2
189 exit 1
190 fi
191
192 find_perf
193
194 mkdir "$PERF_DATA_DIR"
195
196 echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*"
197 "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true
198
199 if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
200 exit 1
201 fi
202
203 copy_kcore
204
205 echo "Done"
206}
207
208subcommand()
209{
210 find_perf
211 check_buildid_cache_permissions
212 echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*"
213 "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $*
214}
215
216if [ "$1" = "fix_buildid_cache_permissions" ] ; then
217 fix_buildid_cache_permissions
218 exit 0
219fi
220
221PERF_SUB_COMMAND=$1
222PERF_DATA_DIR=$2
223shift || true
224shift || true
225
226if [ -z "$PERF_SUB_COMMAND" ] ; then
227 usage
228fi
229
230if [ -z "$PERF_DATA_DIR" ] ; then
231 usage
232fi
233
234case "$PERF_SUB_COMMAND" in
235"record")
236 while [ "$1" != "--" ] ; do
237 PERF_OPTIONS+="$1 "
238 shift || break
239 done
240 if [ "$1" != "--" ] ; then
241 echo "Options and workload are required for recording" >&2
242 usage
243 fi
244 shift
245 record $*
246;;
247"script")
248 subcommand $*
249;;
250"report")
251 subcommand $*
252;;
253"inject")
254 subcommand $*
255;;
256*)
257 usage
258;;
259esac
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 2282d41879a2..452a8474d29d 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -313,6 +313,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
313 int status; 313 int status;
314 struct stat st; 314 struct stat st;
315 const char *prefix; 315 const char *prefix;
316 char sbuf[STRERR_BUFSIZE];
316 317
317 prefix = NULL; 318 prefix = NULL;
318 if (p->option & RUN_SETUP) 319 if (p->option & RUN_SETUP)
@@ -343,7 +344,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
343 status = 1; 344 status = 1;
344 /* Check for ENOSPC and EIO errors.. */ 345 /* Check for ENOSPC and EIO errors.. */
345 if (fflush(stdout)) { 346 if (fflush(stdout)) {
346 fprintf(stderr, "write failure on standard output: %s", strerror(errno)); 347 fprintf(stderr, "write failure on standard output: %s",
348 strerror_r(errno, sbuf, sizeof(sbuf)));
347 goto out; 349 goto out;
348 } 350 }
349 if (ferror(stdout)) { 351 if (ferror(stdout)) {
@@ -351,7 +353,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
351 goto out; 353 goto out;
352 } 354 }
353 if (fclose(stdout)) { 355 if (fclose(stdout)) {
354 fprintf(stderr, "close failed on standard output: %s", strerror(errno)); 356 fprintf(stderr, "close failed on standard output: %s",
357 strerror_r(errno, sbuf, sizeof(sbuf)));
355 goto out; 358 goto out;
356 } 359 }
357 status = 0; 360 status = 0;
@@ -466,6 +469,7 @@ void pthread__unblock_sigwinch(void)
466int main(int argc, const char **argv) 469int main(int argc, const char **argv)
467{ 470{
468 const char *cmd; 471 const char *cmd;
472 char sbuf[STRERR_BUFSIZE];
469 473
470 /* The page_size is placed in util object. */ 474 /* The page_size is placed in util object. */
471 page_size = sysconf(_SC_PAGE_SIZE); 475 page_size = sysconf(_SC_PAGE_SIZE);
@@ -561,7 +565,7 @@ int main(int argc, const char **argv)
561 } 565 }
562 566
563 fprintf(stderr, "Failed to run command '%s': %s\n", 567 fprintf(stderr, "Failed to run command '%s': %s\n",
564 cmd, strerror(errno)); 568 cmd, strerror_r(errno, sbuf, sizeof(sbuf)));
565out: 569out:
566 return 1; 570 return 1;
567} 571}
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 510c65f72858..220d44e44c1b 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -41,8 +41,6 @@ void pthread__unblock_sigwinch(void);
41 41
42struct record_opts { 42struct record_opts {
43 struct target target; 43 struct target target;
44 int call_graph;
45 bool call_graph_enabled;
46 bool group; 44 bool group;
47 bool inherit_stat; 45 bool inherit_stat;
48 bool no_buffering; 46 bool no_buffering;
@@ -60,7 +58,6 @@ struct record_opts {
60 u64 branch_stack; 58 u64 branch_stack;
61 u64 default_interval; 59 u64 default_interval;
62 u64 user_interval; 60 u64 user_interval;
63 u16 stack_dump_size;
64 bool sample_transaction; 61 bool sample_transaction;
65 unsigned initial_delay; 62 unsigned initial_delay;
66}; 63};
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 6f8b01bc6033..162c978f1491 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -6,6 +6,7 @@
6#include <unistd.h> 6#include <unistd.h>
7#include <string.h> 7#include <string.h>
8#include "builtin.h" 8#include "builtin.h"
9#include "hist.h"
9#include "intlist.h" 10#include "intlist.h"
10#include "tests.h" 11#include "tests.h"
11#include "debug.h" 12#include "debug.h"
@@ -154,6 +155,18 @@ static struct test {
154 .func = test__hists_cumulate, 155 .func = test__hists_cumulate,
155 }, 156 },
156 { 157 {
158 .desc = "Test tracking with sched_switch",
159 .func = test__switch_tracking,
160 },
161 {
162 .desc = "Filter fds with revents mask in a fdarray",
163 .func = test__fdarray__filter,
164 },
165 {
166 .desc = "Add fd to a fdarray, making it autogrow",
167 .func = test__fdarray__add,
168 },
169 {
157 .func = NULL, 170 .func = NULL,
158 }, 171 },
159}; 172};
@@ -185,9 +198,11 @@ static bool perf_test__matches(int curr, int argc, const char *argv[])
185static int run_test(struct test *test) 198static int run_test(struct test *test)
186{ 199{
187 int status, err = -1, child = fork(); 200 int status, err = -1, child = fork();
201 char sbuf[STRERR_BUFSIZE];
188 202
189 if (child < 0) { 203 if (child < 0) {
190 pr_err("failed to fork test: %s\n", strerror(errno)); 204 pr_err("failed to fork test: %s\n",
205 strerror_r(errno, sbuf, sizeof(sbuf)));
191 return -1; 206 return -1;
192 } 207 }
193 208
@@ -288,6 +303,10 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
288 OPT_END() 303 OPT_END()
289 }; 304 };
290 struct intlist *skiplist = NULL; 305 struct intlist *skiplist = NULL;
306 int ret = hists__init();
307
308 if (ret < 0)
309 return ret;
291 310
292 argc = parse_options(argc, argv, test_options, test_usage, 0); 311 argc = parse_options(argc, argv, test_options, test_usage, 0);
293 if (argc >= 1 && !strcmp(argv[0], "list")) 312 if (argc >= 1 && !strcmp(argv[0], "list"))
@@ -297,7 +316,7 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
297 symbol_conf.sort_by_name = true; 316 symbol_conf.sort_by_name = true;
298 symbol_conf.try_vmlinux_path = true; 317 symbol_conf.try_vmlinux_path = true;
299 318
300 if (symbol__init() < 0) 319 if (symbol__init(NULL) < 0)
301 return -1; 320 return -1;
302 321
303 if (skip != NULL) 322 if (skip != NULL)
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 96adb730b744..fc25e57f4a5d 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -9,6 +9,7 @@
9#include "perf_regs.h" 9#include "perf_regs.h"
10#include "map.h" 10#include "map.h"
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h"
12 13
13static int mmap_handler(struct perf_tool *tool __maybe_unused, 14static int mmap_handler(struct perf_tool *tool __maybe_unused,
14 union perf_event *event, 15 union perf_event *event,
@@ -120,6 +121,8 @@ int test__dwarf_unwind(void)
120 return -1; 121 return -1;
121 } 122 }
122 123
124 callchain_param.record_mode = CALLCHAIN_DWARF;
125
123 if (init_live_machine(machine)) { 126 if (init_live_machine(machine)) {
124 pr_err("Could not init machine\n"); 127 pr_err("Could not init machine\n");
125 goto out; 128 goto out;
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
new file mode 100644
index 000000000000..d24b837951d4
--- /dev/null
+++ b/tools/perf/tests/fdarray.c
@@ -0,0 +1,174 @@
1#include <api/fd/array.h>
2#include "util/debug.h"
3#include "tests/tests.h"
4
5static void fdarray__init_revents(struct fdarray *fda, short revents)
6{
7 int fd;
8
9 fda->nr = fda->nr_alloc;
10
11 for (fd = 0; fd < fda->nr; ++fd) {
12 fda->entries[fd].fd = fda->nr - fd;
13 fda->entries[fd].revents = revents;
14 }
15}
16
17static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE *fp)
18{
19 int printed = 0;
20
21 if (!verbose)
22 return 0;
23
24 printed += fprintf(fp, "\n%s: ", prefix);
25 return printed + fdarray__fprintf(fda, fp);
26}
27
28int test__fdarray__filter(void)
29{
30 int nr_fds, expected_fd[2], fd, err = TEST_FAIL;
31 struct fdarray *fda = fdarray__new(5, 5);
32
33 if (fda == NULL) {
34 pr_debug("\nfdarray__new() failed!");
35 goto out;
36 }
37
38 fdarray__init_revents(fda, POLLIN);
39 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
40 if (nr_fds != fda->nr_alloc) {
41 pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything",
42 nr_fds, fda->nr_alloc);
43 goto out_delete;
44 }
45
46 fdarray__init_revents(fda, POLLHUP);
47 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
48 if (nr_fds != 0) {
49 pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds",
50 nr_fds, fda->nr_alloc);
51 goto out_delete;
52 }
53
54 fdarray__init_revents(fda, POLLHUP);
55 fda->entries[2].revents = POLLIN;
56 expected_fd[0] = fda->entries[2].fd;
57
58 pr_debug("\nfiltering all but fda->entries[2]:");
59 fdarray__fprintf_prefix(fda, "before", stderr);
60 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
61 fdarray__fprintf_prefix(fda, " after", stderr);
62 if (nr_fds != 1) {
63 pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds);
64 goto out_delete;
65 }
66
67 if (fda->entries[0].fd != expected_fd[0]) {
68 pr_debug("\nfda->entries[0].fd=%d != %d\n",
69 fda->entries[0].fd, expected_fd[0]);
70 goto out_delete;
71 }
72
73 fdarray__init_revents(fda, POLLHUP);
74 fda->entries[0].revents = POLLIN;
75 expected_fd[0] = fda->entries[0].fd;
76 fda->entries[3].revents = POLLIN;
77 expected_fd[1] = fda->entries[3].fd;
78
79 pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):");
80 fdarray__fprintf_prefix(fda, "before", stderr);
81 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
82 fdarray__fprintf_prefix(fda, " after", stderr);
83 if (nr_fds != 2) {
84 pr_debug("\nfdarray__filter()=%d != 2, should have left just two events",
85 nr_fds);
86 goto out_delete;
87 }
88
89 for (fd = 0; fd < 2; ++fd) {
90 if (fda->entries[fd].fd != expected_fd[fd]) {
91 pr_debug("\nfda->entries[%d].fd=%d != %d\n", fd,
92 fda->entries[fd].fd, expected_fd[fd]);
93 goto out_delete;
94 }
95 }
96
97 pr_debug("\n");
98
99 err = 0;
100out_delete:
101 fdarray__delete(fda);
102out:
103 return err;
104}
105
106int test__fdarray__add(void)
107{
108 int err = TEST_FAIL;
109 struct fdarray *fda = fdarray__new(2, 2);
110
111 if (fda == NULL) {
112 pr_debug("\nfdarray__new() failed!");
113 goto out;
114 }
115
116#define FDA_CHECK(_idx, _fd, _revents) \
117 if (fda->entries[_idx].fd != _fd) { \
118 pr_debug("\n%d: fda->entries[%d](%d) != %d!", \
119 __LINE__, _idx, fda->entries[1].fd, _fd); \
120 goto out_delete; \
121 } \
122 if (fda->entries[_idx].events != (_revents)) { \
123 pr_debug("\n%d: fda->entries[%d].revents(%d) != %d!", \
124 __LINE__, _idx, fda->entries[_idx].fd, _revents); \
125 goto out_delete; \
126 }
127
128#define FDA_ADD(_idx, _fd, _revents, _nr) \
129 if (fdarray__add(fda, _fd, _revents) < 0) { \
130 pr_debug("\n%d: fdarray__add(fda, %d, %d) failed!", \
131 __LINE__,_fd, _revents); \
132 goto out_delete; \
133 } \
134 if (fda->nr != _nr) { \
135 pr_debug("\n%d: fdarray__add(fda, %d, %d)=%d != %d", \
136 __LINE__,_fd, _revents, fda->nr, _nr); \
137 goto out_delete; \
138 } \
139 FDA_CHECK(_idx, _fd, _revents)
140
141 FDA_ADD(0, 1, POLLIN, 1);
142 FDA_ADD(1, 2, POLLERR, 2);
143
144 fdarray__fprintf_prefix(fda, "before growing array", stderr);
145
146 FDA_ADD(2, 35, POLLHUP, 3);
147
148 if (fda->entries == NULL) {
149 pr_debug("\nfdarray__add(fda, 35, POLLHUP) should have allocated fda->pollfd!");
150 goto out_delete;
151 }
152
153 fdarray__fprintf_prefix(fda, "after 3rd add", stderr);
154
155 FDA_ADD(3, 88, POLLIN | POLLOUT, 4);
156
157 fdarray__fprintf_prefix(fda, "after 4th add", stderr);
158
159 FDA_CHECK(0, 1, POLLIN);
160 FDA_CHECK(1, 2, POLLERR);
161 FDA_CHECK(2, 35, POLLHUP);
162 FDA_CHECK(3, 88, POLLIN | POLLOUT);
163
164#undef FDA_ADD
165#undef FDA_CHECK
166
167 pr_debug("\n");
168
169 err = 0;
170out_delete:
171 fdarray__delete(fda);
172out:
173 return err;
174}
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 0ac240db2e24..614d5c4978ab 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -245,7 +245,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec
245static int test1(struct perf_evsel *evsel, struct machine *machine) 245static int test1(struct perf_evsel *evsel, struct machine *machine)
246{ 246{
247 int err; 247 int err;
248 struct hists *hists = &evsel->hists; 248 struct hists *hists = evsel__hists(evsel);
249 /* 249 /*
250 * expected output: 250 * expected output:
251 * 251 *
@@ -295,7 +295,7 @@ out:
295static int test2(struct perf_evsel *evsel, struct machine *machine) 295static int test2(struct perf_evsel *evsel, struct machine *machine)
296{ 296{
297 int err; 297 int err;
298 struct hists *hists = &evsel->hists; 298 struct hists *hists = evsel__hists(evsel);
299 /* 299 /*
300 * expected output: 300 * expected output:
301 * 301 *
@@ -442,7 +442,7 @@ out:
442static int test3(struct perf_evsel *evsel, struct machine *machine) 442static int test3(struct perf_evsel *evsel, struct machine *machine)
443{ 443{
444 int err; 444 int err;
445 struct hists *hists = &evsel->hists; 445 struct hists *hists = evsel__hists(evsel);
446 /* 446 /*
447 * expected output: 447 * expected output:
448 * 448 *
@@ -498,7 +498,7 @@ out:
498static int test4(struct perf_evsel *evsel, struct machine *machine) 498static int test4(struct perf_evsel *evsel, struct machine *machine)
499{ 499{
500 int err; 500 int err;
501 struct hists *hists = &evsel->hists; 501 struct hists *hists = evsel__hists(evsel);
502 /* 502 /*
503 * expected output: 503 * expected output:
504 * 504 *
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 821f581fd930..5a31787cc6b9 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -66,11 +66,12 @@ static int add_hist_entries(struct perf_evlist *evlist,
66 .ops = &hist_iter_normal, 66 .ops = &hist_iter_normal,
67 .hide_unresolved = false, 67 .hide_unresolved = false,
68 }; 68 };
69 struct hists *hists = evsel__hists(evsel);
69 70
70 /* make sure it has no filter at first */ 71 /* make sure it has no filter at first */
71 evsel->hists.thread_filter = NULL; 72 hists->thread_filter = NULL;
72 evsel->hists.dso_filter = NULL; 73 hists->dso_filter = NULL;
73 evsel->hists.symbol_filter_str = NULL; 74 hists->symbol_filter_str = NULL;
74 75
75 sample.pid = fake_samples[i].pid; 76 sample.pid = fake_samples[i].pid;
76 sample.tid = fake_samples[i].pid; 77 sample.tid = fake_samples[i].pid;
@@ -134,7 +135,7 @@ int test__hists_filter(void)
134 goto out; 135 goto out;
135 136
136 evlist__for_each(evlist, evsel) { 137 evlist__for_each(evlist, evsel) {
137 struct hists *hists = &evsel->hists; 138 struct hists *hists = evsel__hists(evsel);
138 139
139 hists__collapse_resort(hists, NULL); 140 hists__collapse_resort(hists, NULL);
140 hists__output_resort(hists); 141 hists__output_resort(hists);
@@ -160,7 +161,7 @@ int test__hists_filter(void)
160 hists->stats.total_non_filtered_period); 161 hists->stats.total_non_filtered_period);
161 162
162 /* now applying thread filter for 'bash' */ 163 /* now applying thread filter for 'bash' */
163 evsel->hists.thread_filter = fake_samples[9].thread; 164 hists->thread_filter = fake_samples[9].thread;
164 hists__filter_by_thread(hists); 165 hists__filter_by_thread(hists);
165 166
166 if (verbose > 2) { 167 if (verbose > 2) {
@@ -185,11 +186,11 @@ int test__hists_filter(void)
185 hists->stats.total_non_filtered_period == 400); 186 hists->stats.total_non_filtered_period == 400);
186 187
187 /* remove thread filter first */ 188 /* remove thread filter first */
188 evsel->hists.thread_filter = NULL; 189 hists->thread_filter = NULL;
189 hists__filter_by_thread(hists); 190 hists__filter_by_thread(hists);
190 191
191 /* now applying dso filter for 'kernel' */ 192 /* now applying dso filter for 'kernel' */
192 evsel->hists.dso_filter = fake_samples[0].map->dso; 193 hists->dso_filter = fake_samples[0].map->dso;
193 hists__filter_by_dso(hists); 194 hists__filter_by_dso(hists);
194 195
195 if (verbose > 2) { 196 if (verbose > 2) {
@@ -214,7 +215,7 @@ int test__hists_filter(void)
214 hists->stats.total_non_filtered_period == 300); 215 hists->stats.total_non_filtered_period == 300);
215 216
216 /* remove dso filter first */ 217 /* remove dso filter first */
217 evsel->hists.dso_filter = NULL; 218 hists->dso_filter = NULL;
218 hists__filter_by_dso(hists); 219 hists__filter_by_dso(hists);
219 220
220 /* 221 /*
@@ -224,7 +225,7 @@ int test__hists_filter(void)
224 * be counted as a separate entry but the sample count and 225 * be counted as a separate entry but the sample count and
225 * total period will be remained. 226 * total period will be remained.
226 */ 227 */
227 evsel->hists.symbol_filter_str = "main"; 228 hists->symbol_filter_str = "main";
228 hists__filter_by_symbol(hists); 229 hists__filter_by_symbol(hists);
229 230
230 if (verbose > 2) { 231 if (verbose > 2) {
@@ -249,8 +250,8 @@ int test__hists_filter(void)
249 hists->stats.total_non_filtered_period == 300); 250 hists->stats.total_non_filtered_period == 300);
250 251
251 /* now applying all filters at once. */ 252 /* now applying all filters at once. */
252 evsel->hists.thread_filter = fake_samples[1].thread; 253 hists->thread_filter = fake_samples[1].thread;
253 evsel->hists.dso_filter = fake_samples[1].map->dso; 254 hists->dso_filter = fake_samples[1].map->dso;
254 hists__filter_by_thread(hists); 255 hists__filter_by_thread(hists);
255 hists__filter_by_dso(hists); 256 hists__filter_by_dso(hists);
256 257
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index d4b34b0f50a2..278ba8344c23 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -73,6 +73,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
73 * "bash [libc] malloc" so total 9 entries will be in the tree. 73 * "bash [libc] malloc" so total 9 entries will be in the tree.
74 */ 74 */
75 evlist__for_each(evlist, evsel) { 75 evlist__for_each(evlist, evsel) {
76 struct hists *hists = evsel__hists(evsel);
77
76 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { 78 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) {
77 const union perf_event event = { 79 const union perf_event event = {
78 .header = { 80 .header = {
@@ -87,7 +89,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
87 &sample) < 0) 89 &sample) < 0)
88 goto out; 90 goto out;
89 91
90 he = __hists__add_entry(&evsel->hists, &al, NULL, 92 he = __hists__add_entry(hists, &al, NULL,
91 NULL, NULL, 1, 1, 0, true); 93 NULL, NULL, 1, 1, 0, true);
92 if (he == NULL) 94 if (he == NULL)
93 goto out; 95 goto out;
@@ -111,7 +113,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
111 &sample) < 0) 113 &sample) < 0)
112 goto out; 114 goto out;
113 115
114 he = __hists__add_entry(&evsel->hists, &al, NULL, 116 he = __hists__add_entry(hists, &al, NULL,
115 NULL, NULL, 1, 1, 0, true); 117 NULL, NULL, 1, 1, 0, true);
116 if (he == NULL) 118 if (he == NULL)
117 goto out; 119 goto out;
@@ -271,6 +273,7 @@ static int validate_link(struct hists *leader, struct hists *other)
271int test__hists_link(void) 273int test__hists_link(void)
272{ 274{
273 int err = -1; 275 int err = -1;
276 struct hists *hists, *first_hists;
274 struct machines machines; 277 struct machines machines;
275 struct machine *machine = NULL; 278 struct machine *machine = NULL;
276 struct perf_evsel *evsel, *first; 279 struct perf_evsel *evsel, *first;
@@ -306,24 +309,28 @@ int test__hists_link(void)
306 goto out; 309 goto out;
307 310
308 evlist__for_each(evlist, evsel) { 311 evlist__for_each(evlist, evsel) {
309 hists__collapse_resort(&evsel->hists, NULL); 312 hists = evsel__hists(evsel);
313 hists__collapse_resort(hists, NULL);
310 314
311 if (verbose > 2) 315 if (verbose > 2)
312 print_hists_in(&evsel->hists); 316 print_hists_in(hists);
313 } 317 }
314 318
315 first = perf_evlist__first(evlist); 319 first = perf_evlist__first(evlist);
316 evsel = perf_evlist__last(evlist); 320 evsel = perf_evlist__last(evlist);
317 321
322 first_hists = evsel__hists(first);
323 hists = evsel__hists(evsel);
324
318 /* match common entries */ 325 /* match common entries */
319 hists__match(&first->hists, &evsel->hists); 326 hists__match(first_hists, hists);
320 err = validate_match(&first->hists, &evsel->hists); 327 err = validate_match(first_hists, hists);
321 if (err) 328 if (err)
322 goto out; 329 goto out;
323 330
324 /* link common and/or dummy entries */ 331 /* link common and/or dummy entries */
325 hists__link(&first->hists, &evsel->hists); 332 hists__link(first_hists, hists);
326 err = validate_link(&first->hists, &evsel->hists); 333 err = validate_link(first_hists, hists);
327 if (err) 334 if (err)
328 goto out; 335 goto out;
329 336
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index e3bbd6c54c1b..a748f2be1222 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -122,7 +122,7 @@ typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
122static int test1(struct perf_evsel *evsel, struct machine *machine) 122static int test1(struct perf_evsel *evsel, struct machine *machine)
123{ 123{
124 int err; 124 int err;
125 struct hists *hists = &evsel->hists; 125 struct hists *hists = evsel__hists(evsel);
126 struct hist_entry *he; 126 struct hist_entry *he;
127 struct rb_root *root; 127 struct rb_root *root;
128 struct rb_node *node; 128 struct rb_node *node;
@@ -159,7 +159,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
159 print_hists_out(hists); 159 print_hists_out(hists);
160 } 160 }
161 161
162 root = &evsel->hists.entries; 162 root = &hists->entries;
163 node = rb_first(root); 163 node = rb_first(root);
164 he = rb_entry(node, struct hist_entry, rb_node); 164 he = rb_entry(node, struct hist_entry, rb_node);
165 TEST_ASSERT_VAL("Invalid hist entry", 165 TEST_ASSERT_VAL("Invalid hist entry",
@@ -224,7 +224,7 @@ out:
224static int test2(struct perf_evsel *evsel, struct machine *machine) 224static int test2(struct perf_evsel *evsel, struct machine *machine)
225{ 225{
226 int err; 226 int err;
227 struct hists *hists = &evsel->hists; 227 struct hists *hists = evsel__hists(evsel);
228 struct hist_entry *he; 228 struct hist_entry *he;
229 struct rb_root *root; 229 struct rb_root *root;
230 struct rb_node *node; 230 struct rb_node *node;
@@ -259,7 +259,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
259 print_hists_out(hists); 259 print_hists_out(hists);
260 } 260 }
261 261
262 root = &evsel->hists.entries; 262 root = &hists->entries;
263 node = rb_first(root); 263 node = rb_first(root);
264 he = rb_entry(node, struct hist_entry, rb_node); 264 he = rb_entry(node, struct hist_entry, rb_node);
265 TEST_ASSERT_VAL("Invalid hist entry", 265 TEST_ASSERT_VAL("Invalid hist entry",
@@ -280,7 +280,7 @@ out:
280static int test3(struct perf_evsel *evsel, struct machine *machine) 280static int test3(struct perf_evsel *evsel, struct machine *machine)
281{ 281{
282 int err; 282 int err;
283 struct hists *hists = &evsel->hists; 283 struct hists *hists = evsel__hists(evsel);
284 struct hist_entry *he; 284 struct hist_entry *he;
285 struct rb_root *root; 285 struct rb_root *root;
286 struct rb_node *node; 286 struct rb_node *node;
@@ -313,7 +313,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
313 print_hists_out(hists); 313 print_hists_out(hists);
314 } 314 }
315 315
316 root = &evsel->hists.entries; 316 root = &hists->entries;
317 node = rb_first(root); 317 node = rb_first(root);
318 he = rb_entry(node, struct hist_entry, rb_node); 318 he = rb_entry(node, struct hist_entry, rb_node);
319 TEST_ASSERT_VAL("Invalid hist entry", 319 TEST_ASSERT_VAL("Invalid hist entry",
@@ -354,7 +354,7 @@ out:
354static int test4(struct perf_evsel *evsel, struct machine *machine) 354static int test4(struct perf_evsel *evsel, struct machine *machine)
355{ 355{
356 int err; 356 int err;
357 struct hists *hists = &evsel->hists; 357 struct hists *hists = evsel__hists(evsel);
358 struct hist_entry *he; 358 struct hist_entry *he;
359 struct rb_root *root; 359 struct rb_root *root;
360 struct rb_node *node; 360 struct rb_node *node;
@@ -391,7 +391,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
391 print_hists_out(hists); 391 print_hists_out(hists);
392 } 392 }
393 393
394 root = &evsel->hists.entries; 394 root = &hists->entries;
395 node = rb_first(root); 395 node = rb_first(root);
396 he = rb_entry(node, struct hist_entry, rb_node); 396 he = rb_entry(node, struct hist_entry, rb_node);
397 TEST_ASSERT_VAL("Invalid hist entry", 397 TEST_ASSERT_VAL("Invalid hist entry",
@@ -456,7 +456,7 @@ out:
456static int test5(struct perf_evsel *evsel, struct machine *machine) 456static int test5(struct perf_evsel *evsel, struct machine *machine)
457{ 457{
458 int err; 458 int err;
459 struct hists *hists = &evsel->hists; 459 struct hists *hists = evsel__hists(evsel);
460 struct hist_entry *he; 460 struct hist_entry *he;
461 struct rb_root *root; 461 struct rb_root *root;
462 struct rb_node *node; 462 struct rb_node *node;
@@ -494,7 +494,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)
494 print_hists_out(hists); 494 print_hists_out(hists);
495 } 495 }
496 496
497 root = &evsel->hists.entries; 497 root = &hists->entries;
498 node = rb_first(root); 498 node = rb_first(root);
499 he = rb_entry(node, struct hist_entry, rb_node); 499 he = rb_entry(node, struct hist_entry, rb_node);
500 500
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 142263492f6f..9b9622a33932 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -31,6 +31,7 @@ int test__basic_mmap(void)
31 unsigned int nr_events[nsyscalls], 31 unsigned int nr_events[nsyscalls],
32 expected_nr_events[nsyscalls], i, j; 32 expected_nr_events[nsyscalls], i, j;
33 struct perf_evsel *evsels[nsyscalls], *evsel; 33 struct perf_evsel *evsels[nsyscalls], *evsel;
34 char sbuf[STRERR_BUFSIZE];
34 35
35 threads = thread_map__new(-1, getpid(), UINT_MAX); 36 threads = thread_map__new(-1, getpid(), UINT_MAX);
36 if (threads == NULL) { 37 if (threads == NULL) {
@@ -49,7 +50,7 @@ int test__basic_mmap(void)
49 sched_setaffinity(0, sizeof(cpu_set), &cpu_set); 50 sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
50 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 51 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
51 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 52 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
52 cpus->map[0], strerror(errno)); 53 cpus->map[0], strerror_r(errno, sbuf, sizeof(sbuf)));
53 goto out_free_cpus; 54 goto out_free_cpus;
54 } 55 }
55 56
@@ -79,7 +80,7 @@ int test__basic_mmap(void)
79 if (perf_evsel__open(evsels[i], cpus, threads) < 0) { 80 if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
80 pr_debug("failed to open counter: %s, " 81 pr_debug("failed to open counter: %s, "
81 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 82 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
82 strerror(errno)); 83 strerror_r(errno, sbuf, sizeof(sbuf)));
83 goto out_delete_evlist; 84 goto out_delete_evlist;
84 } 85 }
85 86
@@ -89,7 +90,7 @@ int test__basic_mmap(void)
89 90
90 if (perf_evlist__mmap(evlist, 128, true) < 0) { 91 if (perf_evlist__mmap(evlist, 128, true) < 0) {
91 pr_debug("failed to mmap events: %d (%s)\n", errno, 92 pr_debug("failed to mmap events: %d (%s)\n", errno,
92 strerror(errno)); 93 strerror_r(errno, sbuf, sizeof(sbuf)));
93 goto out_delete_evlist; 94 goto out_delete_evlist;
94 } 95 }
95 96
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
index 5fecdbd2f5f7..8fa82d1700c7 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -12,6 +12,7 @@ int test__open_syscall_event_on_all_cpus(void)
12 unsigned int nr_open_calls = 111, i; 12 unsigned int nr_open_calls = 111, i;
13 cpu_set_t cpu_set; 13 cpu_set_t cpu_set;
14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
15 char sbuf[STRERR_BUFSIZE];
15 16
16 if (threads == NULL) { 17 if (threads == NULL) {
17 pr_debug("thread_map__new\n"); 18 pr_debug("thread_map__new\n");
@@ -35,7 +36,7 @@ int test__open_syscall_event_on_all_cpus(void)
35 if (perf_evsel__open(evsel, cpus, threads) < 0) { 36 if (perf_evsel__open(evsel, cpus, threads) < 0) {
36 pr_debug("failed to open counter: %s, " 37 pr_debug("failed to open counter: %s, "
37 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 38 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
38 strerror(errno)); 39 strerror_r(errno, sbuf, sizeof(sbuf)));
39 goto out_evsel_delete; 40 goto out_evsel_delete;
40 } 41 }
41 42
@@ -56,7 +57,7 @@ int test__open_syscall_event_on_all_cpus(void)
56 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 57 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
57 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 58 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
58 cpus->map[cpu], 59 cpus->map[cpu],
59 strerror(errno)); 60 strerror_r(errno, sbuf, sizeof(sbuf)));
60 goto out_close_fd; 61 goto out_close_fd;
61 } 62 }
62 for (i = 0; i < ncalls; ++i) { 63 for (i = 0; i < ncalls; ++i) {
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index 0785b64ffd6c..127dcae0b760 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -22,6 +22,7 @@ int test__syscall_open_tp_fields(void)
22 struct perf_evlist *evlist = perf_evlist__new(); 22 struct perf_evlist *evlist = perf_evlist__new();
23 struct perf_evsel *evsel; 23 struct perf_evsel *evsel;
24 int err = -1, i, nr_events = 0, nr_polls = 0; 24 int err = -1, i, nr_events = 0, nr_polls = 0;
25 char sbuf[STRERR_BUFSIZE];
25 26
26 if (evlist == NULL) { 27 if (evlist == NULL) {
27 pr_debug("%s: perf_evlist__new\n", __func__); 28 pr_debug("%s: perf_evlist__new\n", __func__);
@@ -48,13 +49,15 @@ int test__syscall_open_tp_fields(void)
48 49
49 err = perf_evlist__open(evlist); 50 err = perf_evlist__open(evlist);
50 if (err < 0) { 51 if (err < 0) {
51 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 52 pr_debug("perf_evlist__open: %s\n",
53 strerror_r(errno, sbuf, sizeof(sbuf)));
52 goto out_delete_evlist; 54 goto out_delete_evlist;
53 } 55 }
54 56
55 err = perf_evlist__mmap(evlist, UINT_MAX, false); 57 err = perf_evlist__mmap(evlist, UINT_MAX, false);
56 if (err < 0) { 58 if (err < 0) {
57 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 59 pr_debug("perf_evlist__mmap: %s\n",
60 strerror_r(errno, sbuf, sizeof(sbuf)));
58 goto out_delete_evlist; 61 goto out_delete_evlist;
59 } 62 }
60 63
@@ -102,7 +105,7 @@ int test__syscall_open_tp_fields(void)
102 } 105 }
103 106
104 if (nr_events == before) 107 if (nr_events == before)
105 poll(evlist->pollfd, evlist->nr_fds, 10); 108 perf_evlist__poll(evlist, 10);
106 109
107 if (++nr_polls > 5) { 110 if (++nr_polls > 5) {
108 pr_debug("%s: no events!\n", __func__); 111 pr_debug("%s: no events!\n", __func__);
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
index c1dc7d25f38c..a33b2daae40f 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/open-syscall.c
@@ -9,6 +9,7 @@ int test__open_syscall_event(void)
9 struct perf_evsel *evsel; 9 struct perf_evsel *evsel;
10 unsigned int nr_open_calls = 111, i; 10 unsigned int nr_open_calls = 111, i;
11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
12 char sbuf[STRERR_BUFSIZE];
12 13
13 if (threads == NULL) { 14 if (threads == NULL) {
14 pr_debug("thread_map__new\n"); 15 pr_debug("thread_map__new\n");
@@ -24,7 +25,7 @@ int test__open_syscall_event(void)
24 if (perf_evsel__open_per_thread(evsel, threads) < 0) { 25 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
25 pr_debug("failed to open counter: %s, " 26 pr_debug("failed to open counter: %s, "
26 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 27 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
27 strerror(errno)); 28 strerror_r(errno, sbuf, sizeof(sbuf)));
28 goto out_evsel_delete; 29 goto out_evsel_delete;
29 } 30 }
30 31
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 5941927a4b7f..7f2f51f93619 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -457,6 +457,36 @@ static int test__checkevent_pmu_events(struct perf_evlist *evlist)
457 return 0; 457 return 0;
458} 458}
459 459
460
461static int test__checkevent_pmu_events_mix(struct perf_evlist *evlist)
462{
463 struct perf_evsel *evsel = perf_evlist__first(evlist);
464
465 /* pmu-event:u */
466 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
467 TEST_ASSERT_VAL("wrong exclude_user",
468 !evsel->attr.exclude_user);
469 TEST_ASSERT_VAL("wrong exclude_kernel",
470 evsel->attr.exclude_kernel);
471 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
472 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
473 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
474
475 /* cpu/pmu-event/u*/
476 evsel = perf_evsel__next(evsel);
477 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
478 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
479 TEST_ASSERT_VAL("wrong exclude_user",
480 !evsel->attr.exclude_user);
481 TEST_ASSERT_VAL("wrong exclude_kernel",
482 evsel->attr.exclude_kernel);
483 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
484 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
485 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
486
487 return 0;
488}
489
460static int test__checkterms_simple(struct list_head *terms) 490static int test__checkterms_simple(struct list_head *terms)
461{ 491{
462 struct parse_events_term *term; 492 struct parse_events_term *term;
@@ -1554,6 +1584,12 @@ static int test_pmu_events(void)
1554 e.check = test__checkevent_pmu_events; 1584 e.check = test__checkevent_pmu_events;
1555 1585
1556 ret = test_event(&e); 1586 ret = test_event(&e);
1587 if (ret)
1588 break;
1589 snprintf(name, MAX_NAME, "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
1590 e.name = name;
1591 e.check = test__checkevent_pmu_events_mix;
1592 ret = test_event(&e);
1557#undef MAX_NAME 1593#undef MAX_NAME
1558 } 1594 }
1559 1595
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index aca1a83dd13a..7a228a2a070b 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -59,6 +59,7 @@ int test__PERF_RECORD(void)
59 int err = -1, errs = 0, i, wakeups = 0; 59 int err = -1, errs = 0, i, wakeups = 0;
60 u32 cpu; 60 u32 cpu;
61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; 61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
62 char sbuf[STRERR_BUFSIZE];
62 63
63 if (evlist == NULL || argv == NULL) { 64 if (evlist == NULL || argv == NULL) {
64 pr_debug("Not enough memory to create evlist\n"); 65 pr_debug("Not enough memory to create evlist\n");
@@ -100,7 +101,8 @@ int test__PERF_RECORD(void)
100 101
101 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); 102 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
102 if (err < 0) { 103 if (err < 0) {
103 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); 104 pr_debug("sched__get_first_possible_cpu: %s\n",
105 strerror_r(errno, sbuf, sizeof(sbuf)));
104 goto out_delete_evlist; 106 goto out_delete_evlist;
105 } 107 }
106 108
@@ -110,7 +112,8 @@ int test__PERF_RECORD(void)
110 * So that we can check perf_sample.cpu on all the samples. 112 * So that we can check perf_sample.cpu on all the samples.
111 */ 113 */
112 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { 114 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
113 pr_debug("sched_setaffinity: %s\n", strerror(errno)); 115 pr_debug("sched_setaffinity: %s\n",
116 strerror_r(errno, sbuf, sizeof(sbuf)));
114 goto out_delete_evlist; 117 goto out_delete_evlist;
115 } 118 }
116 119
@@ -120,7 +123,8 @@ int test__PERF_RECORD(void)
120 */ 123 */
121 err = perf_evlist__open(evlist); 124 err = perf_evlist__open(evlist);
122 if (err < 0) { 125 if (err < 0) {
123 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 126 pr_debug("perf_evlist__open: %s\n",
127 strerror_r(errno, sbuf, sizeof(sbuf)));
124 goto out_delete_evlist; 128 goto out_delete_evlist;
125 } 129 }
126 130
@@ -131,7 +135,8 @@ int test__PERF_RECORD(void)
131 */ 135 */
132 err = perf_evlist__mmap(evlist, opts.mmap_pages, false); 136 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
133 if (err < 0) { 137 if (err < 0) {
134 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 138 pr_debug("perf_evlist__mmap: %s\n",
139 strerror_r(errno, sbuf, sizeof(sbuf)));
135 goto out_delete_evlist; 140 goto out_delete_evlist;
136 } 141 }
137 142
@@ -263,7 +268,7 @@ int test__PERF_RECORD(void)
263 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does. 268 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
264 */ 269 */
265 if (total_events == before && false) 270 if (total_events == before && false)
266 poll(evlist->pollfd, evlist->nr_fds, -1); 271 perf_evlist__poll(evlist, -1);
267 272
268 sleep(1); 273 sleep(1);
269 if (++wakeups > 5) { 274 if (++wakeups > 5) {
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 12b322fa3475..eeb68bb1972d 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -152,7 +152,7 @@ int test__pmu(void)
152 if (ret) 152 if (ret)
153 break; 153 break;
154 154
155 ret = perf_pmu__config_terms(&formats, &attr, terms); 155 ret = perf_pmu__config_terms(&formats, &attr, terms, false);
156 if (ret) 156 if (ret)
157 break; 157 break;
158 158
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c
index c04d1f268576..d31f2c4d9f64 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/tests/rdpmc.c
@@ -100,6 +100,7 @@ static int __test__rdpmc(void)
100 }; 100 };
101 u64 delta_sum = 0; 101 u64 delta_sum = 0;
102 struct sigaction sa; 102 struct sigaction sa;
103 char sbuf[STRERR_BUFSIZE];
103 104
104 sigfillset(&sa.sa_mask); 105 sigfillset(&sa.sa_mask);
105 sa.sa_sigaction = segfault_handler; 106 sa.sa_sigaction = segfault_handler;
@@ -109,14 +110,15 @@ static int __test__rdpmc(void)
109 perf_event_open_cloexec_flag()); 110 perf_event_open_cloexec_flag());
110 if (fd < 0) { 111 if (fd < 0) {
111 pr_err("Error: sys_perf_event_open() syscall returned " 112 pr_err("Error: sys_perf_event_open() syscall returned "
112 "with %d (%s)\n", fd, strerror(errno)); 113 "with %d (%s)\n", fd,
114 strerror_r(errno, sbuf, sizeof(sbuf)));
113 return -1; 115 return -1;
114 } 116 }
115 117
116 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); 118 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
117 if (addr == (void *)(-1)) { 119 if (addr == (void *)(-1)) {
118 pr_err("Error: mmap() syscall returned with (%s)\n", 120 pr_err("Error: mmap() syscall returned with (%s)\n",
119 strerror(errno)); 121 strerror_r(errno, sbuf, sizeof(sbuf)));
120 goto out_close; 122 goto out_close;
121 } 123 }
122 124
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 983d6b8562a8..1aa21c90731b 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -22,6 +22,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
22 volatile int tmp = 0; 22 volatile int tmp = 0;
23 u64 total_periods = 0; 23 u64 total_periods = 0;
24 int nr_samples = 0; 24 int nr_samples = 0;
25 char sbuf[STRERR_BUFSIZE];
25 union perf_event *event; 26 union perf_event *event;
26 struct perf_evsel *evsel; 27 struct perf_evsel *evsel;
27 struct perf_evlist *evlist; 28 struct perf_evlist *evlist;
@@ -62,14 +63,15 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
62 63
63 err = -errno; 64 err = -errno;
64 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", 65 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
65 strerror(errno), knob, (u64)attr.sample_freq); 66 strerror_r(errno, sbuf, sizeof(sbuf)),
67 knob, (u64)attr.sample_freq);
66 goto out_delete_evlist; 68 goto out_delete_evlist;
67 } 69 }
68 70
69 err = perf_evlist__mmap(evlist, 128, true); 71 err = perf_evlist__mmap(evlist, 128, true);
70 if (err < 0) { 72 if (err < 0) {
71 pr_debug("failed to mmap event: %d (%s)\n", errno, 73 pr_debug("failed to mmap event: %d (%s)\n", errno,
72 strerror(errno)); 74 strerror_r(errno, sbuf, sizeof(sbuf)));
73 goto out_delete_evlist; 75 goto out_delete_evlist;
74 } 76 }
75 77
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
new file mode 100644
index 000000000000..cc68648c7c55
--- /dev/null
+++ b/tools/perf/tests/switch-tracking.c
@@ -0,0 +1,572 @@
1#include <sys/time.h>
2#include <sys/prctl.h>
3#include <time.h>
4#include <stdlib.h>
5
6#include "parse-events.h"
7#include "evlist.h"
8#include "evsel.h"
9#include "thread_map.h"
10#include "cpumap.h"
11#include "tests.h"
12
13static int spin_sleep(void)
14{
15 struct timeval start, now, diff, maxtime;
16 struct timespec ts;
17 int err, i;
18
19 maxtime.tv_sec = 0;
20 maxtime.tv_usec = 50000;
21
22 err = gettimeofday(&start, NULL);
23 if (err)
24 return err;
25
26 /* Spin for 50ms */
27 while (1) {
28 for (i = 0; i < 1000; i++)
29 barrier();
30
31 err = gettimeofday(&now, NULL);
32 if (err)
33 return err;
34
35 timersub(&now, &start, &diff);
36 if (timercmp(&diff, &maxtime, > /* For checkpatch */))
37 break;
38 }
39
40 ts.tv_nsec = 50 * 1000 * 1000;
41 ts.tv_sec = 0;
42
43 /* Sleep for 50ms */
44 err = nanosleep(&ts, NULL);
45 if (err == EINTR)
46 err = 0;
47
48 return err;
49}
50
51struct switch_tracking {
52 struct perf_evsel *switch_evsel;
53 struct perf_evsel *cycles_evsel;
54 pid_t *tids;
55 int nr_tids;
56 int comm_seen[4];
57 int cycles_before_comm_1;
58 int cycles_between_comm_2_and_comm_3;
59 int cycles_after_comm_4;
60};
61
62static int check_comm(struct switch_tracking *switch_tracking,
63 union perf_event *event, const char *comm, int nr)
64{
65 if (event->header.type == PERF_RECORD_COMM &&
66 (pid_t)event->comm.pid == getpid() &&
67 (pid_t)event->comm.tid == getpid() &&
68 strcmp(event->comm.comm, comm) == 0) {
69 if (switch_tracking->comm_seen[nr]) {
70 pr_debug("Duplicate comm event\n");
71 return -1;
72 }
73 switch_tracking->comm_seen[nr] = 1;
74 pr_debug3("comm event: %s nr: %d\n", event->comm.comm, nr);
75 return 1;
76 }
77 return 0;
78}
79
80static int check_cpu(struct switch_tracking *switch_tracking, int cpu)
81{
82 int i, nr = cpu + 1;
83
84 if (cpu < 0)
85 return -1;
86
87 if (!switch_tracking->tids) {
88 switch_tracking->tids = calloc(nr, sizeof(pid_t));
89 if (!switch_tracking->tids)
90 return -1;
91 for (i = 0; i < nr; i++)
92 switch_tracking->tids[i] = -1;
93 switch_tracking->nr_tids = nr;
94 return 0;
95 }
96
97 if (cpu >= switch_tracking->nr_tids) {
98 void *addr;
99
100 addr = realloc(switch_tracking->tids, nr * sizeof(pid_t));
101 if (!addr)
102 return -1;
103 switch_tracking->tids = addr;
104 for (i = switch_tracking->nr_tids; i < nr; i++)
105 switch_tracking->tids[i] = -1;
106 switch_tracking->nr_tids = nr;
107 return 0;
108 }
109
110 return 0;
111}
112
113static int process_sample_event(struct perf_evlist *evlist,
114 union perf_event *event,
115 struct switch_tracking *switch_tracking)
116{
117 struct perf_sample sample;
118 struct perf_evsel *evsel;
119 pid_t next_tid, prev_tid;
120 int cpu, err;
121
122 if (perf_evlist__parse_sample(evlist, event, &sample)) {
123 pr_debug("perf_evlist__parse_sample failed\n");
124 return -1;
125 }
126
127 evsel = perf_evlist__id2evsel(evlist, sample.id);
128 if (evsel == switch_tracking->switch_evsel) {
129 next_tid = perf_evsel__intval(evsel, &sample, "next_pid");
130 prev_tid = perf_evsel__intval(evsel, &sample, "prev_pid");
131 cpu = sample.cpu;
132 pr_debug3("sched_switch: cpu: %d prev_tid %d next_tid %d\n",
133 cpu, prev_tid, next_tid);
134 err = check_cpu(switch_tracking, cpu);
135 if (err)
136 return err;
137 /*
138 * Check for no missing sched_switch events i.e. that the
139 * evsel->system_wide flag has worked.
140 */
141 if (switch_tracking->tids[cpu] != -1 &&
142 switch_tracking->tids[cpu] != prev_tid) {
143 pr_debug("Missing sched_switch events\n");
144 return -1;
145 }
146 switch_tracking->tids[cpu] = next_tid;
147 }
148
149 if (evsel == switch_tracking->cycles_evsel) {
150 pr_debug3("cycles event\n");
151 if (!switch_tracking->comm_seen[0])
152 switch_tracking->cycles_before_comm_1 = 1;
153 if (switch_tracking->comm_seen[1] &&
154 !switch_tracking->comm_seen[2])
155 switch_tracking->cycles_between_comm_2_and_comm_3 = 1;
156 if (switch_tracking->comm_seen[3])
157 switch_tracking->cycles_after_comm_4 = 1;
158 }
159
160 return 0;
161}
162
163static int process_event(struct perf_evlist *evlist, union perf_event *event,
164 struct switch_tracking *switch_tracking)
165{
166 if (event->header.type == PERF_RECORD_SAMPLE)
167 return process_sample_event(evlist, event, switch_tracking);
168
169 if (event->header.type == PERF_RECORD_COMM) {
170 int err, done = 0;
171
172 err = check_comm(switch_tracking, event, "Test COMM 1", 0);
173 if (err < 0)
174 return -1;
175 done += err;
176 err = check_comm(switch_tracking, event, "Test COMM 2", 1);
177 if (err < 0)
178 return -1;
179 done += err;
180 err = check_comm(switch_tracking, event, "Test COMM 3", 2);
181 if (err < 0)
182 return -1;
183 done += err;
184 err = check_comm(switch_tracking, event, "Test COMM 4", 3);
185 if (err < 0)
186 return -1;
187 done += err;
188 if (done != 1) {
189 pr_debug("Unexpected comm event\n");
190 return -1;
191 }
192 }
193
194 return 0;
195}
196
197struct event_node {
198 struct list_head list;
199 union perf_event *event;
200 u64 event_time;
201};
202
203static int add_event(struct perf_evlist *evlist, struct list_head *events,
204 union perf_event *event)
205{
206 struct perf_sample sample;
207 struct event_node *node;
208
209 node = malloc(sizeof(struct event_node));
210 if (!node) {
211 pr_debug("malloc failed\n");
212 return -1;
213 }
214 node->event = event;
215 list_add(&node->list, events);
216
217 if (perf_evlist__parse_sample(evlist, event, &sample)) {
218 pr_debug("perf_evlist__parse_sample failed\n");
219 return -1;
220 }
221
222 if (!sample.time) {
223 pr_debug("event with no time\n");
224 return -1;
225 }
226
227 node->event_time = sample.time;
228
229 return 0;
230}
231
232static void free_event_nodes(struct list_head *events)
233{
234 struct event_node *node;
235
236 while (!list_empty(events)) {
237 node = list_entry(events->next, struct event_node, list);
238 list_del(&node->list);
239 free(node);
240 }
241}
242
243static int compar(const void *a, const void *b)
244{
245 const struct event_node *nodea = a;
246 const struct event_node *nodeb = b;
247 s64 cmp = nodea->event_time - nodeb->event_time;
248
249 return cmp;
250}
251
252static int process_events(struct perf_evlist *evlist,
253 struct switch_tracking *switch_tracking)
254{
255 union perf_event *event;
256 unsigned pos, cnt = 0;
257 LIST_HEAD(events);
258 struct event_node *events_array, *node;
259 int i, ret;
260
261 for (i = 0; i < evlist->nr_mmaps; i++) {
262 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
263 cnt += 1;
264 ret = add_event(evlist, &events, event);
265 perf_evlist__mmap_consume(evlist, i);
266 if (ret < 0)
267 goto out_free_nodes;
268 }
269 }
270
271 events_array = calloc(cnt, sizeof(struct event_node));
272 if (!events_array) {
273 pr_debug("calloc failed\n");
274 ret = -1;
275 goto out_free_nodes;
276 }
277
278 pos = 0;
279 list_for_each_entry(node, &events, list)
280 events_array[pos++] = *node;
281
282 qsort(events_array, cnt, sizeof(struct event_node), compar);
283
284 for (pos = 0; pos < cnt; pos++) {
285 ret = process_event(evlist, events_array[pos].event,
286 switch_tracking);
287 if (ret < 0)
288 goto out_free;
289 }
290
291 ret = 0;
292out_free:
293 pr_debug("%u events recorded\n", cnt);
294 free(events_array);
295out_free_nodes:
296 free_event_nodes(&events);
297 return ret;
298}
299
300/**
301 * test__switch_tracking - test using sched_switch and tracking events.
302 *
303 * This function implements a test that checks that sched_switch events and
304 * tracking events can be recorded for a workload (current process) using the
305 * evsel->system_wide and evsel->tracking flags (respectively) with other events
306 * sometimes enabled or disabled.
307 */
308int test__switch_tracking(void)
309{
310 const char *sched_switch = "sched:sched_switch";
311 struct switch_tracking switch_tracking = { .tids = NULL, };
312 struct record_opts opts = {
313 .mmap_pages = UINT_MAX,
314 .user_freq = UINT_MAX,
315 .user_interval = ULLONG_MAX,
316 .freq = 4000,
317 .target = {
318 .uses_mmap = true,
319 },
320 };
321 struct thread_map *threads = NULL;
322 struct cpu_map *cpus = NULL;
323 struct perf_evlist *evlist = NULL;
324 struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel;
325 struct perf_evsel *switch_evsel, *tracking_evsel;
326 const char *comm;
327 int err = -1;
328
329 threads = thread_map__new(-1, getpid(), UINT_MAX);
330 if (!threads) {
331 pr_debug("thread_map__new failed!\n");
332 goto out_err;
333 }
334
335 cpus = cpu_map__new(NULL);
336 if (!cpus) {
337 pr_debug("cpu_map__new failed!\n");
338 goto out_err;
339 }
340
341 evlist = perf_evlist__new();
342 if (!evlist) {
343 pr_debug("perf_evlist__new failed!\n");
344 goto out_err;
345 }
346
347 perf_evlist__set_maps(evlist, cpus, threads);
348
349 /* First event */
350 err = parse_events(evlist, "cpu-clock:u");
351 if (err) {
352 pr_debug("Failed to parse event dummy:u\n");
353 goto out_err;
354 }
355
356 cpu_clocks_evsel = perf_evlist__last(evlist);
357
358 /* Second event */
359 err = parse_events(evlist, "cycles:u");
360 if (err) {
361 pr_debug("Failed to parse event cycles:u\n");
362 goto out_err;
363 }
364
365 cycles_evsel = perf_evlist__last(evlist);
366
367 /* Third event */
368 if (!perf_evlist__can_select_event(evlist, sched_switch)) {
369 fprintf(stderr, " (no sched_switch)");
370 err = 0;
371 goto out;
372 }
373
374 err = parse_events(evlist, sched_switch);
375 if (err) {
376 pr_debug("Failed to parse event %s\n", sched_switch);
377 goto out_err;
378 }
379
380 switch_evsel = perf_evlist__last(evlist);
381
382 perf_evsel__set_sample_bit(switch_evsel, CPU);
383 perf_evsel__set_sample_bit(switch_evsel, TIME);
384
385 switch_evsel->system_wide = true;
386 switch_evsel->no_aux_samples = true;
387 switch_evsel->immediate = true;
388
389 /* Test moving an event to the front */
390 if (cycles_evsel == perf_evlist__first(evlist)) {
391 pr_debug("cycles event already at front");
392 goto out_err;
393 }
394 perf_evlist__to_front(evlist, cycles_evsel);
395 if (cycles_evsel != perf_evlist__first(evlist)) {
396 pr_debug("Failed to move cycles event to front");
397 goto out_err;
398 }
399
400 perf_evsel__set_sample_bit(cycles_evsel, CPU);
401 perf_evsel__set_sample_bit(cycles_evsel, TIME);
402
403 /* Fourth event */
404 err = parse_events(evlist, "dummy:u");
405 if (err) {
406 pr_debug("Failed to parse event dummy:u\n");
407 goto out_err;
408 }
409
410 tracking_evsel = perf_evlist__last(evlist);
411
412 perf_evlist__set_tracking_event(evlist, tracking_evsel);
413
414 tracking_evsel->attr.freq = 0;
415 tracking_evsel->attr.sample_period = 1;
416
417 perf_evsel__set_sample_bit(tracking_evsel, TIME);
418
419 /* Config events */
420 perf_evlist__config(evlist, &opts);
421
422 /* Check moved event is still at the front */
423 if (cycles_evsel != perf_evlist__first(evlist)) {
424 pr_debug("Front event no longer at front");
425 goto out_err;
426 }
427
428 /* Check tracking event is tracking */
429 if (!tracking_evsel->attr.mmap || !tracking_evsel->attr.comm) {
430 pr_debug("Tracking event not tracking\n");
431 goto out_err;
432 }
433
434 /* Check non-tracking events are not tracking */
435 evlist__for_each(evlist, evsel) {
436 if (evsel != tracking_evsel) {
437 if (evsel->attr.mmap || evsel->attr.comm) {
438 pr_debug("Non-tracking event is tracking\n");
439 goto out_err;
440 }
441 }
442 }
443
444 if (perf_evlist__open(evlist) < 0) {
445 fprintf(stderr, " (not supported)");
446 err = 0;
447 goto out;
448 }
449
450 err = perf_evlist__mmap(evlist, UINT_MAX, false);
451 if (err) {
452 pr_debug("perf_evlist__mmap failed!\n");
453 goto out_err;
454 }
455
456 perf_evlist__enable(evlist);
457
458 err = perf_evlist__disable_event(evlist, cpu_clocks_evsel);
459 if (err) {
460 pr_debug("perf_evlist__disable_event failed!\n");
461 goto out_err;
462 }
463
464 err = spin_sleep();
465 if (err) {
466 pr_debug("spin_sleep failed!\n");
467 goto out_err;
468 }
469
470 comm = "Test COMM 1";
471 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
472 if (err) {
473 pr_debug("PR_SET_NAME failed!\n");
474 goto out_err;
475 }
476
477 err = perf_evlist__disable_event(evlist, cycles_evsel);
478 if (err) {
479 pr_debug("perf_evlist__disable_event failed!\n");
480 goto out_err;
481 }
482
483 comm = "Test COMM 2";
484 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
485 if (err) {
486 pr_debug("PR_SET_NAME failed!\n");
487 goto out_err;
488 }
489
490 err = spin_sleep();
491 if (err) {
492 pr_debug("spin_sleep failed!\n");
493 goto out_err;
494 }
495
496 comm = "Test COMM 3";
497 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
498 if (err) {
499 pr_debug("PR_SET_NAME failed!\n");
500 goto out_err;
501 }
502
503 err = perf_evlist__enable_event(evlist, cycles_evsel);
504 if (err) {
505 pr_debug("perf_evlist__disable_event failed!\n");
506 goto out_err;
507 }
508
509 comm = "Test COMM 4";
510 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
511 if (err) {
512 pr_debug("PR_SET_NAME failed!\n");
513 goto out_err;
514 }
515
516 err = spin_sleep();
517 if (err) {
518 pr_debug("spin_sleep failed!\n");
519 goto out_err;
520 }
521
522 perf_evlist__disable(evlist);
523
524 switch_tracking.switch_evsel = switch_evsel;
525 switch_tracking.cycles_evsel = cycles_evsel;
526
527 err = process_events(evlist, &switch_tracking);
528
529 zfree(&switch_tracking.tids);
530
531 if (err)
532 goto out_err;
533
534 /* Check all 4 comm events were seen i.e. that evsel->tracking works */
535 if (!switch_tracking.comm_seen[0] || !switch_tracking.comm_seen[1] ||
536 !switch_tracking.comm_seen[2] || !switch_tracking.comm_seen[3]) {
537 pr_debug("Missing comm events\n");
538 goto out_err;
539 }
540
541 /* Check cycles event got enabled */
542 if (!switch_tracking.cycles_before_comm_1) {
543 pr_debug("Missing cycles events\n");
544 goto out_err;
545 }
546
547 /* Check cycles event got disabled */
548 if (switch_tracking.cycles_between_comm_2_and_comm_3) {
549 pr_debug("cycles events even though event was disabled\n");
550 goto out_err;
551 }
552
553 /* Check cycles event got enabled again */
554 if (!switch_tracking.cycles_after_comm_4) {
555 pr_debug("Missing cycles events\n");
556 goto out_err;
557 }
558out:
559 if (evlist) {
560 perf_evlist__disable(evlist);
561 perf_evlist__delete(evlist);
562 } else {
563 cpu_map__delete(cpus);
564 thread_map__delete(threads);
565 }
566
567 return err;
568
569out_err:
570 err = -1;
571 goto out;
572}
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 5ff3db318f12..3a8fedef83bc 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -42,6 +42,7 @@ int test__task_exit(void)
42 .uses_mmap = true, 42 .uses_mmap = true,
43 }; 43 };
44 const char *argv[] = { "true", NULL }; 44 const char *argv[] = { "true", NULL };
45 char sbuf[STRERR_BUFSIZE];
45 46
46 signal(SIGCHLD, sig_handler); 47 signal(SIGCHLD, sig_handler);
47 48
@@ -82,13 +83,14 @@ int test__task_exit(void)
82 83
83 err = perf_evlist__open(evlist); 84 err = perf_evlist__open(evlist);
84 if (err < 0) { 85 if (err < 0) {
85 pr_debug("Couldn't open the evlist: %s\n", strerror(-err)); 86 pr_debug("Couldn't open the evlist: %s\n",
87 strerror_r(-err, sbuf, sizeof(sbuf)));
86 goto out_delete_evlist; 88 goto out_delete_evlist;
87 } 89 }
88 90
89 if (perf_evlist__mmap(evlist, 128, true) < 0) { 91 if (perf_evlist__mmap(evlist, 128, true) < 0) {
90 pr_debug("failed to mmap events: %d (%s)\n", errno, 92 pr_debug("failed to mmap events: %d (%s)\n", errno,
91 strerror(errno)); 93 strerror_r(errno, sbuf, sizeof(sbuf)));
92 goto out_delete_evlist; 94 goto out_delete_evlist;
93 } 95 }
94 96
@@ -103,7 +105,7 @@ retry:
103 } 105 }
104 106
105 if (!exited || !nr_exit) { 107 if (!exited || !nr_exit) {
106 poll(evlist->pollfd, evlist->nr_fds, -1); 108 perf_evlist__poll(evlist, -1);
107 goto retry; 109 goto retry;
108 } 110 }
109 111
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index ed64790a395f..00e776a87a9c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -48,6 +48,9 @@ int test__mmap_thread_lookup(void);
48int test__thread_mg_share(void); 48int test__thread_mg_share(void);
49int test__hists_output(void); 49int test__hists_output(void);
50int test__hists_cumulate(void); 50int test__hists_cumulate(void);
51int test__switch_tracking(void);
52int test__fdarray__filter(void);
53int test__fdarray__add(void);
51 54
52#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 55#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
53#ifdef HAVE_DWARF_UNWIND_SUPPORT 56#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
index 89c16b988618..e8278c558d4a 100644
--- a/tools/perf/ui/browsers/header.c
+++ b/tools/perf/ui/browsers/header.c
@@ -1,6 +1,7 @@
1#include "util/cache.h" 1#include "util/cache.h"
2#include "util/debug.h" 2#include "util/debug.h"
3#include "ui/browser.h" 3#include "ui/browser.h"
4#include "ui/keysyms.h"
4#include "ui/ui.h" 5#include "ui/ui.h"
5#include "ui/util.h" 6#include "ui/util.h"
6#include "ui/libslang.h" 7#include "ui/libslang.h"
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a94b11fc5e00..cfb976b3de3a 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -10,6 +10,7 @@
10#include "../../util/pstack.h" 10#include "../../util/pstack.h"
11#include "../../util/sort.h" 11#include "../../util/sort.h"
12#include "../../util/util.h" 12#include "../../util/util.h"
13#include "../../util/top.h"
13#include "../../arch/common.h" 14#include "../../arch/common.h"
14 15
15#include "../browser.h" 16#include "../browser.h"
@@ -34,7 +35,9 @@ struct hist_browser {
34 35
35extern void hist_browser__init_hpp(void); 36extern void hist_browser__init_hpp(void);
36 37
37static int hists__browser_title(struct hists *hists, char *bf, size_t size); 38static int hists__browser_title(struct hists *hists,
39 struct hist_browser_timer *hbt,
40 char *bf, size_t size);
38static void hist_browser__update_nr_entries(struct hist_browser *hb); 41static void hist_browser__update_nr_entries(struct hist_browser *hb);
39 42
40static struct rb_node *hists__filter_entries(struct rb_node *nd, 43static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -228,8 +231,10 @@ static void callchain_node__init_have_children(struct callchain_node *node)
228{ 231{
229 struct callchain_list *chain; 232 struct callchain_list *chain;
230 233
231 list_for_each_entry(chain, &node->val, list) 234 if (!list_empty(&node->val)) {
235 chain = list_entry(node->val.prev, struct callchain_list, list);
232 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); 236 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root);
237 }
233 238
234 callchain_node__init_have_children_rb_tree(node); 239 callchain_node__init_have_children_rb_tree(node);
235} 240}
@@ -387,7 +392,7 @@ static int hist_browser__run(struct hist_browser *browser,
387 browser->b.entries = &browser->hists->entries; 392 browser->b.entries = &browser->hists->entries;
388 browser->b.nr_entries = hist_browser__nr_entries(browser); 393 browser->b.nr_entries = hist_browser__nr_entries(browser);
389 394
390 hists__browser_title(browser->hists, title, sizeof(title)); 395 hists__browser_title(browser->hists, hbt, title, sizeof(title));
391 396
392 if (ui_browser__show(&browser->b, title, 397 if (ui_browser__show(&browser->b, title,
393 "Press '?' for help on key bindings") < 0) 398 "Press '?' for help on key bindings") < 0)
@@ -414,7 +419,8 @@ static int hist_browser__run(struct hist_browser *browser,
414 ui_browser__warn_lost_events(&browser->b); 419 ui_browser__warn_lost_events(&browser->b);
415 } 420 }
416 421
417 hists__browser_title(browser->hists, title, sizeof(title)); 422 hists__browser_title(browser->hists,
423 hbt, title, sizeof(title));
418 ui_browser__show_title(&browser->b, title); 424 ui_browser__show_title(&browser->b, title);
419 continue; 425 continue;
420 } 426 }
@@ -474,26 +480,87 @@ static char *callchain_list__sym_name(struct callchain_list *cl,
474 return bf; 480 return bf;
475} 481}
476 482
483struct callchain_print_arg {
484 /* for hists browser */
485 off_t row_offset;
486 bool is_current_entry;
487
488 /* for file dump */
489 FILE *fp;
490 int printed;
491};
492
493typedef void (*print_callchain_entry_fn)(struct hist_browser *browser,
494 struct callchain_list *chain,
495 const char *str, int offset,
496 unsigned short row,
497 struct callchain_print_arg *arg);
498
499static void hist_browser__show_callchain_entry(struct hist_browser *browser,
500 struct callchain_list *chain,
501 const char *str, int offset,
502 unsigned short row,
503 struct callchain_print_arg *arg)
504{
505 int color, width;
506 char folded_sign = callchain_list__folded(chain);
507
508 color = HE_COLORSET_NORMAL;
509 width = browser->b.width - (offset + 2);
510 if (ui_browser__is_current_entry(&browser->b, row)) {
511 browser->selection = &chain->ms;
512 color = HE_COLORSET_SELECTED;
513 arg->is_current_entry = true;
514 }
515
516 ui_browser__set_color(&browser->b, color);
517 hist_browser__gotorc(browser, row, 0);
518 slsmg_write_nstring(" ", offset);
519 slsmg_printf("%c ", folded_sign);
520 slsmg_write_nstring(str, width);
521}
522
523static void hist_browser__fprintf_callchain_entry(struct hist_browser *b __maybe_unused,
524 struct callchain_list *chain,
525 const char *str, int offset,
526 unsigned short row __maybe_unused,
527 struct callchain_print_arg *arg)
528{
529 char folded_sign = callchain_list__folded(chain);
530
531 arg->printed += fprintf(arg->fp, "%*s%c %s\n", offset, " ",
532 folded_sign, str);
533}
534
535typedef bool (*check_output_full_fn)(struct hist_browser *browser,
536 unsigned short row);
537
538static bool hist_browser__check_output_full(struct hist_browser *browser,
539 unsigned short row)
540{
541 return browser->b.rows == row;
542}
543
544static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_unused,
545 unsigned short row __maybe_unused)
546{
547 return false;
548}
549
477#define LEVEL_OFFSET_STEP 3 550#define LEVEL_OFFSET_STEP 3
478 551
479static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browser, 552static int hist_browser__show_callchain(struct hist_browser *browser,
480 struct callchain_node *chain_node, 553 struct rb_root *root, int level,
481 u64 total, int level, 554 unsigned short row, u64 total,
482 unsigned short row, 555 print_callchain_entry_fn print,
483 off_t *row_offset, 556 struct callchain_print_arg *arg,
484 bool *is_current_entry) 557 check_output_full_fn is_output_full)
485{ 558{
486 struct rb_node *node; 559 struct rb_node *node;
487 int first_row = row, width, offset = level * LEVEL_OFFSET_STEP; 560 int first_row = row, offset = level * LEVEL_OFFSET_STEP;
488 u64 new_total, remaining; 561 u64 new_total;
489 562
490 if (callchain_param.mode == CHAIN_GRAPH_REL) 563 node = rb_first(root);
491 new_total = chain_node->children_hit;
492 else
493 new_total = total;
494
495 remaining = new_total;
496 node = rb_first(&chain_node->rb_root);
497 while (node) { 564 while (node) {
498 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 565 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
499 struct rb_node *next = rb_next(node); 566 struct rb_node *next = rb_next(node);
@@ -503,30 +570,28 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
503 int first = true; 570 int first = true;
504 int extra_offset = 0; 571 int extra_offset = 0;
505 572
506 remaining -= cumul;
507
508 list_for_each_entry(chain, &child->val, list) { 573 list_for_each_entry(chain, &child->val, list) {
509 char bf[1024], *alloc_str; 574 char bf[1024], *alloc_str;
510 const char *str; 575 const char *str;
511 int color;
512 bool was_first = first; 576 bool was_first = first;
513 577
514 if (first) 578 if (first)
515 first = false; 579 first = false;
516 else 580 else if (level > 1)
517 extra_offset = LEVEL_OFFSET_STEP; 581 extra_offset = LEVEL_OFFSET_STEP;
518 582
519 folded_sign = callchain_list__folded(chain); 583 folded_sign = callchain_list__folded(chain);
520 if (*row_offset != 0) { 584 if (arg->row_offset != 0) {
521 --*row_offset; 585 arg->row_offset--;
522 goto do_next; 586 goto do_next;
523 } 587 }
524 588
525 alloc_str = NULL; 589 alloc_str = NULL;
526 str = callchain_list__sym_name(chain, bf, sizeof(bf), 590 str = callchain_list__sym_name(chain, bf, sizeof(bf),
527 browser->show_dso); 591 browser->show_dso);
528 if (was_first) { 592
529 double percent = cumul * 100.0 / new_total; 593 if (was_first && level > 1) {
594 double percent = cumul * 100.0 / total;
530 595
531 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) 596 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
532 str = "Not enough memory!"; 597 str = "Not enough memory!";
@@ -534,22 +599,11 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
534 str = alloc_str; 599 str = alloc_str;
535 } 600 }
536 601
537 color = HE_COLORSET_NORMAL; 602 print(browser, chain, str, offset + extra_offset, row, arg);
538 width = browser->b.width - (offset + extra_offset + 2);
539 if (ui_browser__is_current_entry(&browser->b, row)) {
540 browser->selection = &chain->ms;
541 color = HE_COLORSET_SELECTED;
542 *is_current_entry = true;
543 }
544 603
545 ui_browser__set_color(&browser->b, color);
546 hist_browser__gotorc(browser, row, 0);
547 slsmg_write_nstring(" ", offset + extra_offset);
548 slsmg_printf("%c ", folded_sign);
549 slsmg_write_nstring(str, width);
550 free(alloc_str); 604 free(alloc_str);
551 605
552 if (++row == browser->b.rows) 606 if (is_output_full(browser, ++row))
553 goto out; 607 goto out;
554do_next: 608do_next:
555 if (folded_sign == '+') 609 if (folded_sign == '+')
@@ -558,89 +612,21 @@ do_next:
558 612
559 if (folded_sign == '-') { 613 if (folded_sign == '-') {
560 const int new_level = level + (extra_offset ? 2 : 1); 614 const int new_level = level + (extra_offset ? 2 : 1);
561 row += hist_browser__show_callchain_node_rb_tree(browser, child, new_total,
562 new_level, row, row_offset,
563 is_current_entry);
564 }
565 if (row == browser->b.rows)
566 goto out;
567 node = next;
568 }
569out:
570 return row - first_row;
571}
572
573static int hist_browser__show_callchain_node(struct hist_browser *browser,
574 struct callchain_node *node,
575 int level, unsigned short row,
576 off_t *row_offset,
577 bool *is_current_entry)
578{
579 struct callchain_list *chain;
580 int first_row = row,
581 offset = level * LEVEL_OFFSET_STEP,
582 width = browser->b.width - offset;
583 char folded_sign = ' ';
584
585 list_for_each_entry(chain, &node->val, list) {
586 char bf[1024], *s;
587 int color;
588 615
589 folded_sign = callchain_list__folded(chain); 616 if (callchain_param.mode == CHAIN_GRAPH_REL)
590 617 new_total = child->children_hit;
591 if (*row_offset != 0) { 618 else
592 --*row_offset; 619 new_total = total;
593 continue;
594 }
595 620
596 color = HE_COLORSET_NORMAL; 621 row += hist_browser__show_callchain(browser, &child->rb_root,
597 if (ui_browser__is_current_entry(&browser->b, row)) { 622 new_level, row, new_total,
598 browser->selection = &chain->ms; 623 print, arg, is_output_full);
599 color = HE_COLORSET_SELECTED;
600 *is_current_entry = true;
601 } 624 }
602 625 if (is_output_full(browser, row))
603 s = callchain_list__sym_name(chain, bf, sizeof(bf),
604 browser->show_dso);
605 hist_browser__gotorc(browser, row, 0);
606 ui_browser__set_color(&browser->b, color);
607 slsmg_write_nstring(" ", offset);
608 slsmg_printf("%c ", folded_sign);
609 slsmg_write_nstring(s, width - 2);
610
611 if (++row == browser->b.rows)
612 goto out;
613 }
614
615 if (folded_sign == '-')
616 row += hist_browser__show_callchain_node_rb_tree(browser, node,
617 browser->hists->stats.total_period,
618 level + 1, row,
619 row_offset,
620 is_current_entry);
621out:
622 return row - first_row;
623}
624
625static int hist_browser__show_callchain(struct hist_browser *browser,
626 struct rb_root *chain,
627 int level, unsigned short row,
628 off_t *row_offset,
629 bool *is_current_entry)
630{
631 struct rb_node *nd;
632 int first_row = row;
633
634 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
635 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
636
637 row += hist_browser__show_callchain_node(browser, node, level,
638 row, row_offset,
639 is_current_entry);
640 if (row == browser->b.rows)
641 break; 626 break;
627 node = next;
642 } 628 }
643 629out:
644 return row - first_row; 630 return row - first_row;
645} 631}
646 632
@@ -653,17 +639,18 @@ struct hpp_arg {
653static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) 639static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
654{ 640{
655 struct hpp_arg *arg = hpp->ptr; 641 struct hpp_arg *arg = hpp->ptr;
656 int ret; 642 int ret, len;
657 va_list args; 643 va_list args;
658 double percent; 644 double percent;
659 645
660 va_start(args, fmt); 646 va_start(args, fmt);
647 len = va_arg(args, int);
661 percent = va_arg(args, double); 648 percent = va_arg(args, double);
662 va_end(args); 649 va_end(args);
663 650
664 ui_browser__set_percent_color(arg->b, percent, arg->current_entry); 651 ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
665 652
666 ret = scnprintf(hpp->buf, hpp->size, fmt, percent); 653 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
667 slsmg_printf("%s", hpp->buf); 654 slsmg_printf("%s", hpp->buf);
668 655
669 advance_hpp(hpp, ret); 656 advance_hpp(hpp, ret);
@@ -677,12 +664,12 @@ static u64 __hpp_get_##_field(struct hist_entry *he) \
677} \ 664} \
678 \ 665 \
679static int \ 666static int \
680hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ 667hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
681 struct perf_hpp *hpp, \ 668 struct perf_hpp *hpp, \
682 struct hist_entry *he) \ 669 struct hist_entry *he) \
683{ \ 670{ \
684 return __hpp__fmt(hpp, he, __hpp_get_##_field, " %6.2f%%", \ 671 return hpp__fmt(fmt, hpp, he, __hpp_get_##_field, " %*.2f%%", \
685 __hpp__slsmg_color_printf, true); \ 672 __hpp__slsmg_color_printf, true); \
686} 673}
687 674
688#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 675#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
@@ -692,18 +679,20 @@ static u64 __hpp_get_acc_##_field(struct hist_entry *he) \
692} \ 679} \
693 \ 680 \
694static int \ 681static int \
695hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ 682hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
696 struct perf_hpp *hpp, \ 683 struct perf_hpp *hpp, \
697 struct hist_entry *he) \ 684 struct hist_entry *he) \
698{ \ 685{ \
699 if (!symbol_conf.cumulate_callchain) { \ 686 if (!symbol_conf.cumulate_callchain) { \
700 int ret = scnprintf(hpp->buf, hpp->size, "%8s", "N/A"); \ 687 int len = fmt->user_len ?: fmt->len; \
688 int ret = scnprintf(hpp->buf, hpp->size, \
689 "%*s", len, "N/A"); \
701 slsmg_printf("%s", hpp->buf); \ 690 slsmg_printf("%s", hpp->buf); \
702 \ 691 \
703 return ret; \ 692 return ret; \
704 } \ 693 } \
705 return __hpp__fmt(hpp, he, __hpp_get_acc_##_field, " %6.2f%%", \ 694 return hpp__fmt(fmt, hpp, he, __hpp_get_acc_##_field, \
706 __hpp__slsmg_color_printf, true); \ 695 " %*.2f%%", __hpp__slsmg_color_printf, true); \
707} 696}
708 697
709__HPP_COLOR_PERCENT_FN(overhead, period) 698__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -812,10 +801,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
812 --row_offset; 801 --row_offset;
813 802
814 if (folded_sign == '-' && row != browser->b.rows) { 803 if (folded_sign == '-' && row != browser->b.rows) {
815 printed += hist_browser__show_callchain(browser, &entry->sorted_chain, 804 u64 total = hists__total_period(entry->hists);
816 1, row, &row_offset, 805 struct callchain_print_arg arg = {
817 &current_entry); 806 .row_offset = row_offset,
818 if (current_entry) 807 .is_current_entry = current_entry,
808 };
809
810 printed += hist_browser__show_callchain(browser,
811 &entry->sorted_chain, 1, row, total,
812 hist_browser__show_callchain_entry, &arg,
813 hist_browser__check_output_full);
814
815 if (arg.is_current_entry)
819 browser->he_selection = entry; 816 browser->he_selection = entry;
820 } 817 }
821 818
@@ -847,9 +844,6 @@ static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists)
847 if (perf_hpp__should_skip(fmt)) 844 if (perf_hpp__should_skip(fmt))
848 continue; 845 continue;
849 846
850 /* We need to add the length of the columns header. */
851 perf_hpp__reset_width(fmt, hists);
852
853 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 847 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
854 if (advance_hpp_check(&dummy_hpp, ret)) 848 if (advance_hpp_check(&dummy_hpp, ret))
855 break; 849 break;
@@ -1074,113 +1068,21 @@ do_offset:
1074 } 1068 }
1075} 1069}
1076 1070
1077static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
1078 struct callchain_node *chain_node,
1079 u64 total, int level,
1080 FILE *fp)
1081{
1082 struct rb_node *node;
1083 int offset = level * LEVEL_OFFSET_STEP;
1084 u64 new_total, remaining;
1085 int printed = 0;
1086
1087 if (callchain_param.mode == CHAIN_GRAPH_REL)
1088 new_total = chain_node->children_hit;
1089 else
1090 new_total = total;
1091
1092 remaining = new_total;
1093 node = rb_first(&chain_node->rb_root);
1094 while (node) {
1095 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
1096 struct rb_node *next = rb_next(node);
1097 u64 cumul = callchain_cumul_hits(child);
1098 struct callchain_list *chain;
1099 char folded_sign = ' ';
1100 int first = true;
1101 int extra_offset = 0;
1102
1103 remaining -= cumul;
1104
1105 list_for_each_entry(chain, &child->val, list) {
1106 char bf[1024], *alloc_str;
1107 const char *str;
1108 bool was_first = first;
1109
1110 if (first)
1111 first = false;
1112 else
1113 extra_offset = LEVEL_OFFSET_STEP;
1114
1115 folded_sign = callchain_list__folded(chain);
1116
1117 alloc_str = NULL;
1118 str = callchain_list__sym_name(chain, bf, sizeof(bf),
1119 browser->show_dso);
1120 if (was_first) {
1121 double percent = cumul * 100.0 / new_total;
1122
1123 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
1124 str = "Not enough memory!";
1125 else
1126 str = alloc_str;
1127 }
1128
1129 printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
1130 free(alloc_str);
1131 if (folded_sign == '+')
1132 break;
1133 }
1134
1135 if (folded_sign == '-') {
1136 const int new_level = level + (extra_offset ? 2 : 1);
1137 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
1138 new_level, fp);
1139 }
1140
1141 node = next;
1142 }
1143
1144 return printed;
1145}
1146
1147static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
1148 struct callchain_node *node,
1149 int level, FILE *fp)
1150{
1151 struct callchain_list *chain;
1152 int offset = level * LEVEL_OFFSET_STEP;
1153 char folded_sign = ' ';
1154 int printed = 0;
1155
1156 list_for_each_entry(chain, &node->val, list) {
1157 char bf[1024], *s;
1158
1159 folded_sign = callchain_list__folded(chain);
1160 s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso);
1161 printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
1162 }
1163
1164 if (folded_sign == '-')
1165 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
1166 browser->hists->stats.total_period,
1167 level + 1, fp);
1168 return printed;
1169}
1170
1171static int hist_browser__fprintf_callchain(struct hist_browser *browser, 1071static int hist_browser__fprintf_callchain(struct hist_browser *browser,
1172 struct rb_root *chain, int level, FILE *fp) 1072 struct hist_entry *he, FILE *fp)
1173{ 1073{
1174 struct rb_node *nd; 1074 u64 total = hists__total_period(he->hists);
1175 int printed = 0; 1075 struct callchain_print_arg arg = {
1176 1076 .fp = fp,
1177 for (nd = rb_first(chain); nd; nd = rb_next(nd)) { 1077 };
1178 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
1179 1078
1180 printed += hist_browser__fprintf_callchain_node(browser, node, level, fp); 1079 if (symbol_conf.cumulate_callchain)
1181 } 1080 total = he->stat_acc->period;
1182 1081
1183 return printed; 1082 hist_browser__show_callchain(browser, &he->sorted_chain, 1, 0, total,
1083 hist_browser__fprintf_callchain_entry, &arg,
1084 hist_browser__check_dump_full);
1085 return arg.printed;
1184} 1086}
1185 1087
1186static int hist_browser__fprintf_entry(struct hist_browser *browser, 1088static int hist_browser__fprintf_entry(struct hist_browser *browser,
@@ -1219,7 +1121,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1219 printed += fprintf(fp, "%s\n", rtrim(s)); 1121 printed += fprintf(fp, "%s\n", rtrim(s));
1220 1122
1221 if (folded_sign == '-') 1123 if (folded_sign == '-')
1222 printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp); 1124 printed += hist_browser__fprintf_callchain(browser, he, fp);
1223 1125
1224 return printed; 1126 return printed;
1225} 1127}
@@ -1305,7 +1207,15 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *browser
1305 return browser->he_selection->thread; 1207 return browser->he_selection->thread;
1306} 1208}
1307 1209
1308static int hists__browser_title(struct hists *hists, char *bf, size_t size) 1210/* Check whether the browser is for 'top' or 'report' */
1211static inline bool is_report_browser(void *timer)
1212{
1213 return timer == NULL;
1214}
1215
1216static int hists__browser_title(struct hists *hists,
1217 struct hist_browser_timer *hbt,
1218 char *bf, size_t size)
1309{ 1219{
1310 char unit; 1220 char unit;
1311 int printed; 1221 int printed;
@@ -1330,12 +1240,14 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size)
1330 ev_name = buf; 1240 ev_name = buf;
1331 1241
1332 for_each_group_member(pos, evsel) { 1242 for_each_group_member(pos, evsel) {
1243 struct hists *pos_hists = evsel__hists(pos);
1244
1333 if (symbol_conf.filter_relative) { 1245 if (symbol_conf.filter_relative) {
1334 nr_samples += pos->hists.stats.nr_non_filtered_samples; 1246 nr_samples += pos_hists->stats.nr_non_filtered_samples;
1335 nr_events += pos->hists.stats.total_non_filtered_period; 1247 nr_events += pos_hists->stats.total_non_filtered_period;
1336 } else { 1248 } else {
1337 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1249 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
1338 nr_events += pos->hists.stats.total_period; 1250 nr_events += pos_hists->stats.total_period;
1339 } 1251 }
1340 } 1252 }
1341 } 1253 }
@@ -1357,6 +1269,13 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size)
1357 if (dso) 1269 if (dso)
1358 printed += scnprintf(bf + printed, size - printed, 1270 printed += scnprintf(bf + printed, size - printed,
1359 ", DSO: %s", dso->short_name); 1271 ", DSO: %s", dso->short_name);
1272 if (!is_report_browser(hbt)) {
1273 struct perf_top *top = hbt->arg;
1274
1275 if (top->zero)
1276 printed += scnprintf(bf + printed, size - printed, " [z]");
1277 }
1278
1360 return printed; 1279 return printed;
1361} 1280}
1362 1281
@@ -1368,12 +1287,6 @@ static inline void free_popup_options(char **options, int n)
1368 zfree(&options[i]); 1287 zfree(&options[i]);
1369} 1288}
1370 1289
1371/* Check whether the browser is for 'top' or 'report' */
1372static inline bool is_report_browser(void *timer)
1373{
1374 return timer == NULL;
1375}
1376
1377/* 1290/*
1378 * Only runtime switching of perf data file will make "input_name" point 1291 * Only runtime switching of perf data file will make "input_name" point
1379 * to a malloced buffer. So add "is_input_name_malloced" flag to decide 1292 * to a malloced buffer. So add "is_input_name_malloced" flag to decide
@@ -1488,7 +1401,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1488 float min_pcnt, 1401 float min_pcnt,
1489 struct perf_session_env *env) 1402 struct perf_session_env *env)
1490{ 1403{
1491 struct hists *hists = &evsel->hists; 1404 struct hists *hists = evsel__hists(evsel);
1492 struct hist_browser *browser = hist_browser__new(hists); 1405 struct hist_browser *browser = hist_browser__new(hists);
1493 struct branch_info *bi; 1406 struct branch_info *bi;
1494 struct pstack *fstack; 1407 struct pstack *fstack;
@@ -1498,6 +1411,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1498 char buf[64]; 1411 char buf[64];
1499 char script_opt[64]; 1412 char script_opt[64];
1500 int delay_secs = hbt ? hbt->refresh : 0; 1413 int delay_secs = hbt ? hbt->refresh : 0;
1414 struct perf_hpp_fmt *fmt;
1501 1415
1502#define HIST_BROWSER_HELP_COMMON \ 1416#define HIST_BROWSER_HELP_COMMON \
1503 "h/?/F1 Show this window\n" \ 1417 "h/?/F1 Show this window\n" \
@@ -1529,6 +1443,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1529 "P Print histograms to perf.hist.N\n" 1443 "P Print histograms to perf.hist.N\n"
1530 "t Zoom into current Thread\n" 1444 "t Zoom into current Thread\n"
1531 "V Verbose (DSO names in callchains, etc)\n" 1445 "V Verbose (DSO names in callchains, etc)\n"
1446 "z Toggle zeroing of samples\n"
1532 "/ Filter symbol by name"; 1447 "/ Filter symbol by name";
1533 1448
1534 if (browser == NULL) 1449 if (browser == NULL)
@@ -1547,6 +1462,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1547 1462
1548 memset(options, 0, sizeof(options)); 1463 memset(options, 0, sizeof(options));
1549 1464
1465 perf_hpp__for_each_format(fmt)
1466 perf_hpp__reset_width(fmt, hists);
1467
1468 if (symbol_conf.col_width_list_str)
1469 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
1470
1550 while (1) { 1471 while (1) {
1551 const struct thread *thread = NULL; 1472 const struct thread *thread = NULL;
1552 const struct dso *dso = NULL; 1473 const struct dso *dso = NULL;
@@ -1623,6 +1544,13 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1623 case 'F': 1544 case 'F':
1624 symbol_conf.filter_relative ^= 1; 1545 symbol_conf.filter_relative ^= 1;
1625 continue; 1546 continue;
1547 case 'z':
1548 if (!is_report_browser(hbt)) {
1549 struct perf_top *top = hbt->arg;
1550
1551 top->zero = !top->zero;
1552 }
1553 continue;
1626 case K_F1: 1554 case K_F1:
1627 case 'h': 1555 case 'h':
1628 case '?': 1556 case '?':
@@ -1888,8 +1816,9 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1888 struct perf_evsel_menu *menu = container_of(browser, 1816 struct perf_evsel_menu *menu = container_of(browser,
1889 struct perf_evsel_menu, b); 1817 struct perf_evsel_menu, b);
1890 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); 1818 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
1819 struct hists *hists = evsel__hists(evsel);
1891 bool current_entry = ui_browser__is_current_entry(browser, row); 1820 bool current_entry = ui_browser__is_current_entry(browser, row);
1892 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1821 unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE];
1893 const char *ev_name = perf_evsel__name(evsel); 1822 const char *ev_name = perf_evsel__name(evsel);
1894 char bf[256], unit; 1823 char bf[256], unit;
1895 const char *warn = " "; 1824 const char *warn = " ";
@@ -1904,7 +1833,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1904 ev_name = perf_evsel__group_name(evsel); 1833 ev_name = perf_evsel__group_name(evsel);
1905 1834
1906 for_each_group_member(pos, evsel) { 1835 for_each_group_member(pos, evsel) {
1907 nr_events += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1836 struct hists *pos_hists = evsel__hists(pos);
1837 nr_events += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
1908 } 1838 }
1909 } 1839 }
1910 1840
@@ -1913,7 +1843,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1913 unit, unit == ' ' ? "" : " ", ev_name); 1843 unit, unit == ' ' ? "" : " ", ev_name);
1914 slsmg_printf("%s", bf); 1844 slsmg_printf("%s", bf);
1915 1845
1916 nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 1846 nr_events = hists->stats.nr_events[PERF_RECORD_LOST];
1917 if (nr_events != 0) { 1847 if (nr_events != 0) {
1918 menu->lost_events = true; 1848 menu->lost_events = true;
1919 if (!current_entry) 1849 if (!current_entry)
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 6ca60e482cdc..fc654fb77ace 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -11,6 +11,7 @@
11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...) 11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
12{ 12{
13 int ret = 0; 13 int ret = 0;
14 int len;
14 va_list args; 15 va_list args;
15 double percent; 16 double percent;
16 const char *markup; 17 const char *markup;
@@ -18,6 +19,7 @@ static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
18 size_t size = hpp->size; 19 size_t size = hpp->size;
19 20
20 va_start(args, fmt); 21 va_start(args, fmt);
22 len = va_arg(args, int);
21 percent = va_arg(args, double); 23 percent = va_arg(args, double);
22 va_end(args); 24 va_end(args);
23 25
@@ -25,7 +27,7 @@ static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
25 if (markup) 27 if (markup)
26 ret += scnprintf(buf, size, markup); 28 ret += scnprintf(buf, size, markup);
27 29
28 ret += scnprintf(buf + ret, size - ret, fmt, percent); 30 ret += scnprintf(buf + ret, size - ret, fmt, len, percent);
29 31
30 if (markup) 32 if (markup)
31 ret += scnprintf(buf + ret, size - ret, "</span>"); 33 ret += scnprintf(buf + ret, size - ret, "</span>");
@@ -39,12 +41,12 @@ static u64 he_get_##_field(struct hist_entry *he) \
39 return he->stat._field; \ 41 return he->stat._field; \
40} \ 42} \
41 \ 43 \
42static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 44static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
43 struct perf_hpp *hpp, \ 45 struct perf_hpp *hpp, \
44 struct hist_entry *he) \ 46 struct hist_entry *he) \
45{ \ 47{ \
46 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 48 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
47 __percent_color_snprintf, true); \ 49 __percent_color_snprintf, true); \
48} 50}
49 51
50#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 52#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
@@ -57,8 +59,8 @@ static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,
57 struct perf_hpp *hpp, \ 59 struct perf_hpp *hpp, \
58 struct hist_entry *he) \ 60 struct hist_entry *he) \
59{ \ 61{ \
60 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \ 62 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
61 __percent_color_snprintf, true); \ 63 __percent_color_snprintf, true); \
62} 64}
63 65
64__HPP_COLOR_PERCENT_FN(overhead, period) 66__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -205,10 +207,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
205 if (perf_hpp__is_sort_entry(fmt)) 207 if (perf_hpp__is_sort_entry(fmt))
206 sym_col = col_idx; 208 sym_col = col_idx;
207 209
208 fmt->header(fmt, &hpp, hists_to_evsel(hists));
209
210 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), 210 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
211 -1, ltrim(s), 211 -1, fmt->name,
212 renderer, "markup", 212 renderer, "markup",
213 col_idx++, NULL); 213 col_idx++, NULL);
214 } 214 }
@@ -319,7 +319,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
319 gtk_container_add(GTK_CONTAINER(window), vbox); 319 gtk_container_add(GTK_CONTAINER(window), vbox);
320 320
321 evlist__for_each(evlist, pos) { 321 evlist__for_each(evlist, pos) {
322 struct hists *hists = &pos->hists; 322 struct hists *hists = evsel__hists(pos);
323 const char *evname = perf_evsel__name(pos); 323 const char *evname = perf_evsel__name(pos);
324 GtkWidget *scrolled_window; 324 GtkWidget *scrolled_window;
325 GtkWidget *tab_label; 325 GtkWidget *tab_label;
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 498adb23c02e..2af18376b077 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -15,9 +15,9 @@
15 __ret; \ 15 __ret; \
16}) 16})
17 17
18int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 18static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
19 hpp_field_fn get_field, const char *fmt, 19 hpp_field_fn get_field, const char *fmt, int len,
20 hpp_snprint_fn print_fn, bool fmt_percent) 20 hpp_snprint_fn print_fn, bool fmt_percent)
21{ 21{
22 int ret; 22 int ret;
23 struct hists *hists = he->hists; 23 struct hists *hists = he->hists;
@@ -32,9 +32,9 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
32 if (total) 32 if (total)
33 percent = 100.0 * get_field(he) / total; 33 percent = 100.0 * get_field(he) / total;
34 34
35 ret = hpp__call_print_fn(hpp, print_fn, fmt, percent); 35 ret = hpp__call_print_fn(hpp, print_fn, fmt, len, percent);
36 } else 36 } else
37 ret = hpp__call_print_fn(hpp, print_fn, fmt, get_field(he)); 37 ret = hpp__call_print_fn(hpp, print_fn, fmt, len, get_field(he));
38 38
39 if (perf_evsel__is_group_event(evsel)) { 39 if (perf_evsel__is_group_event(evsel)) {
40 int prev_idx, idx_delta; 40 int prev_idx, idx_delta;
@@ -60,19 +60,19 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
60 */ 60 */
61 if (fmt_percent) { 61 if (fmt_percent) {
62 ret += hpp__call_print_fn(hpp, print_fn, 62 ret += hpp__call_print_fn(hpp, print_fn,
63 fmt, 0.0); 63 fmt, len, 0.0);
64 } else { 64 } else {
65 ret += hpp__call_print_fn(hpp, print_fn, 65 ret += hpp__call_print_fn(hpp, print_fn,
66 fmt, 0ULL); 66 fmt, len, 0ULL);
67 } 67 }
68 } 68 }
69 69
70 if (fmt_percent) { 70 if (fmt_percent) {
71 ret += hpp__call_print_fn(hpp, print_fn, fmt, 71 ret += hpp__call_print_fn(hpp, print_fn, fmt, len,
72 100.0 * period / total); 72 100.0 * period / total);
73 } else { 73 } else {
74 ret += hpp__call_print_fn(hpp, print_fn, fmt, 74 ret += hpp__call_print_fn(hpp, print_fn, fmt,
75 period); 75 len, period);
76 } 76 }
77 77
78 prev_idx = perf_evsel__group_idx(evsel); 78 prev_idx = perf_evsel__group_idx(evsel);
@@ -86,10 +86,10 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
86 */ 86 */
87 if (fmt_percent) { 87 if (fmt_percent) {
88 ret += hpp__call_print_fn(hpp, print_fn, 88 ret += hpp__call_print_fn(hpp, print_fn,
89 fmt, 0.0); 89 fmt, len, 0.0);
90 } else { 90 } else {
91 ret += hpp__call_print_fn(hpp, print_fn, 91 ret += hpp__call_print_fn(hpp, print_fn,
92 fmt, 0ULL); 92 fmt, len, 0ULL);
93 } 93 }
94 } 94 }
95 } 95 }
@@ -104,16 +104,35 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
104 return ret; 104 return ret;
105} 105}
106 106
107int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 107int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
108 hpp_field_fn get_field, const char *fmt, 108 struct hist_entry *he, hpp_field_fn get_field,
109 hpp_snprint_fn print_fn, bool fmt_percent) 109 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
110{
111 int len = fmt->user_len ?: fmt->len;
112
113 if (symbol_conf.field_sep) {
114 return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
115 print_fn, fmt_percent);
116 }
117
118 if (fmt_percent)
119 len -= 2; /* 2 for a space and a % sign */
120 else
121 len -= 1;
122
123 return __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent);
124}
125
126int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
127 struct hist_entry *he, hpp_field_fn get_field,
128 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
110{ 129{
111 if (!symbol_conf.cumulate_callchain) { 130 if (!symbol_conf.cumulate_callchain) {
112 return snprintf(hpp->buf, hpp->size, "%*s", 131 int len = fmt->user_len ?: fmt->len;
113 fmt_percent ? 8 : 12, "N/A"); 132 return snprintf(hpp->buf, hpp->size, " %*s", len - 1, "N/A");
114 } 133 }
115 134
116 return __hpp__fmt(hpp, he, get_field, fmt, print_fn, fmt_percent); 135 return hpp__fmt(fmt, hpp, he, get_field, fmtstr, print_fn, fmt_percent);
117} 136}
118 137
119static int field_cmp(u64 field_a, u64 field_b) 138static int field_cmp(u64 field_a, u64 field_b)
@@ -190,30 +209,26 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
190 return ret; 209 return ret;
191} 210}
192 211
193#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 212static int hpp__width_fn(struct perf_hpp_fmt *fmt,
194static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 213 struct perf_hpp *hpp __maybe_unused,
195 struct perf_hpp *hpp, \ 214 struct perf_evsel *evsel)
196 struct perf_evsel *evsel) \ 215{
197{ \ 216 int len = fmt->user_len ?: fmt->len;
198 int len = _min_width; \ 217
199 \ 218 if (symbol_conf.event_group)
200 if (symbol_conf.event_group) \ 219 len = max(len, evsel->nr_members * fmt->len);
201 len = max(len, evsel->nr_members * _unit_width); \ 220
202 \ 221 if (len < (int)strlen(fmt->name))
203 return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \ 222 len = strlen(fmt->name);
204} 223
205 224 return len;
206#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ 225}
207static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 226
208 struct perf_hpp *hpp __maybe_unused, \ 227static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
209 struct perf_evsel *evsel) \ 228 struct perf_evsel *evsel)
210{ \ 229{
211 int len = _min_width; \ 230 int len = hpp__width_fn(fmt, hpp, evsel);
212 \ 231 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
213 if (symbol_conf.event_group) \
214 len = max(len, evsel->nr_members * _unit_width); \
215 \
216 return len; \
217} 232}
218 233
219static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) 234static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
@@ -221,11 +236,12 @@ static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
221 va_list args; 236 va_list args;
222 ssize_t ssize = hpp->size; 237 ssize_t ssize = hpp->size;
223 double percent; 238 double percent;
224 int ret; 239 int ret, len;
225 240
226 va_start(args, fmt); 241 va_start(args, fmt);
242 len = va_arg(args, int);
227 percent = va_arg(args, double); 243 percent = va_arg(args, double);
228 ret = value_color_snprintf(hpp->buf, hpp->size, fmt, percent); 244 ret = percent_color_len_snprintf(hpp->buf, hpp->size, fmt, len, percent);
229 va_end(args); 245 va_end(args);
230 246
231 return (ret >= ssize) ? (ssize - 1) : ret; 247 return (ret >= ssize) ? (ssize - 1) : ret;
@@ -250,20 +266,19 @@ static u64 he_get_##_field(struct hist_entry *he) \
250 return he->stat._field; \ 266 return he->stat._field; \
251} \ 267} \
252 \ 268 \
253static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 269static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
254 struct perf_hpp *hpp, struct hist_entry *he) \ 270 struct perf_hpp *hpp, struct hist_entry *he) \
255{ \ 271{ \
256 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 272 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
257 hpp_color_scnprintf, true); \ 273 hpp_color_scnprintf, true); \
258} 274}
259 275
260#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 276#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
261static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 277static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
262 struct perf_hpp *hpp, struct hist_entry *he) \ 278 struct perf_hpp *hpp, struct hist_entry *he) \
263{ \ 279{ \
264 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 280 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
265 return __hpp__fmt(hpp, he, he_get_##_field, fmt, \ 281 hpp_entry_scnprintf, true); \
266 hpp_entry_scnprintf, true); \
267} 282}
268 283
269#define __HPP_SORT_FN(_type, _field) \ 284#define __HPP_SORT_FN(_type, _field) \
@@ -278,20 +293,19 @@ static u64 he_get_acc_##_field(struct hist_entry *he) \
278 return he->stat_acc->_field; \ 293 return he->stat_acc->_field; \
279} \ 294} \
280 \ 295 \
281static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 296static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
282 struct perf_hpp *hpp, struct hist_entry *he) \ 297 struct perf_hpp *hpp, struct hist_entry *he) \
283{ \ 298{ \
284 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \ 299 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
285 hpp_color_scnprintf, true); \ 300 hpp_color_scnprintf, true); \
286} 301}
287 302
288#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 303#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
289static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 304static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
290 struct perf_hpp *hpp, struct hist_entry *he) \ 305 struct perf_hpp *hpp, struct hist_entry *he) \
291{ \ 306{ \
292 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 307 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
293 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, fmt, \ 308 hpp_entry_scnprintf, true); \
294 hpp_entry_scnprintf, true); \
295} 309}
296 310
297#define __HPP_SORT_ACC_FN(_type, _field) \ 311#define __HPP_SORT_ACC_FN(_type, _field) \
@@ -306,12 +320,11 @@ static u64 he_get_raw_##_field(struct hist_entry *he) \
306 return he->stat._field; \ 320 return he->stat._field; \
307} \ 321} \
308 \ 322 \
309static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 323static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
310 struct perf_hpp *hpp, struct hist_entry *he) \ 324 struct perf_hpp *hpp, struct hist_entry *he) \
311{ \ 325{ \
312 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ 326 return hpp__fmt(fmt, hpp, he, he_get_raw_##_field, " %*"PRIu64, \
313 return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, \ 327 hpp_entry_scnprintf, false); \
314 hpp_entry_scnprintf, false); \
315} 328}
316 329
317#define __HPP_SORT_RAW_FN(_type, _field) \ 330#define __HPP_SORT_RAW_FN(_type, _field) \
@@ -321,37 +334,29 @@ static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \
321} 334}
322 335
323 336
324#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \ 337#define HPP_PERCENT_FNS(_type, _field) \
325__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
326__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
327__HPP_COLOR_PERCENT_FN(_type, _field) \ 338__HPP_COLOR_PERCENT_FN(_type, _field) \
328__HPP_ENTRY_PERCENT_FN(_type, _field) \ 339__HPP_ENTRY_PERCENT_FN(_type, _field) \
329__HPP_SORT_FN(_type, _field) 340__HPP_SORT_FN(_type, _field)
330 341
331#define HPP_PERCENT_ACC_FNS(_type, _str, _field, _min_width, _unit_width)\ 342#define HPP_PERCENT_ACC_FNS(_type, _field) \
332__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
333__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
334__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 343__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
335__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 344__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
336__HPP_SORT_ACC_FN(_type, _field) 345__HPP_SORT_ACC_FN(_type, _field)
337 346
338#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width) \ 347#define HPP_RAW_FNS(_type, _field) \
339__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
340__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
341__HPP_ENTRY_RAW_FN(_type, _field) \ 348__HPP_ENTRY_RAW_FN(_type, _field) \
342__HPP_SORT_RAW_FN(_type, _field) 349__HPP_SORT_RAW_FN(_type, _field)
343 350
344__HPP_HEADER_FN(overhead_self, "Self", 8, 8) 351HPP_PERCENT_FNS(overhead, period)
345 352HPP_PERCENT_FNS(overhead_sys, period_sys)
346HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8) 353HPP_PERCENT_FNS(overhead_us, period_us)
347HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8) 354HPP_PERCENT_FNS(overhead_guest_sys, period_guest_sys)
348HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8) 355HPP_PERCENT_FNS(overhead_guest_us, period_guest_us)
349HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8) 356HPP_PERCENT_ACC_FNS(overhead_acc, period)
350HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
351HPP_PERCENT_ACC_FNS(overhead_acc, "Children", period, 8, 8)
352 357
353HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) 358HPP_RAW_FNS(samples, nr_events)
354HPP_RAW_FNS(period, "Period", period, 12, 12) 359HPP_RAW_FNS(period, period)
355 360
356static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused, 361static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
357 struct hist_entry *b __maybe_unused) 362 struct hist_entry *b __maybe_unused)
@@ -359,47 +364,50 @@ static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
359 return 0; 364 return 0;
360} 365}
361 366
362#define HPP__COLOR_PRINT_FNS(_name) \ 367#define HPP__COLOR_PRINT_FNS(_name, _fn) \
363 { \ 368 { \
364 .header = hpp__header_ ## _name, \ 369 .name = _name, \
365 .width = hpp__width_ ## _name, \ 370 .header = hpp__header_fn, \
366 .color = hpp__color_ ## _name, \ 371 .width = hpp__width_fn, \
367 .entry = hpp__entry_ ## _name, \ 372 .color = hpp__color_ ## _fn, \
373 .entry = hpp__entry_ ## _fn, \
368 .cmp = hpp__nop_cmp, \ 374 .cmp = hpp__nop_cmp, \
369 .collapse = hpp__nop_cmp, \ 375 .collapse = hpp__nop_cmp, \
370 .sort = hpp__sort_ ## _name, \ 376 .sort = hpp__sort_ ## _fn, \
371 } 377 }
372 378
373#define HPP__COLOR_ACC_PRINT_FNS(_name) \ 379#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn) \
374 { \ 380 { \
375 .header = hpp__header_ ## _name, \ 381 .name = _name, \
376 .width = hpp__width_ ## _name, \ 382 .header = hpp__header_fn, \
377 .color = hpp__color_ ## _name, \ 383 .width = hpp__width_fn, \
378 .entry = hpp__entry_ ## _name, \ 384 .color = hpp__color_ ## _fn, \
385 .entry = hpp__entry_ ## _fn, \
379 .cmp = hpp__nop_cmp, \ 386 .cmp = hpp__nop_cmp, \
380 .collapse = hpp__nop_cmp, \ 387 .collapse = hpp__nop_cmp, \
381 .sort = hpp__sort_ ## _name, \ 388 .sort = hpp__sort_ ## _fn, \
382 } 389 }
383 390
384#define HPP__PRINT_FNS(_name) \ 391#define HPP__PRINT_FNS(_name, _fn) \
385 { \ 392 { \
386 .header = hpp__header_ ## _name, \ 393 .name = _name, \
387 .width = hpp__width_ ## _name, \ 394 .header = hpp__header_fn, \
388 .entry = hpp__entry_ ## _name, \ 395 .width = hpp__width_fn, \
396 .entry = hpp__entry_ ## _fn, \
389 .cmp = hpp__nop_cmp, \ 397 .cmp = hpp__nop_cmp, \
390 .collapse = hpp__nop_cmp, \ 398 .collapse = hpp__nop_cmp, \
391 .sort = hpp__sort_ ## _name, \ 399 .sort = hpp__sort_ ## _fn, \
392 } 400 }
393 401
394struct perf_hpp_fmt perf_hpp__format[] = { 402struct perf_hpp_fmt perf_hpp__format[] = {
395 HPP__COLOR_PRINT_FNS(overhead), 403 HPP__COLOR_PRINT_FNS("Overhead", overhead),
396 HPP__COLOR_PRINT_FNS(overhead_sys), 404 HPP__COLOR_PRINT_FNS("sys", overhead_sys),
397 HPP__COLOR_PRINT_FNS(overhead_us), 405 HPP__COLOR_PRINT_FNS("usr", overhead_us),
398 HPP__COLOR_PRINT_FNS(overhead_guest_sys), 406 HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys),
399 HPP__COLOR_PRINT_FNS(overhead_guest_us), 407 HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us),
400 HPP__COLOR_ACC_PRINT_FNS(overhead_acc), 408 HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc),
401 HPP__PRINT_FNS(samples), 409 HPP__PRINT_FNS("Samples", samples),
402 HPP__PRINT_FNS(period) 410 HPP__PRINT_FNS("Period", period)
403}; 411};
404 412
405LIST_HEAD(perf_hpp__list); 413LIST_HEAD(perf_hpp__list);
@@ -444,14 +452,12 @@ void perf_hpp__init(void)
444 /* 452 /*
445 * If user specified field order, no need to setup default fields. 453 * If user specified field order, no need to setup default fields.
446 */ 454 */
447 if (field_order) 455 if (is_strict_order(field_order))
448 return; 456 return;
449 457
450 if (symbol_conf.cumulate_callchain) { 458 if (symbol_conf.cumulate_callchain) {
451 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC); 459 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC);
452 460 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self";
453 perf_hpp__format[PERF_HPP__OVERHEAD].header =
454 hpp__header_overhead_self;
455 } 461 }
456 462
457 perf_hpp__column_enable(PERF_HPP__OVERHEAD); 463 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
@@ -513,11 +519,11 @@ void perf_hpp__column_disable(unsigned col)
513 519
514void perf_hpp__cancel_cumulate(void) 520void perf_hpp__cancel_cumulate(void)
515{ 521{
516 if (field_order) 522 if (is_strict_order(field_order))
517 return; 523 return;
518 524
519 perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC); 525 perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC);
520 perf_hpp__format[PERF_HPP__OVERHEAD].header = hpp__header_overhead; 526 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead";
521} 527}
522 528
523void perf_hpp__setup_output_field(void) 529void perf_hpp__setup_output_field(void)
@@ -622,3 +628,59 @@ unsigned int hists__sort_list_width(struct hists *hists)
622 628
623 return ret; 629 return ret;
624} 630}
631
632void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
633{
634 int idx;
635
636 if (perf_hpp__is_sort_entry(fmt))
637 return perf_hpp__reset_sort_width(fmt, hists);
638
639 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
640 if (fmt == &perf_hpp__format[idx])
641 break;
642 }
643
644 if (idx == PERF_HPP__MAX_INDEX)
645 return;
646
647 switch (idx) {
648 case PERF_HPP__OVERHEAD:
649 case PERF_HPP__OVERHEAD_SYS:
650 case PERF_HPP__OVERHEAD_US:
651 case PERF_HPP__OVERHEAD_ACC:
652 fmt->len = 8;
653 break;
654
655 case PERF_HPP__OVERHEAD_GUEST_SYS:
656 case PERF_HPP__OVERHEAD_GUEST_US:
657 fmt->len = 9;
658 break;
659
660 case PERF_HPP__SAMPLES:
661 case PERF_HPP__PERIOD:
662 fmt->len = 12;
663 break;
664
665 default:
666 break;
667 }
668}
669
670void perf_hpp__set_user_width(const char *width_list_str)
671{
672 struct perf_hpp_fmt *fmt;
673 const char *ptr = width_list_str;
674
675 perf_hpp__for_each_format(fmt) {
676 char *p;
677
678 int len = strtol(ptr, &p, 10);
679 fmt->user_len = len;
680
681 if (*p == ',')
682 ptr = p + 1;
683 else
684 break;
685 }
686}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 40af0acb4fe9..15b451acbde6 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -395,10 +395,12 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
395 395
396 init_rem_hits(); 396 init_rem_hits();
397 397
398
399 perf_hpp__for_each_format(fmt) 398 perf_hpp__for_each_format(fmt)
400 perf_hpp__reset_width(fmt, hists); 399 perf_hpp__reset_width(fmt, hists);
401 400
401 if (symbol_conf.col_width_list_str)
402 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
403
402 if (!show_header) 404 if (!show_header)
403 goto print_entries; 405 goto print_entries;
404 406
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 809b4c50beae..7dabde14ea54 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -232,9 +232,16 @@ static int mov__parse(struct ins_operands *ops)
232 return -1; 232 return -1;
233 233
234 target = ++s; 234 target = ++s;
235 comment = strchr(s, '#');
235 236
236 while (s[0] != '\0' && !isspace(s[0])) 237 if (comment != NULL)
237 ++s; 238 s = comment - 1;
239 else
240 s = strchr(s, '\0') - 1;
241
242 while (s > target && isspace(s[0]))
243 --s;
244 s++;
238 prev = *s; 245 prev = *s;
239 *s = '\0'; 246 *s = '\0';
240 247
@@ -244,7 +251,6 @@ static int mov__parse(struct ins_operands *ops)
244 if (ops->target.raw == NULL) 251 if (ops->target.raw == NULL)
245 goto out_free_source; 252 goto out_free_source;
246 253
247 comment = strchr(s, '#');
248 if (comment == NULL) 254 if (comment == NULL)
249 return 0; 255 return 0;
250 256
@@ -472,7 +478,7 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
472 478
473 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 479 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
474 480
475 if (addr < sym->start || addr > sym->end) 481 if (addr < sym->start || addr >= sym->end)
476 return -ERANGE; 482 return -ERANGE;
477 483
478 offset = addr - sym->start; 484 offset = addr - sym->start;
@@ -830,7 +836,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
830 end = map__rip_2objdump(map, sym->end); 836 end = map__rip_2objdump(map, sym->end);
831 837
832 offset = line_ip - start; 838 offset = line_ip - start;
833 if ((u64)line_ip < start || (u64)line_ip > end) 839 if ((u64)line_ip < start || (u64)line_ip >= end)
834 offset = -1; 840 offset = -1;
835 else 841 else
836 parsed_line = tmp2 + 1; 842 parsed_line = tmp2 + 1;
@@ -899,10 +905,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
899 struct kcore_extract kce; 905 struct kcore_extract kce;
900 bool delete_extract = false; 906 bool delete_extract = false;
901 907
902 if (filename) { 908 if (filename)
903 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 909 symbol__join_symfs(symfs_filename, filename);
904 symbol_conf.symfs, filename);
905 }
906 910
907 if (filename == NULL) { 911 if (filename == NULL) {
908 if (dso->has_build_id) { 912 if (dso->has_build_id) {
@@ -922,8 +926,7 @@ fallback:
922 * DSO is the same as when 'perf record' ran. 926 * DSO is the same as when 'perf record' ran.
923 */ 927 */
924 filename = (char *)dso->long_name; 928 filename = (char *)dso->long_name;
925 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 929 symbol__join_symfs(symfs_filename, filename);
926 symbol_conf.symfs, filename);
927 free_filename = false; 930 free_filename = false;
928 } 931 }
929 932
@@ -963,7 +966,7 @@ fallback:
963 kce.kcore_filename = symfs_filename; 966 kce.kcore_filename = symfs_filename;
964 kce.addr = map__rip_2objdump(map, sym->start); 967 kce.addr = map__rip_2objdump(map, sym->start);
965 kce.offs = sym->start; 968 kce.offs = sym->start;
966 kce.len = sym->end + 1 - sym->start; 969 kce.len = sym->end - sym->start;
967 if (!kcore_extract__create(&kce)) { 970 if (!kcore_extract__create(&kce)) {
968 delete_extract = true; 971 delete_extract = true;
969 strlcpy(symfs_filename, kce.extract_filename, 972 strlcpy(symfs_filename, kce.extract_filename,
@@ -984,7 +987,7 @@ fallback:
984 disassembler_style ? "-M " : "", 987 disassembler_style ? "-M " : "",
985 disassembler_style ? disassembler_style : "", 988 disassembler_style ? disassembler_style : "",
986 map__rip_2objdump(map, sym->start), 989 map__rip_2objdump(map, sym->start),
987 map__rip_2objdump(map, sym->end+1), 990 map__rip_2objdump(map, sym->end),
988 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 991 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
989 symbol_conf.annotate_src ? "-S" : "", 992 symbol_conf.annotate_src ? "-S" : "",
990 symfs_filename, filename); 993 symfs_filename, filename);
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 7b176dd02e1a..5cf9e1b5989d 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -22,6 +22,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 22extern int perf_default_config(const char *, const char *, void *);
23extern int perf_config(config_fn_t fn, void *); 23extern int perf_config(config_fn_t fn, void *);
24extern int perf_config_int(const char *, const char *); 24extern int perf_config_int(const char *, const char *);
25extern u64 perf_config_u64(const char *, const char *);
25extern int perf_config_bool(const char *, const char *); 26extern int perf_config_bool(const char *, const char *);
26extern int config_error_nonbool(const char *); 27extern int config_error_nonbool(const char *);
27extern const char *perf_config_dirname(const char *, const char *); 28extern const char *perf_config_dirname(const char *, const char *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 437ee09727e6..c84d3f8dcb75 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -25,77 +25,172 @@
25 25
26__thread struct callchain_cursor callchain_cursor; 26__thread struct callchain_cursor callchain_cursor;
27 27
28int 28#ifdef HAVE_DWARF_UNWIND_SUPPORT
29parse_callchain_report_opt(const char *arg) 29static int get_stack_size(const char *str, unsigned long *_size)
30{ 30{
31 char *tok, *tok2;
32 char *endptr; 31 char *endptr;
32 unsigned long size;
33 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
33 34
34 symbol_conf.use_callchain = true; 35 size = strtoul(str, &endptr, 0);
35 36
36 if (!arg) 37 do {
38 if (*endptr)
39 break;
40
41 size = round_up(size, sizeof(u64));
42 if (!size || size > max_size)
43 break;
44
45 *_size = size;
37 return 0; 46 return 0;
38 47
39 tok = strtok((char *)arg, ","); 48 } while (0);
40 if (!tok)
41 return -1;
42 49
43 /* get the output mode */ 50 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
44 if (!strncmp(tok, "graph", strlen(arg))) { 51 max_size, str);
45 callchain_param.mode = CHAIN_GRAPH_ABS; 52 return -1;
53}
54#endif /* HAVE_DWARF_UNWIND_SUPPORT */
46 55
47 } else if (!strncmp(tok, "flat", strlen(arg))) { 56int parse_callchain_record_opt(const char *arg)
48 callchain_param.mode = CHAIN_FLAT; 57{
49 } else if (!strncmp(tok, "fractal", strlen(arg))) { 58 char *tok, *name, *saveptr = NULL;
50 callchain_param.mode = CHAIN_GRAPH_REL; 59 char *buf;
51 } else if (!strncmp(tok, "none", strlen(arg))) { 60 int ret = -1;
52 callchain_param.mode = CHAIN_NONE; 61
53 symbol_conf.use_callchain = false; 62 /* We need buffer that we know we can write to. */
54 return 0; 63 buf = malloc(strlen(arg) + 1);
55 } else { 64 if (!buf)
56 return -1; 65 return -ENOMEM;
57 } 66
67 strcpy(buf, arg);
68
69 tok = strtok_r((char *)buf, ",", &saveptr);
70 name = tok ? : (char *)buf;
71
72 do {
73 /* Framepointer style */
74 if (!strncmp(name, "fp", sizeof("fp"))) {
75 if (!strtok_r(NULL, ",", &saveptr)) {
76 callchain_param.record_mode = CALLCHAIN_FP;
77 ret = 0;
78 } else
79 pr_err("callchain: No more arguments "
80 "needed for -g fp\n");
81 break;
58 82
59 /* get the min percentage */ 83#ifdef HAVE_DWARF_UNWIND_SUPPORT
60 tok = strtok(NULL, ","); 84 /* Dwarf style */
61 if (!tok) 85 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
62 goto setup; 86 const unsigned long default_stack_dump_size = 8192;
63 87
64 callchain_param.min_percent = strtod(tok, &endptr); 88 ret = 0;
65 if (tok == endptr) 89 callchain_param.record_mode = CALLCHAIN_DWARF;
66 return -1; 90 callchain_param.dump_size = default_stack_dump_size;
67 91
68 /* get the print limit */ 92 tok = strtok_r(NULL, ",", &saveptr);
69 tok2 = strtok(NULL, ","); 93 if (tok) {
70 if (!tok2) 94 unsigned long size = 0;
71 goto setup;
72 95
73 if (tok2[0] != 'c') { 96 ret = get_stack_size(tok, &size);
74 callchain_param.print_limit = strtoul(tok2, &endptr, 0); 97 callchain_param.dump_size = size;
75 tok2 = strtok(NULL, ","); 98 }
76 if (!tok2) 99#endif /* HAVE_DWARF_UNWIND_SUPPORT */
77 goto setup; 100 } else {
101 pr_err("callchain: Unknown --call-graph option "
102 "value: %s\n", arg);
103 break;
104 }
105
106 } while (0);
107
108 free(buf);
109 return ret;
110}
111
112static int parse_callchain_mode(const char *value)
113{
114 if (!strncmp(value, "graph", strlen(value))) {
115 callchain_param.mode = CHAIN_GRAPH_ABS;
116 return 0;
117 }
118 if (!strncmp(value, "flat", strlen(value))) {
119 callchain_param.mode = CHAIN_FLAT;
120 return 0;
78 } 121 }
122 if (!strncmp(value, "fractal", strlen(value))) {
123 callchain_param.mode = CHAIN_GRAPH_REL;
124 return 0;
125 }
126 return -1;
127}
79 128
80 /* get the call chain order */ 129static int parse_callchain_order(const char *value)
81 if (!strncmp(tok2, "caller", strlen("caller"))) 130{
131 if (!strncmp(value, "caller", strlen(value))) {
82 callchain_param.order = ORDER_CALLER; 132 callchain_param.order = ORDER_CALLER;
83 else if (!strncmp(tok2, "callee", strlen("callee"))) 133 return 0;
134 }
135 if (!strncmp(value, "callee", strlen(value))) {
84 callchain_param.order = ORDER_CALLEE; 136 callchain_param.order = ORDER_CALLEE;
85 else 137 return 0;
86 return -1; 138 }
139 return -1;
140}
87 141
88 /* Get the sort key */ 142static int parse_callchain_sort_key(const char *value)
89 tok2 = strtok(NULL, ","); 143{
90 if (!tok2) 144 if (!strncmp(value, "function", strlen(value))) {
91 goto setup;
92 if (!strncmp(tok2, "function", strlen("function")))
93 callchain_param.key = CCKEY_FUNCTION; 145 callchain_param.key = CCKEY_FUNCTION;
94 else if (!strncmp(tok2, "address", strlen("address"))) 146 return 0;
147 }
148 if (!strncmp(value, "address", strlen(value))) {
95 callchain_param.key = CCKEY_ADDRESS; 149 callchain_param.key = CCKEY_ADDRESS;
96 else 150 return 0;
97 return -1; 151 }
98setup: 152 return -1;
153}
154
155int
156parse_callchain_report_opt(const char *arg)
157{
158 char *tok;
159 char *endptr;
160 bool minpcnt_set = false;
161
162 symbol_conf.use_callchain = true;
163
164 if (!arg)
165 return 0;
166
167 while ((tok = strtok((char *)arg, ",")) != NULL) {
168 if (!strncmp(tok, "none", strlen(tok))) {
169 callchain_param.mode = CHAIN_NONE;
170 symbol_conf.use_callchain = false;
171 return 0;
172 }
173
174 if (!parse_callchain_mode(tok) ||
175 !parse_callchain_order(tok) ||
176 !parse_callchain_sort_key(tok)) {
177 /* parsing ok - move on to the next */
178 } else if (!minpcnt_set) {
179 /* try to get the min percent */
180 callchain_param.min_percent = strtod(tok, &endptr);
181 if (tok == endptr)
182 return -1;
183 minpcnt_set = true;
184 } else {
185 /* try print limit at last */
186 callchain_param.print_limit = strtoul(tok, &endptr, 0);
187 if (tok == endptr)
188 return -1;
189 }
190
191 arg = NULL;
192 }
193
99 if (callchain_register_param(&callchain_param) < 0) { 194 if (callchain_register_param(&callchain_param) < 0) {
100 pr_err("Can't register callchain params\n"); 195 pr_err("Can't register callchain params\n");
101 return -1; 196 return -1;
@@ -103,6 +198,47 @@ setup:
103 return 0; 198 return 0;
104} 199}
105 200
201int perf_callchain_config(const char *var, const char *value)
202{
203 char *endptr;
204
205 if (prefixcmp(var, "call-graph."))
206 return 0;
207 var += sizeof("call-graph.") - 1;
208
209 if (!strcmp(var, "record-mode"))
210 return parse_callchain_record_opt(value);
211#ifdef HAVE_DWARF_UNWIND_SUPPORT
212 if (!strcmp(var, "dump-size")) {
213 unsigned long size = 0;
214 int ret;
215
216 ret = get_stack_size(value, &size);
217 callchain_param.dump_size = size;
218
219 return ret;
220 }
221#endif
222 if (!strcmp(var, "print-type"))
223 return parse_callchain_mode(value);
224 if (!strcmp(var, "order"))
225 return parse_callchain_order(value);
226 if (!strcmp(var, "sort-key"))
227 return parse_callchain_sort_key(value);
228 if (!strcmp(var, "threshold")) {
229 callchain_param.min_percent = strtod(value, &endptr);
230 if (value == endptr)
231 return -1;
232 }
233 if (!strcmp(var, "print-limit")) {
234 callchain_param.print_limit = strtod(value, &endptr);
235 if (value == endptr)
236 return -1;
237 }
238
239 return 0;
240}
241
106static void 242static void
107rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 243rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
108 enum chain_mode mode) 244 enum chain_mode mode)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index da43619d6173..94cfefddf4db 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -54,6 +54,9 @@ enum chain_key {
54}; 54};
55 55
56struct callchain_param { 56struct callchain_param {
57 bool enabled;
58 enum perf_call_graph_mode record_mode;
59 u32 dump_size;
57 enum chain_mode mode; 60 enum chain_mode mode;
58 u32 print_limit; 61 u32 print_limit;
59 double min_percent; 62 double min_percent;
@@ -62,6 +65,8 @@ struct callchain_param {
62 enum chain_key key; 65 enum chain_key key;
63}; 66};
64 67
68extern struct callchain_param callchain_param;
69
65struct callchain_list { 70struct callchain_list {
66 u64 ip; 71 u64 ip;
67 struct map_symbol ms; 72 struct map_symbol ms;
@@ -154,7 +159,6 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
154struct option; 159struct option;
155struct hist_entry; 160struct hist_entry;
156 161
157int record_parse_callchain(const char *arg, struct record_opts *opts);
158int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 162int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
159int record_callchain_opt(const struct option *opt, const char *arg, int unset); 163int record_callchain_opt(const struct option *opt, const char *arg, int unset);
160 164
@@ -166,7 +170,9 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
166 bool hide_unresolved); 170 bool hide_unresolved);
167 171
168extern const char record_callchain_help[]; 172extern const char record_callchain_help[];
173int parse_callchain_record_opt(const char *arg);
169int parse_callchain_report_opt(const char *arg); 174int parse_callchain_report_opt(const char *arg);
175int perf_callchain_config(const char *var, const char *value);
170 176
171static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, 177static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
172 struct callchain_cursor *src) 178 struct callchain_cursor *src)
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index c5d05ec17220..47b78b3f0325 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -1,7 +1,9 @@
1#include <sched.h>
1#include "util.h" 2#include "util.h"
2#include "../perf.h" 3#include "../perf.h"
3#include "cloexec.h" 4#include "cloexec.h"
4#include "asm/bug.h" 5#include "asm/bug.h"
6#include "debug.h"
5 7
6static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 8static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
7 9
@@ -9,15 +11,30 @@ static int perf_flag_probe(void)
9{ 11{
10 /* use 'safest' configuration as used in perf_evsel__fallback() */ 12 /* use 'safest' configuration as used in perf_evsel__fallback() */
11 struct perf_event_attr attr = { 13 struct perf_event_attr attr = {
12 .type = PERF_COUNT_SW_CPU_CLOCK, 14 .type = PERF_TYPE_SOFTWARE,
13 .config = PERF_COUNT_SW_CPU_CLOCK, 15 .config = PERF_COUNT_SW_CPU_CLOCK,
16 .exclude_kernel = 1,
14 }; 17 };
15 int fd; 18 int fd;
16 int err; 19 int err;
20 int cpu;
21 pid_t pid = -1;
22 char sbuf[STRERR_BUFSIZE];
17 23
18 /* check cloexec flag */ 24 cpu = sched_getcpu();
19 fd = sys_perf_event_open(&attr, 0, -1, -1, 25 if (cpu < 0)
20 PERF_FLAG_FD_CLOEXEC); 26 cpu = 0;
27
28 while (1) {
29 /* check cloexec flag */
30 fd = sys_perf_event_open(&attr, pid, cpu, -1,
31 PERF_FLAG_FD_CLOEXEC);
32 if (fd < 0 && pid == -1 && errno == EACCES) {
33 pid = 0;
34 continue;
35 }
36 break;
37 }
21 err = errno; 38 err = errno;
22 39
23 if (fd >= 0) { 40 if (fd >= 0) {
@@ -25,17 +42,17 @@ static int perf_flag_probe(void)
25 return 1; 42 return 1;
26 } 43 }
27 44
28 WARN_ONCE(err != EINVAL, 45 WARN_ONCE(err != EINVAL && err != EBUSY,
29 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", 46 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
30 err, strerror(err)); 47 err, strerror_r(err, sbuf, sizeof(sbuf)));
31 48
32 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 49 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
33 fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 50 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
34 err = errno; 51 err = errno;
35 52
36 if (WARN_ONCE(fd < 0, 53 if (WARN_ONCE(fd < 0 && err != EBUSY,
37 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 54 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
38 err, strerror(err))) 55 err, strerror_r(err, sbuf, sizeof(sbuf))))
39 return -1; 56 return -1;
40 57
41 close(fd); 58 close(fd);
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 87b8672eb413..f4654183d391 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -335,3 +335,19 @@ int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
335 va_end(args); 335 va_end(args);
336 return value_color_snprintf(bf, size, fmt, percent); 336 return value_color_snprintf(bf, size, fmt, percent);
337} 337}
338
339int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
340{
341 va_list args;
342 int len;
343 double percent;
344 const char *color;
345
346 va_start(args, fmt);
347 len = va_arg(args, int);
348 percent = va_arg(args, double);
349 va_end(args);
350
351 color = get_percent_color(percent);
352 return color_snprintf(bf, size, color, fmt, len, percent);
353}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 7ff30a62a132..0a594b8a0c26 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -41,6 +41,7 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); 42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); 43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 45int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
45const char *get_percent_color(double percent); 46const char *get_percent_color(double percent);
46 47
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index f9e777629e21..b2bb59df65e1 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -74,7 +74,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
74 return new; 74 return new;
75} 75}
76 76
77struct comm *comm__new(const char *str, u64 timestamp) 77struct comm *comm__new(const char *str, u64 timestamp, bool exec)
78{ 78{
79 struct comm *comm = zalloc(sizeof(*comm)); 79 struct comm *comm = zalloc(sizeof(*comm));
80 80
@@ -82,6 +82,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
82 return NULL; 82 return NULL;
83 83
84 comm->start = timestamp; 84 comm->start = timestamp;
85 comm->exec = exec;
85 86
86 comm->comm_str = comm_str__findnew(str, &comm_str_root); 87 comm->comm_str = comm_str__findnew(str, &comm_str_root);
87 if (!comm->comm_str) { 88 if (!comm->comm_str) {
@@ -94,7 +95,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
94 return comm; 95 return comm;
95} 96}
96 97
97int comm__override(struct comm *comm, const char *str, u64 timestamp) 98int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
98{ 99{
99 struct comm_str *new, *old = comm->comm_str; 100 struct comm_str *new, *old = comm->comm_str;
100 101
@@ -106,6 +107,8 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp)
106 comm_str__put(old); 107 comm_str__put(old);
107 comm->comm_str = new; 108 comm->comm_str = new;
108 comm->start = timestamp; 109 comm->start = timestamp;
110 if (exec)
111 comm->exec = true;
109 112
110 return 0; 113 return 0;
111} 114}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index fac5bd51befc..51c10ab257f8 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -11,11 +11,13 @@ struct comm {
11 struct comm_str *comm_str; 11 struct comm_str *comm_str;
12 u64 start; 12 u64 start;
13 struct list_head list; 13 struct list_head list;
14 bool exec;
14}; 15};
15 16
16void comm__free(struct comm *comm); 17void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp); 18struct comm *comm__new(const char *str, u64 timestamp, bool exec);
18const char *comm__str(const struct comm *comm); 19const char *comm__str(const struct comm *comm);
19int comm__override(struct comm *comm, const char *str, u64 timestamp); 20int comm__override(struct comm *comm, const char *str, u64 timestamp,
21 bool exec);
20 22
21#endif /* __PERF_COMM_H */ 23#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 1e5e2e5af6b1..57ff826f150b 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -222,7 +222,8 @@ static int perf_parse_file(config_fn_t fn, void *data)
222 const unsigned char *bomptr = utf8_bom; 222 const unsigned char *bomptr = utf8_bom;
223 223
224 for (;;) { 224 for (;;) {
225 int c = get_next_char(); 225 int line, c = get_next_char();
226
226 if (bomptr && *bomptr) { 227 if (bomptr && *bomptr) {
227 /* We are at the file beginning; skip UTF8-encoded BOM 228 /* We are at the file beginning; skip UTF8-encoded BOM
228 * if present. Sane editors won't put this in on their 229 * if present. Sane editors won't put this in on their
@@ -261,8 +262,16 @@ static int perf_parse_file(config_fn_t fn, void *data)
261 if (!isalpha(c)) 262 if (!isalpha(c))
262 break; 263 break;
263 var[baselen] = tolower(c); 264 var[baselen] = tolower(c);
264 if (get_value(fn, data, var, baselen+1) < 0) 265
266 /*
267 * The get_value function might or might not reach the '\n',
268 * so saving the current line number for error reporting.
269 */
270 line = config_linenr;
271 if (get_value(fn, data, var, baselen+1) < 0) {
272 config_linenr = line;
265 break; 273 break;
274 }
266 } 275 }
267 die("bad config file line %d in %s", config_linenr, config_file_name); 276 die("bad config file line %d in %s", config_linenr, config_file_name);
268} 277}
@@ -286,6 +295,21 @@ static int parse_unit_factor(const char *end, unsigned long *val)
286 return 0; 295 return 0;
287} 296}
288 297
298static int perf_parse_llong(const char *value, long long *ret)
299{
300 if (value && *value) {
301 char *end;
302 long long val = strtoll(value, &end, 0);
303 unsigned long factor = 1;
304
305 if (!parse_unit_factor(end, &factor))
306 return 0;
307 *ret = val * factor;
308 return 1;
309 }
310 return 0;
311}
312
289static int perf_parse_long(const char *value, long *ret) 313static int perf_parse_long(const char *value, long *ret)
290{ 314{
291 if (value && *value) { 315 if (value && *value) {
@@ -307,6 +331,15 @@ static void die_bad_config(const char *name)
307 die("bad config value for '%s'", name); 331 die("bad config value for '%s'", name);
308} 332}
309 333
334u64 perf_config_u64(const char *name, const char *value)
335{
336 long long ret = 0;
337
338 if (!perf_parse_llong(value, &ret))
339 die_bad_config(name);
340 return (u64) ret;
341}
342
310int perf_config_int(const char *name, const char *value) 343int perf_config_int(const char *name, const char *value)
311{ 344{
312 long ret = 0; 345 long ret = 0;
@@ -372,6 +405,9 @@ int perf_default_config(const char *var, const char *value,
372 if (!prefixcmp(var, "ui.")) 405 if (!prefixcmp(var, "ui."))
373 return perf_ui_config(var, value); 406 return perf_ui_config(var, value);
374 407
408 if (!prefixcmp(var, "call-graph."))
409 return perf_callchain_config(var, value);
410
375 /* Add other config variables here. */ 411 /* Add other config variables here. */
376 return 0; 412 return 0;
377} 413}
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 29d720cf5844..1921942fc2e0 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -50,12 +50,14 @@ static int open_file_read(struct perf_data_file *file)
50{ 50{
51 struct stat st; 51 struct stat st;
52 int fd; 52 int fd;
53 char sbuf[STRERR_BUFSIZE];
53 54
54 fd = open(file->path, O_RDONLY); 55 fd = open(file->path, O_RDONLY);
55 if (fd < 0) { 56 if (fd < 0) {
56 int err = errno; 57 int err = errno;
57 58
58 pr_err("failed to open %s: %s", file->path, strerror(err)); 59 pr_err("failed to open %s: %s", file->path,
60 strerror_r(err, sbuf, sizeof(sbuf)));
59 if (err == ENOENT && !strcmp(file->path, "perf.data")) 61 if (err == ENOENT && !strcmp(file->path, "perf.data"))
60 pr_err(" (try 'perf record' first)"); 62 pr_err(" (try 'perf record' first)");
61 pr_err("\n"); 63 pr_err("\n");
@@ -88,6 +90,7 @@ static int open_file_read(struct perf_data_file *file)
88static int open_file_write(struct perf_data_file *file) 90static int open_file_write(struct perf_data_file *file)
89{ 91{
90 int fd; 92 int fd;
93 char sbuf[STRERR_BUFSIZE];
91 94
92 if (check_backup(file)) 95 if (check_backup(file))
93 return -1; 96 return -1;
@@ -95,7 +98,8 @@ static int open_file_write(struct perf_data_file *file)
95 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 98 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
96 99
97 if (fd < 0) 100 if (fd < 0)
98 pr_err("failed to open %s : %s\n", file->path, strerror(errno)); 101 pr_err("failed to open %s : %s\n", file->path,
102 strerror_r(errno, sbuf, sizeof(sbuf)));
99 103
100 return fd; 104 return fd;
101} 105}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 71d419362634..ba357f3226c6 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -13,8 +13,12 @@
13#include "util.h" 13#include "util.h"
14#include "target.h" 14#include "target.h"
15 15
16#define NSECS_PER_SEC 1000000000ULL
17#define NSECS_PER_USEC 1000ULL
18
16int verbose; 19int verbose;
17bool dump_trace = false, quiet = false; 20bool dump_trace = false, quiet = false;
21int debug_ordered_events;
18 22
19static int _eprintf(int level, int var, const char *fmt, va_list args) 23static int _eprintf(int level, int var, const char *fmt, va_list args)
20{ 24{
@@ -42,6 +46,35 @@ int eprintf(int level, int var, const char *fmt, ...)
42 return ret; 46 return ret;
43} 47}
44 48
49static int __eprintf_time(u64 t, const char *fmt, va_list args)
50{
51 int ret = 0;
52 u64 secs, usecs, nsecs = t;
53
54 secs = nsecs / NSECS_PER_SEC;
55 nsecs -= secs * NSECS_PER_SEC;
56 usecs = nsecs / NSECS_PER_USEC;
57
58 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
59 secs, usecs);
60 ret += vfprintf(stderr, fmt, args);
61 return ret;
62}
63
64int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
65{
66 int ret = 0;
67 va_list args;
68
69 if (var >= level) {
70 va_start(args, fmt);
71 ret = __eprintf_time(t, fmt, args);
72 va_end(args);
73 }
74
75 return ret;
76}
77
45/* 78/*
46 * Overloading libtraceevent standard info print 79 * Overloading libtraceevent standard info print
47 * function, display with -v in perf. 80 * function, display with -v in perf.
@@ -110,7 +143,8 @@ static struct debug_variable {
110 const char *name; 143 const char *name;
111 int *ptr; 144 int *ptr;
112} debug_variables[] = { 145} debug_variables[] = {
113 { .name = "verbose", .ptr = &verbose }, 146 { .name = "verbose", .ptr = &verbose },
147 { .name = "ordered-events", .ptr = &debug_ordered_events},
114 { .name = NULL, } 148 { .name = NULL, }
115}; 149};
116 150
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 89fb6b0f7ab2..be264d6f3b30 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -3,6 +3,7 @@
3#define __PERF_DEBUG_H 3#define __PERF_DEBUG_H
4 4
5#include <stdbool.h> 5#include <stdbool.h>
6#include <string.h>
6#include "event.h" 7#include "event.h"
7#include "../ui/helpline.h" 8#include "../ui/helpline.h"
8#include "../ui/progress.h" 9#include "../ui/progress.h"
@@ -10,6 +11,7 @@
10 11
11extern int verbose; 12extern int verbose;
12extern bool quiet, dump_trace; 13extern bool quiet, dump_trace;
14extern int debug_ordered_events;
13 15
14#ifndef pr_fmt 16#ifndef pr_fmt
15#define pr_fmt(fmt) fmt 17#define pr_fmt(fmt) fmt
@@ -29,6 +31,14 @@ extern bool quiet, dump_trace;
29#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 31#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
30#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 32#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
31 33
34#define pr_time_N(n, var, t, fmt, ...) \
35 eprintf_time(n, var, t, fmt, ##__VA_ARGS__)
36
37#define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
38#define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
39
40#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
41
32int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 42int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
33void trace_event(union perf_event *event); 43void trace_event(union perf_event *event);
34 44
@@ -38,6 +48,7 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
38void pr_stat(const char *fmt, ...); 48void pr_stat(const char *fmt, ...);
39 49
40int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); 50int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
51int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5)));
41 52
42int perf_debug_option(const char *str); 53int perf_debug_option(const char *str);
43 54
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 90d02c661dd4..0247acfdfaca 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -37,6 +37,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
37{ 37{
38 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 38 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
39 int ret = 0; 39 int ret = 0;
40 size_t len;
40 41
41 switch (type) { 42 switch (type) {
42 case DSO_BINARY_TYPE__DEBUGLINK: { 43 case DSO_BINARY_TYPE__DEBUGLINK: {
@@ -60,26 +61,25 @@ int dso__read_binary_type_filename(const struct dso *dso,
60 break; 61 break;
61 62
62 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: 63 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
63 snprintf(filename, size, "%s/usr/lib/debug%s.debug", 64 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
64 symbol_conf.symfs, dso->long_name); 65 snprintf(filename + len, size - len, "%s.debug", dso->long_name);
65 break; 66 break;
66 67
67 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: 68 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
68 snprintf(filename, size, "%s/usr/lib/debug%s", 69 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
69 symbol_conf.symfs, dso->long_name); 70 snprintf(filename + len, size - len, "%s", dso->long_name);
70 break; 71 break;
71 72
72 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: 73 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
73 { 74 {
74 const char *last_slash; 75 const char *last_slash;
75 size_t len;
76 size_t dir_size; 76 size_t dir_size;
77 77
78 last_slash = dso->long_name + dso->long_name_len; 78 last_slash = dso->long_name + dso->long_name_len;
79 while (last_slash != dso->long_name && *last_slash != '/') 79 while (last_slash != dso->long_name && *last_slash != '/')
80 last_slash--; 80 last_slash--;
81 81
82 len = scnprintf(filename, size, "%s", symbol_conf.symfs); 82 len = __symbol__join_symfs(filename, size, "");
83 dir_size = last_slash - dso->long_name + 2; 83 dir_size = last_slash - dso->long_name + 2;
84 if (dir_size > (size - len)) { 84 if (dir_size > (size - len)) {
85 ret = -1; 85 ret = -1;
@@ -100,26 +100,24 @@ int dso__read_binary_type_filename(const struct dso *dso,
100 build_id__sprintf(dso->build_id, 100 build_id__sprintf(dso->build_id,
101 sizeof(dso->build_id), 101 sizeof(dso->build_id),
102 build_id_hex); 102 build_id_hex);
103 snprintf(filename, size, 103 len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
104 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", 104 snprintf(filename + len, size - len, "%.2s/%s.debug",
105 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 105 build_id_hex, build_id_hex + 2);
106 break; 106 break;
107 107
108 case DSO_BINARY_TYPE__VMLINUX: 108 case DSO_BINARY_TYPE__VMLINUX:
109 case DSO_BINARY_TYPE__GUEST_VMLINUX: 109 case DSO_BINARY_TYPE__GUEST_VMLINUX:
110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: 110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
111 snprintf(filename, size, "%s%s", 111 __symbol__join_symfs(filename, size, dso->long_name);
112 symbol_conf.symfs, dso->long_name);
113 break; 112 break;
114 113
115 case DSO_BINARY_TYPE__GUEST_KMODULE: 114 case DSO_BINARY_TYPE__GUEST_KMODULE:
116 snprintf(filename, size, "%s%s%s", symbol_conf.symfs, 115 path__join3(filename, size, symbol_conf.symfs,
117 root_dir, dso->long_name); 116 root_dir, dso->long_name);
118 break; 117 break;
119 118
120 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 119 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
121 snprintf(filename, size, "%s%s", symbol_conf.symfs, 120 __symbol__join_symfs(filename, size, dso->long_name);
122 dso->long_name);
123 break; 121 break;
124 122
125 case DSO_BINARY_TYPE__KCORE: 123 case DSO_BINARY_TYPE__KCORE:
@@ -164,13 +162,15 @@ static void close_first_dso(void);
164static int do_open(char *name) 162static int do_open(char *name)
165{ 163{
166 int fd; 164 int fd;
165 char sbuf[STRERR_BUFSIZE];
167 166
168 do { 167 do {
169 fd = open(name, O_RDONLY); 168 fd = open(name, O_RDONLY);
170 if (fd >= 0) 169 if (fd >= 0)
171 return fd; 170 return fd;
172 171
173 pr_debug("dso open failed, mmap: %s\n", strerror(errno)); 172 pr_debug("dso open failed, mmap: %s\n",
173 strerror_r(errno, sbuf, sizeof(sbuf)));
174 if (!dso__data_open_cnt || errno != EMFILE) 174 if (!dso__data_open_cnt || errno != EMFILE)
175 break; 175 break;
176 176
@@ -532,10 +532,12 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
532static int data_file_size(struct dso *dso) 532static int data_file_size(struct dso *dso)
533{ 533{
534 struct stat st; 534 struct stat st;
535 char sbuf[STRERR_BUFSIZE];
535 536
536 if (!dso->data.file_size) { 537 if (!dso->data.file_size) {
537 if (fstat(dso->data.fd, &st)) { 538 if (fstat(dso->data.fd, &st)) {
538 pr_err("dso mmap failed, fstat: %s\n", strerror(errno)); 539 pr_err("dso mmap failed, fstat: %s\n",
540 strerror_r(errno, sbuf, sizeof(sbuf)));
539 return -1; 541 return -1;
540 } 542 }
541 dso->data.file_size = st.st_size; 543 dso->data.file_size = st.st_size;
@@ -651,6 +653,65 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
651 return dso; 653 return dso;
652} 654}
653 655
656/*
657 * Find a matching entry and/or link current entry to RB tree.
658 * Either one of the dso or name parameter must be non-NULL or the
659 * function will not work.
660 */
661static struct dso *dso__findlink_by_longname(struct rb_root *root,
662 struct dso *dso, const char *name)
663{
664 struct rb_node **p = &root->rb_node;
665 struct rb_node *parent = NULL;
666
667 if (!name)
668 name = dso->long_name;
669 /*
670 * Find node with the matching name
671 */
672 while (*p) {
673 struct dso *this = rb_entry(*p, struct dso, rb_node);
674 int rc = strcmp(name, this->long_name);
675
676 parent = *p;
677 if (rc == 0) {
678 /*
679 * In case the new DSO is a duplicate of an existing
680 * one, print an one-time warning & put the new entry
681 * at the end of the list of duplicates.
682 */
683 if (!dso || (dso == this))
684 return this; /* Find matching dso */
685 /*
686 * The core kernel DSOs may have duplicated long name.
687 * In this case, the short name should be different.
688 * Comparing the short names to differentiate the DSOs.
689 */
690 rc = strcmp(dso->short_name, this->short_name);
691 if (rc == 0) {
692 pr_err("Duplicated dso name: %s\n", name);
693 return NULL;
694 }
695 }
696 if (rc < 0)
697 p = &parent->rb_left;
698 else
699 p = &parent->rb_right;
700 }
701 if (dso) {
702 /* Add new node and rebalance tree */
703 rb_link_node(&dso->rb_node, parent, p);
704 rb_insert_color(&dso->rb_node, root);
705 }
706 return NULL;
707}
708
709static inline struct dso *
710dso__find_by_longname(const struct rb_root *root, const char *name)
711{
712 return dso__findlink_by_longname((struct rb_root *)root, NULL, name);
713}
714
654void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 715void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
655{ 716{
656 if (name == NULL) 717 if (name == NULL)
@@ -753,6 +814,7 @@ struct dso *dso__new(const char *name)
753 dso->a2l_fails = 1; 814 dso->a2l_fails = 1;
754 dso->kernel = DSO_TYPE_USER; 815 dso->kernel = DSO_TYPE_USER;
755 dso->needs_swap = DSO_SWAP__UNSET; 816 dso->needs_swap = DSO_SWAP__UNSET;
817 RB_CLEAR_NODE(&dso->rb_node);
756 INIT_LIST_HEAD(&dso->node); 818 INIT_LIST_HEAD(&dso->node);
757 INIT_LIST_HEAD(&dso->data.open_entry); 819 INIT_LIST_HEAD(&dso->data.open_entry);
758 } 820 }
@@ -763,6 +825,10 @@ struct dso *dso__new(const char *name)
763void dso__delete(struct dso *dso) 825void dso__delete(struct dso *dso)
764{ 826{
765 int i; 827 int i;
828
829 if (!RB_EMPTY_NODE(&dso->rb_node))
830 pr_err("DSO %s is still in rbtree when being deleted!\n",
831 dso->long_name);
766 for (i = 0; i < MAP__NR_TYPES; ++i) 832 for (i = 0; i < MAP__NR_TYPES; ++i)
767 symbols__delete(&dso->symbols[i]); 833 symbols__delete(&dso->symbols[i]);
768 834
@@ -849,35 +915,34 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
849 return have_build_id; 915 return have_build_id;
850} 916}
851 917
852void dsos__add(struct list_head *head, struct dso *dso) 918void dsos__add(struct dsos *dsos, struct dso *dso)
853{ 919{
854 list_add_tail(&dso->node, head); 920 list_add_tail(&dso->node, &dsos->head);
921 dso__findlink_by_longname(&dsos->root, dso, NULL);
855} 922}
856 923
857struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short) 924struct dso *dsos__find(const struct dsos *dsos, const char *name,
925 bool cmp_short)
858{ 926{
859 struct dso *pos; 927 struct dso *pos;
860 928
861 if (cmp_short) { 929 if (cmp_short) {
862 list_for_each_entry(pos, head, node) 930 list_for_each_entry(pos, &dsos->head, node)
863 if (strcmp(pos->short_name, name) == 0) 931 if (strcmp(pos->short_name, name) == 0)
864 return pos; 932 return pos;
865 return NULL; 933 return NULL;
866 } 934 }
867 list_for_each_entry(pos, head, node) 935 return dso__find_by_longname(&dsos->root, name);
868 if (strcmp(pos->long_name, name) == 0)
869 return pos;
870 return NULL;
871} 936}
872 937
873struct dso *__dsos__findnew(struct list_head *head, const char *name) 938struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
874{ 939{
875 struct dso *dso = dsos__find(head, name, false); 940 struct dso *dso = dsos__find(dsos, name, false);
876 941
877 if (!dso) { 942 if (!dso) {
878 dso = dso__new(name); 943 dso = dso__new(name);
879 if (dso != NULL) { 944 if (dso != NULL) {
880 dsos__add(head, dso); 945 dsos__add(dsos, dso);
881 dso__set_basename(dso); 946 dso__set_basename(dso);
882 } 947 }
883 } 948 }
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 5e463c0964d4..acb651acc7fd 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -90,8 +90,18 @@ struct dso_cache {
90 char data[0]; 90 char data[0];
91}; 91};
92 92
93/*
94 * DSOs are put into both a list for fast iteration and rbtree for fast
95 * long name lookup.
96 */
97struct dsos {
98 struct list_head head;
99 struct rb_root root; /* rbtree root sorted by long name */
100};
101
93struct dso { 102struct dso {
94 struct list_head node; 103 struct list_head node;
104 struct rb_node rb_node; /* rbtree node sorted by long name */
95 struct rb_root symbols[MAP__NR_TYPES]; 105 struct rb_root symbols[MAP__NR_TYPES];
96 struct rb_root symbol_names[MAP__NR_TYPES]; 106 struct rb_root symbol_names[MAP__NR_TYPES];
97 void *a2l; 107 void *a2l;
@@ -224,10 +234,10 @@ struct map *dso__new_map(const char *name);
224struct dso *dso__kernel_findnew(struct machine *machine, const char *name, 234struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
225 const char *short_name, int dso_type); 235 const char *short_name, int dso_type);
226 236
227void dsos__add(struct list_head *head, struct dso *dso); 237void dsos__add(struct dsos *dsos, struct dso *dso);
228struct dso *dsos__find(const struct list_head *head, const char *name, 238struct dso *dsos__find(const struct dsos *dsos, const char *name,
229 bool cmp_short); 239 bool cmp_short);
230struct dso *__dsos__findnew(struct list_head *head, const char *name); 240struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
231bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 241bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
232 242
233size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 243size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 1398c83d896d..4af6b279e34a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -558,13 +558,17 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
558 struct map *map; 558 struct map *map;
559 struct kmap *kmap; 559 struct kmap *kmap;
560 int err; 560 int err;
561 union perf_event *event;
562
563 if (machine->vmlinux_maps[0] == NULL)
564 return -1;
565
561 /* 566 /*
562 * We should get this from /sys/kernel/sections/.text, but till that is 567 * We should get this from /sys/kernel/sections/.text, but till that is
563 * available use this, and after it is use this as a fallback for older 568 * available use this, and after it is use this as a fallback for older
564 * kernels. 569 * kernels.
565 */ 570 */
566 union perf_event *event = zalloc((sizeof(event->mmap) + 571 event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
567 machine->id_hdr_size));
568 if (event == NULL) { 572 if (event == NULL) {
569 pr_debug("Not enough memory synthesizing mmap event " 573 pr_debug("Not enough memory synthesizing mmap event "
570 "for kernel modules\n"); 574 "for kernel modules\n");
@@ -784,9 +788,9 @@ try_again:
784 * "[vdso]" dso, but for now lets use the old trick of looking 788 * "[vdso]" dso, but for now lets use the old trick of looking
785 * in the whole kernel symbol list. 789 * in the whole kernel symbol list.
786 */ 790 */
787 if ((long long)al->addr < 0 && 791 if (cpumode == PERF_RECORD_MISC_USER && machine &&
788 cpumode == PERF_RECORD_MISC_USER && 792 mg != &machine->kmaps &&
789 machine && mg != &machine->kmaps) { 793 machine__kernel_ip(machine, al->addr)) {
790 mg = &machine->kmaps; 794 mg = &machine->kmaps;
791 load_map = true; 795 load_map = true;
792 goto try_again; 796 goto try_again;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 94d6976180da..5699e7e2a790 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -156,6 +156,8 @@ struct perf_sample {
156 u32 cpu; 156 u32 cpu;
157 u32 raw_size; 157 u32 raw_size;
158 u64 data_src; 158 u64 data_src;
159 u32 flags;
160 u16 insn_len;
159 void *raw_data; 161 void *raw_data;
160 struct ip_callchain *callchain; 162 struct ip_callchain *callchain;
161 struct branch_stack *branch_stack; 163 struct branch_stack *branch_stack;
@@ -188,6 +190,32 @@ enum perf_user_event_type { /* above any possible kernel type */
188 PERF_RECORD_HEADER_MAX 190 PERF_RECORD_HEADER_MAX
189}; 191};
190 192
193/*
194 * The kernel collects the number of events it couldn't send in a stretch and
195 * when possible sends this number in a PERF_RECORD_LOST event. The number of
196 * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
197 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
198 * the sum of all struct lost_event.lost fields reported.
199 *
200 * The total_period is needed because by default auto-freq is used, so
201 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
202 * the total number of low level events, it is necessary to to sum all struct
203 * sample_event.period and stash the result in total_period.
204 */
205struct events_stats {
206 u64 total_period;
207 u64 total_non_filtered_period;
208 u64 total_lost;
209 u64 total_invalid_chains;
210 u32 nr_events[PERF_RECORD_HEADER_MAX];
211 u32 nr_non_filtered_samples;
212 u32 nr_lost_warned;
213 u32 nr_unknown_events;
214 u32 nr_invalid_chains;
215 u32 nr_unknown_id;
216 u32 nr_unprocessable_samples;
217};
218
191struct attr_event { 219struct attr_event {
192 struct perf_event_header header; 220 struct perf_event_header header;
193 struct perf_event_attr attr; 221 struct perf_event_attr attr;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 814e954c1318..3c9e77d6b4c2 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,9 @@
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/hash.h> 26#include <linux/hash.h>
27 27
28static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
29static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
30
28#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 31#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
29#define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 32#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
30 33
@@ -37,6 +40,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
37 INIT_HLIST_HEAD(&evlist->heads[i]); 40 INIT_HLIST_HEAD(&evlist->heads[i]);
38 INIT_LIST_HEAD(&evlist->entries); 41 INIT_LIST_HEAD(&evlist->entries);
39 perf_evlist__set_maps(evlist, cpus, threads); 42 perf_evlist__set_maps(evlist, cpus, threads);
43 fdarray__init(&evlist->pollfd, 64);
40 evlist->workload.pid = -1; 44 evlist->workload.pid = -1;
41} 45}
42 46
@@ -102,7 +106,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
102void perf_evlist__exit(struct perf_evlist *evlist) 106void perf_evlist__exit(struct perf_evlist *evlist)
103{ 107{
104 zfree(&evlist->mmap); 108 zfree(&evlist->mmap);
105 zfree(&evlist->pollfd); 109 fdarray__exit(&evlist->pollfd);
106} 110}
107 111
108void perf_evlist__delete(struct perf_evlist *evlist) 112void perf_evlist__delete(struct perf_evlist *evlist)
@@ -122,6 +126,7 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
122{ 126{
123 list_add_tail(&entry->node, &evlist->entries); 127 list_add_tail(&entry->node, &evlist->entries);
124 entry->idx = evlist->nr_entries; 128 entry->idx = evlist->nr_entries;
129 entry->tracking = !entry->idx;
125 130
126 if (!evlist->nr_entries++) 131 if (!evlist->nr_entries++)
127 perf_evlist__set_id_pos(evlist); 132 perf_evlist__set_id_pos(evlist);
@@ -265,17 +270,27 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
265 return 0; 270 return 0;
266} 271}
267 272
273static int perf_evlist__nr_threads(struct perf_evlist *evlist,
274 struct perf_evsel *evsel)
275{
276 if (evsel->system_wide)
277 return 1;
278 else
279 return thread_map__nr(evlist->threads);
280}
281
268void perf_evlist__disable(struct perf_evlist *evlist) 282void perf_evlist__disable(struct perf_evlist *evlist)
269{ 283{
270 int cpu, thread; 284 int cpu, thread;
271 struct perf_evsel *pos; 285 struct perf_evsel *pos;
272 int nr_cpus = cpu_map__nr(evlist->cpus); 286 int nr_cpus = cpu_map__nr(evlist->cpus);
273 int nr_threads = thread_map__nr(evlist->threads); 287 int nr_threads;
274 288
275 for (cpu = 0; cpu < nr_cpus; cpu++) { 289 for (cpu = 0; cpu < nr_cpus; cpu++) {
276 evlist__for_each(evlist, pos) { 290 evlist__for_each(evlist, pos) {
277 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 291 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
278 continue; 292 continue;
293 nr_threads = perf_evlist__nr_threads(evlist, pos);
279 for (thread = 0; thread < nr_threads; thread++) 294 for (thread = 0; thread < nr_threads; thread++)
280 ioctl(FD(pos, cpu, thread), 295 ioctl(FD(pos, cpu, thread),
281 PERF_EVENT_IOC_DISABLE, 0); 296 PERF_EVENT_IOC_DISABLE, 0);
@@ -288,12 +303,13 @@ void perf_evlist__enable(struct perf_evlist *evlist)
288 int cpu, thread; 303 int cpu, thread;
289 struct perf_evsel *pos; 304 struct perf_evsel *pos;
290 int nr_cpus = cpu_map__nr(evlist->cpus); 305 int nr_cpus = cpu_map__nr(evlist->cpus);
291 int nr_threads = thread_map__nr(evlist->threads); 306 int nr_threads;
292 307
293 for (cpu = 0; cpu < nr_cpus; cpu++) { 308 for (cpu = 0; cpu < nr_cpus; cpu++) {
294 evlist__for_each(evlist, pos) { 309 evlist__for_each(evlist, pos) {
295 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 310 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
296 continue; 311 continue;
312 nr_threads = perf_evlist__nr_threads(evlist, pos);
297 for (thread = 0; thread < nr_threads; thread++) 313 for (thread = 0; thread < nr_threads; thread++)
298 ioctl(FD(pos, cpu, thread), 314 ioctl(FD(pos, cpu, thread),
299 PERF_EVENT_IOC_ENABLE, 0); 315 PERF_EVENT_IOC_ENABLE, 0);
@@ -305,12 +321,14 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
305 struct perf_evsel *evsel) 321 struct perf_evsel *evsel)
306{ 322{
307 int cpu, thread, err; 323 int cpu, thread, err;
324 int nr_cpus = cpu_map__nr(evlist->cpus);
325 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
308 326
309 if (!evsel->fd) 327 if (!evsel->fd)
310 return 0; 328 return 0;
311 329
312 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 330 for (cpu = 0; cpu < nr_cpus; cpu++) {
313 for (thread = 0; thread < evlist->threads->nr; thread++) { 331 for (thread = 0; thread < nr_threads; thread++) {
314 err = ioctl(FD(evsel, cpu, thread), 332 err = ioctl(FD(evsel, cpu, thread),
315 PERF_EVENT_IOC_DISABLE, 0); 333 PERF_EVENT_IOC_DISABLE, 0);
316 if (err) 334 if (err)
@@ -324,12 +342,14 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
324 struct perf_evsel *evsel) 342 struct perf_evsel *evsel)
325{ 343{
326 int cpu, thread, err; 344 int cpu, thread, err;
345 int nr_cpus = cpu_map__nr(evlist->cpus);
346 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
327 347
328 if (!evsel->fd) 348 if (!evsel->fd)
329 return -EINVAL; 349 return -EINVAL;
330 350
331 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 351 for (cpu = 0; cpu < nr_cpus; cpu++) {
332 for (thread = 0; thread < evlist->threads->nr; thread++) { 352 for (thread = 0; thread < nr_threads; thread++) {
333 err = ioctl(FD(evsel, cpu, thread), 353 err = ioctl(FD(evsel, cpu, thread),
334 PERF_EVENT_IOC_ENABLE, 0); 354 PERF_EVENT_IOC_ENABLE, 0);
335 if (err) 355 if (err)
@@ -339,21 +359,111 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
339 return 0; 359 return 0;
340} 360}
341 361
342static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 362static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
363 struct perf_evsel *evsel, int cpu)
364{
365 int thread, err;
366 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
367
368 if (!evsel->fd)
369 return -EINVAL;
370
371 for (thread = 0; thread < nr_threads; thread++) {
372 err = ioctl(FD(evsel, cpu, thread),
373 PERF_EVENT_IOC_ENABLE, 0);
374 if (err)
375 return err;
376 }
377 return 0;
378}
379
380static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
381 struct perf_evsel *evsel,
382 int thread)
383{
384 int cpu, err;
385 int nr_cpus = cpu_map__nr(evlist->cpus);
386
387 if (!evsel->fd)
388 return -EINVAL;
389
390 for (cpu = 0; cpu < nr_cpus; cpu++) {
391 err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
392 if (err)
393 return err;
394 }
395 return 0;
396}
397
398int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
399 struct perf_evsel *evsel, int idx)
400{
401 bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus);
402
403 if (per_cpu_mmaps)
404 return perf_evlist__enable_event_cpu(evlist, evsel, idx);
405 else
406 return perf_evlist__enable_event_thread(evlist, evsel, idx);
407}
408
409int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
343{ 410{
344 int nr_cpus = cpu_map__nr(evlist->cpus); 411 int nr_cpus = cpu_map__nr(evlist->cpus);
345 int nr_threads = thread_map__nr(evlist->threads); 412 int nr_threads = thread_map__nr(evlist->threads);
346 int nfds = nr_cpus * nr_threads * evlist->nr_entries; 413 int nfds = 0;
347 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 414 struct perf_evsel *evsel;
348 return evlist->pollfd != NULL ? 0 : -ENOMEM; 415
416 list_for_each_entry(evsel, &evlist->entries, node) {
417 if (evsel->system_wide)
418 nfds += nr_cpus;
419 else
420 nfds += nr_cpus * nr_threads;
421 }
422
423 if (fdarray__available_entries(&evlist->pollfd) < nfds &&
424 fdarray__grow(&evlist->pollfd, nfds) < 0)
425 return -ENOMEM;
426
427 return 0;
428}
429
430static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx)
431{
432 int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
433 /*
434 * Save the idx so that when we filter out fds POLLHUP'ed we can
435 * close the associated evlist->mmap[] entry.
436 */
437 if (pos >= 0) {
438 evlist->pollfd.priv[pos].idx = idx;
439
440 fcntl(fd, F_SETFL, O_NONBLOCK);
441 }
442
443 return pos;
444}
445
446int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
447{
448 return __perf_evlist__add_pollfd(evlist, fd, -1);
449}
450
451static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd)
452{
453 struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd);
454
455 perf_evlist__mmap_put(evlist, fda->priv[fd].idx);
456}
457
458int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
459{
460 return fdarray__filter(&evlist->pollfd, revents_and_mask,
461 perf_evlist__munmap_filtered);
349} 462}
350 463
351void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 464int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
352{ 465{
353 fcntl(fd, F_SETFL, O_NONBLOCK); 466 return fdarray__poll(&evlist->pollfd, timeout);
354 evlist->pollfd[evlist->nr_fds].fd = fd;
355 evlist->pollfd[evlist->nr_fds].events = POLLIN;
356 evlist->nr_fds++;
357} 467}
358 468
359static void perf_evlist__id_hash(struct perf_evlist *evlist, 469static void perf_evlist__id_hash(struct perf_evlist *evlist,
@@ -566,14 +676,36 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
566 return event; 676 return event;
567} 677}
568 678
679static bool perf_mmap__empty(struct perf_mmap *md)
680{
681 return perf_mmap__read_head(md) != md->prev;
682}
683
684static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
685{
686 ++evlist->mmap[idx].refcnt;
687}
688
689static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
690{
691 BUG_ON(evlist->mmap[idx].refcnt == 0);
692
693 if (--evlist->mmap[idx].refcnt == 0)
694 __perf_evlist__munmap(evlist, idx);
695}
696
569void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 697void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
570{ 698{
699 struct perf_mmap *md = &evlist->mmap[idx];
700
571 if (!evlist->overwrite) { 701 if (!evlist->overwrite) {
572 struct perf_mmap *md = &evlist->mmap[idx];
573 unsigned int old = md->prev; 702 unsigned int old = md->prev;
574 703
575 perf_mmap__write_tail(md, old); 704 perf_mmap__write_tail(md, old);
576 } 705 }
706
707 if (md->refcnt == 1 && perf_mmap__empty(md))
708 perf_evlist__mmap_put(evlist, idx);
577} 709}
578 710
579static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 711static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
@@ -581,6 +713,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
581 if (evlist->mmap[idx].base != NULL) { 713 if (evlist->mmap[idx].base != NULL) {
582 munmap(evlist->mmap[idx].base, evlist->mmap_len); 714 munmap(evlist->mmap[idx].base, evlist->mmap_len);
583 evlist->mmap[idx].base = NULL; 715 evlist->mmap[idx].base = NULL;
716 evlist->mmap[idx].refcnt = 0;
584 } 717 }
585} 718}
586 719
@@ -614,6 +747,20 @@ struct mmap_params {
614static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 747static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
615 struct mmap_params *mp, int fd) 748 struct mmap_params *mp, int fd)
616{ 749{
750 /*
751 * The last one will be done at perf_evlist__mmap_consume(), so that we
752 * make sure we don't prevent tools from consuming every last event in
753 * the ring buffer.
754 *
755 * I.e. we can get the POLLHUP meaning that the fd doesn't exist
756 * anymore, but the last events for it are still in the ring buffer,
757 * waiting to be consumed.
758 *
759 * Tools can chose to ignore this at their own discretion, but the
760 * evlist layer can't just drop it when filtering events in
761 * perf_evlist__filter_pollfd().
762 */
763 evlist->mmap[idx].refcnt = 2;
617 evlist->mmap[idx].prev = 0; 764 evlist->mmap[idx].prev = 0;
618 evlist->mmap[idx].mask = mp->mask; 765 evlist->mmap[idx].mask = mp->mask;
619 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 766 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
@@ -625,7 +772,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
625 return -1; 772 return -1;
626 } 773 }
627 774
628 perf_evlist__add_pollfd(evlist, fd);
629 return 0; 775 return 0;
630} 776}
631 777
@@ -636,7 +782,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
636 struct perf_evsel *evsel; 782 struct perf_evsel *evsel;
637 783
638 evlist__for_each(evlist, evsel) { 784 evlist__for_each(evlist, evsel) {
639 int fd = FD(evsel, cpu, thread); 785 int fd;
786
787 if (evsel->system_wide && thread)
788 continue;
789
790 fd = FD(evsel, cpu, thread);
640 791
641 if (*output == -1) { 792 if (*output == -1) {
642 *output = fd; 793 *output = fd;
@@ -645,6 +796,13 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
645 } else { 796 } else {
646 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 797 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
647 return -1; 798 return -1;
799
800 perf_evlist__mmap_get(evlist, idx);
801 }
802
803 if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
804 perf_evlist__mmap_put(evlist, idx);
805 return -1;
648 } 806 }
649 807
650 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 808 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -804,7 +962,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
804 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 962 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
805 return -ENOMEM; 963 return -ENOMEM;
806 964
807 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 965 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
808 return -ENOMEM; 966 return -ENOMEM;
809 967
810 evlist->overwrite = overwrite; 968 evlist->overwrite = overwrite;
@@ -845,6 +1003,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
845 1003
846out_delete_threads: 1004out_delete_threads:
847 thread_map__delete(evlist->threads); 1005 thread_map__delete(evlist->threads);
1006 evlist->threads = NULL;
848 return -1; 1007 return -1;
849} 1008}
850 1009
@@ -1017,11 +1176,51 @@ void perf_evlist__close(struct perf_evlist *evlist)
1017 } 1176 }
1018} 1177}
1019 1178
1179static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
1180{
1181 int err = -ENOMEM;
1182
1183 /*
1184 * Try reading /sys/devices/system/cpu/online to get
1185 * an all cpus map.
1186 *
1187 * FIXME: -ENOMEM is the best we can do here, the cpu_map
1188 * code needs an overhaul to properly forward the
1189 * error, and we may not want to do that fallback to a
1190 * default cpu identity map :-\
1191 */
1192 evlist->cpus = cpu_map__new(NULL);
1193 if (evlist->cpus == NULL)
1194 goto out;
1195
1196 evlist->threads = thread_map__new_dummy();
1197 if (evlist->threads == NULL)
1198 goto out_free_cpus;
1199
1200 err = 0;
1201out:
1202 return err;
1203out_free_cpus:
1204 cpu_map__delete(evlist->cpus);
1205 evlist->cpus = NULL;
1206 goto out;
1207}
1208
1020int perf_evlist__open(struct perf_evlist *evlist) 1209int perf_evlist__open(struct perf_evlist *evlist)
1021{ 1210{
1022 struct perf_evsel *evsel; 1211 struct perf_evsel *evsel;
1023 int err; 1212 int err;
1024 1213
1214 /*
1215 * Default: one fd per CPU, all threads, aka systemwide
1216 * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL
1217 */
1218 if (evlist->threads == NULL && evlist->cpus == NULL) {
1219 err = perf_evlist__create_syswide_maps(evlist);
1220 if (err < 0)
1221 goto out_err;
1222 }
1223
1025 perf_evlist__update_id_pos(evlist); 1224 perf_evlist__update_id_pos(evlist);
1026 1225
1027 evlist__for_each(evlist, evsel) { 1226 evlist__for_each(evlist, evsel) {
@@ -1061,6 +1260,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1061 } 1260 }
1062 1261
1063 if (!evlist->workload.pid) { 1262 if (!evlist->workload.pid) {
1263 int ret;
1264
1064 if (pipe_output) 1265 if (pipe_output)
1065 dup2(2, 1); 1266 dup2(2, 1);
1066 1267
@@ -1078,8 +1279,22 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1078 /* 1279 /*
1079 * Wait until the parent tells us to go. 1280 * Wait until the parent tells us to go.
1080 */ 1281 */
1081 if (read(go_pipe[0], &bf, 1) == -1) 1282 ret = read(go_pipe[0], &bf, 1);
1082 perror("unable to read pipe"); 1283 /*
1284 * The parent will ask for the execvp() to be performed by
1285 * writing exactly one byte, in workload.cork_fd, usually via
1286 * perf_evlist__start_workload().
1287 *
1288 * For cancelling the workload without actuallin running it,
1289 * the parent will just close workload.cork_fd, without writing
1290 * anything, i.e. read will return zero and we just exit()
1291 * here.
1292 */
1293 if (ret != 1) {
1294 if (ret == -1)
1295 perror("unable to read pipe");
1296 exit(ret);
1297 }
1083 1298
1084 execvp(argv[0], (char **)argv); 1299 execvp(argv[0], (char **)argv);
1085 1300
@@ -1102,8 +1317,14 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1102 sigaction(SIGUSR1, &act, NULL); 1317 sigaction(SIGUSR1, &act, NULL);
1103 } 1318 }
1104 1319
1105 if (target__none(target)) 1320 if (target__none(target)) {
1321 if (evlist->threads == NULL) {
1322 fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n",
1323 __func__, __LINE__);
1324 goto out_close_pipes;
1325 }
1106 evlist->threads->map[0] = evlist->workload.pid; 1326 evlist->threads->map[0] = evlist->workload.pid;
1327 }
1107 1328
1108 close(child_ready_pipe[1]); 1329 close(child_ready_pipe[1]);
1109 close(go_pipe[0]); 1330 close(go_pipe[0]);
@@ -1202,7 +1423,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1202 int err, char *buf, size_t size) 1423 int err, char *buf, size_t size)
1203{ 1424{
1204 int printed, value; 1425 int printed, value;
1205 char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1426 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1206 1427
1207 switch (err) { 1428 switch (err) {
1208 case EACCES: 1429 case EACCES:
@@ -1250,3 +1471,19 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
1250 1471
1251 list_splice(&move, &evlist->entries); 1472 list_splice(&move, &evlist->entries);
1252} 1473}
1474
1475void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
1476 struct perf_evsel *tracking_evsel)
1477{
1478 struct perf_evsel *evsel;
1479
1480 if (tracking_evsel->tracking)
1481 return;
1482
1483 evlist__for_each(evlist, evsel) {
1484 if (evsel != tracking_evsel)
1485 evsel->tracking = false;
1486 }
1487
1488 tracking_evsel->tracking = true;
1489}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index f5173cd63693..649b0c597283 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,6 +2,7 @@
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <api/fd/array.h>
5#include <stdio.h> 6#include <stdio.h>
6#include "../perf.h" 7#include "../perf.h"
7#include "event.h" 8#include "event.h"
@@ -17,9 +18,15 @@ struct record_opts;
17#define PERF_EVLIST__HLIST_BITS 8 18#define PERF_EVLIST__HLIST_BITS 8
18#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 19#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
19 20
21/**
22 * struct perf_mmap - perf's ring buffer mmap details
23 *
24 * @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
25 */
20struct perf_mmap { 26struct perf_mmap {
21 void *base; 27 void *base;
22 int mask; 28 int mask;
29 int refcnt;
23 unsigned int prev; 30 unsigned int prev;
24 char event_copy[PERF_SAMPLE_MAX_SIZE]; 31 char event_copy[PERF_SAMPLE_MAX_SIZE];
25}; 32};
@@ -29,7 +36,6 @@ struct perf_evlist {
29 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 36 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
30 int nr_entries; 37 int nr_entries;
31 int nr_groups; 38 int nr_groups;
32 int nr_fds;
33 int nr_mmaps; 39 int nr_mmaps;
34 size_t mmap_len; 40 size_t mmap_len;
35 int id_pos; 41 int id_pos;
@@ -40,8 +46,8 @@ struct perf_evlist {
40 pid_t pid; 46 pid_t pid;
41 } workload; 47 } workload;
42 bool overwrite; 48 bool overwrite;
49 struct fdarray pollfd;
43 struct perf_mmap *mmap; 50 struct perf_mmap *mmap;
44 struct pollfd *pollfd;
45 struct thread_map *threads; 51 struct thread_map *threads;
46 struct cpu_map *cpus; 52 struct cpu_map *cpus;
47 struct perf_evsel *selected; 53 struct perf_evsel *selected;
@@ -82,7 +88,11 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
82void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 88void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
83 int cpu, int thread, u64 id); 89 int cpu, int thread, u64 id);
84 90
85void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 91int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
92int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
93int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
94
95int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
86 96
87struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 97struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
88 98
@@ -107,6 +117,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
107 void *ucontext)); 117 void *ucontext));
108int perf_evlist__start_workload(struct perf_evlist *evlist); 118int perf_evlist__start_workload(struct perf_evlist *evlist);
109 119
120struct option;
121
110int perf_evlist__parse_mmap_pages(const struct option *opt, 122int perf_evlist__parse_mmap_pages(const struct option *opt,
111 const char *str, 123 const char *str,
112 int unset); 124 int unset);
@@ -122,6 +134,8 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
122 struct perf_evsel *evsel); 134 struct perf_evsel *evsel);
123int perf_evlist__enable_event(struct perf_evlist *evlist, 135int perf_evlist__enable_event(struct perf_evlist *evlist,
124 struct perf_evsel *evsel); 136 struct perf_evsel *evsel);
137int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
138 struct perf_evsel *evsel, int idx);
125 139
126void perf_evlist__set_selected(struct perf_evlist *evlist, 140void perf_evlist__set_selected(struct perf_evlist *evlist,
127 struct perf_evsel *evsel); 141 struct perf_evsel *evsel);
@@ -262,4 +276,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
262#define evlist__for_each_safe(evlist, tmp, evsel) \ 276#define evlist__for_each_safe(evlist, tmp, evsel) \
263 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) 277 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel)
264 278
279void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
280 struct perf_evsel *tracking_evsel);
281
265#endif /* __PERF_EVLIST_H */ 282#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21a373ebea22..2f9e68025ede 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,6 +15,8 @@
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
16#include <sys/resource.h> 16#include <sys/resource.h>
17#include "asm/bug.h" 17#include "asm/bug.h"
18#include "callchain.h"
19#include "cgroup.h"
18#include "evsel.h" 20#include "evsel.h"
19#include "evlist.h" 21#include "evlist.h"
20#include "util.h" 22#include "util.h"
@@ -32,6 +34,48 @@ static struct {
32 bool cloexec; 34 bool cloexec;
33} perf_missing_features; 35} perf_missing_features;
34 36
37static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
38{
39 return 0;
40}
41
42static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused)
43{
44}
45
46static struct {
47 size_t size;
48 int (*init)(struct perf_evsel *evsel);
49 void (*fini)(struct perf_evsel *evsel);
50} perf_evsel__object = {
51 .size = sizeof(struct perf_evsel),
52 .init = perf_evsel__no_extra_init,
53 .fini = perf_evsel__no_extra_fini,
54};
55
56int perf_evsel__object_config(size_t object_size,
57 int (*init)(struct perf_evsel *evsel),
58 void (*fini)(struct perf_evsel *evsel))
59{
60
61 if (object_size == 0)
62 goto set_methods;
63
64 if (perf_evsel__object.size > object_size)
65 return -EINVAL;
66
67 perf_evsel__object.size = object_size;
68
69set_methods:
70 if (init != NULL)
71 perf_evsel__object.init = init;
72
73 if (fini != NULL)
74 perf_evsel__object.fini = fini;
75
76 return 0;
77}
78
35#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 79#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
36 80
37int __perf_evsel__sample_size(u64 sample_type) 81int __perf_evsel__sample_size(u64 sample_type)
@@ -116,16 +160,6 @@ void perf_evsel__calc_id_pos(struct perf_evsel *evsel)
116 evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type); 160 evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type);
117} 161}
118 162
119void hists__init(struct hists *hists)
120{
121 memset(hists, 0, sizeof(*hists));
122 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
123 hists->entries_in = &hists->entries_in_array[0];
124 hists->entries_collapsed = RB_ROOT;
125 hists->entries = RB_ROOT;
126 pthread_mutex_init(&hists->lock, NULL);
127}
128
129void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, 163void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
130 enum perf_event_sample_format bit) 164 enum perf_event_sample_format bit)
131{ 165{
@@ -162,19 +196,20 @@ void perf_evsel__init(struct perf_evsel *evsel,
162 struct perf_event_attr *attr, int idx) 196 struct perf_event_attr *attr, int idx)
163{ 197{
164 evsel->idx = idx; 198 evsel->idx = idx;
199 evsel->tracking = !idx;
165 evsel->attr = *attr; 200 evsel->attr = *attr;
166 evsel->leader = evsel; 201 evsel->leader = evsel;
167 evsel->unit = ""; 202 evsel->unit = "";
168 evsel->scale = 1.0; 203 evsel->scale = 1.0;
169 INIT_LIST_HEAD(&evsel->node); 204 INIT_LIST_HEAD(&evsel->node);
170 hists__init(&evsel->hists); 205 perf_evsel__object.init(evsel);
171 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); 206 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
172 perf_evsel__calc_id_pos(evsel); 207 perf_evsel__calc_id_pos(evsel);
173} 208}
174 209
175struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) 210struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
176{ 211{
177 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 212 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
178 213
179 if (evsel != NULL) 214 if (evsel != NULL)
180 perf_evsel__init(evsel, attr, idx); 215 perf_evsel__init(evsel, attr, idx);
@@ -184,7 +219,7 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
184 219
185struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) 220struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
186{ 221{
187 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 222 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
188 223
189 if (evsel != NULL) { 224 if (evsel != NULL) {
190 struct perf_event_attr attr = { 225 struct perf_event_attr attr = {
@@ -502,20 +537,19 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
502} 537}
503 538
504static void 539static void
505perf_evsel__config_callgraph(struct perf_evsel *evsel, 540perf_evsel__config_callgraph(struct perf_evsel *evsel)
506 struct record_opts *opts)
507{ 541{
508 bool function = perf_evsel__is_function_event(evsel); 542 bool function = perf_evsel__is_function_event(evsel);
509 struct perf_event_attr *attr = &evsel->attr; 543 struct perf_event_attr *attr = &evsel->attr;
510 544
511 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 545 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
512 546
513 if (opts->call_graph == CALLCHAIN_DWARF) { 547 if (callchain_param.record_mode == CALLCHAIN_DWARF) {
514 if (!function) { 548 if (!function) {
515 perf_evsel__set_sample_bit(evsel, REGS_USER); 549 perf_evsel__set_sample_bit(evsel, REGS_USER);
516 perf_evsel__set_sample_bit(evsel, STACK_USER); 550 perf_evsel__set_sample_bit(evsel, STACK_USER);
517 attr->sample_regs_user = PERF_REGS_MASK; 551 attr->sample_regs_user = PERF_REGS_MASK;
518 attr->sample_stack_user = opts->stack_dump_size; 552 attr->sample_stack_user = callchain_param.dump_size;
519 attr->exclude_callchain_user = 1; 553 attr->exclude_callchain_user = 1;
520 } else { 554 } else {
521 pr_info("Cannot use DWARF unwind for function trace event," 555 pr_info("Cannot use DWARF unwind for function trace event,"
@@ -561,7 +595,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
561{ 595{
562 struct perf_evsel *leader = evsel->leader; 596 struct perf_evsel *leader = evsel->leader;
563 struct perf_event_attr *attr = &evsel->attr; 597 struct perf_event_attr *attr = &evsel->attr;
564 int track = !evsel->idx; /* only the first counter needs these */ 598 int track = evsel->tracking;
565 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; 599 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
566 600
567 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 601 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
@@ -624,8 +658,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
624 attr->mmap_data = track; 658 attr->mmap_data = track;
625 } 659 }
626 660
627 if (opts->call_graph_enabled && !evsel->no_aux_samples) 661 if (callchain_param.enabled && !evsel->no_aux_samples)
628 perf_evsel__config_callgraph(evsel, opts); 662 perf_evsel__config_callgraph(evsel);
629 663
630 if (target__has_cpu(&opts->target)) 664 if (target__has_cpu(&opts->target))
631 perf_evsel__set_sample_bit(evsel, CPU); 665 perf_evsel__set_sample_bit(evsel, CPU);
@@ -633,9 +667,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
633 if (opts->period) 667 if (opts->period)
634 perf_evsel__set_sample_bit(evsel, PERIOD); 668 perf_evsel__set_sample_bit(evsel, PERIOD);
635 669
636 if (!perf_missing_features.sample_id_all && 670 /*
637 (opts->sample_time || !opts->no_inherit || 671 * When the user explicitely disabled time don't force it here.
638 target__has_cpu(&opts->target) || per_cpu)) 672 */
673 if (opts->sample_time &&
674 (!perf_missing_features.sample_id_all &&
675 (!opts->no_inherit || target__has_cpu(&opts->target) || per_cpu)))
639 perf_evsel__set_sample_bit(evsel, TIME); 676 perf_evsel__set_sample_bit(evsel, TIME);
640 677
641 if (opts->raw_samples && !evsel->no_aux_samples) { 678 if (opts->raw_samples && !evsel->no_aux_samples) {
@@ -689,9 +726,13 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
689 } 726 }
690} 727}
691 728
692int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 729static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
693{ 730{
694 int cpu, thread; 731 int cpu, thread;
732
733 if (evsel->system_wide)
734 nthreads = 1;
735
695 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 736 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
696 737
697 if (evsel->fd) { 738 if (evsel->fd) {
@@ -710,6 +751,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea
710{ 751{
711 int cpu, thread; 752 int cpu, thread;
712 753
754 if (evsel->system_wide)
755 nthreads = 1;
756
713 for (cpu = 0; cpu < ncpus; cpu++) { 757 for (cpu = 0; cpu < ncpus; cpu++) {
714 for (thread = 0; thread < nthreads; thread++) { 758 for (thread = 0; thread < nthreads; thread++) {
715 int fd = FD(evsel, cpu, thread), 759 int fd = FD(evsel, cpu, thread),
@@ -740,6 +784,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
740 784
741int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 785int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
742{ 786{
787 if (evsel->system_wide)
788 nthreads = 1;
789
743 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 790 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
744 if (evsel->sample_id == NULL) 791 if (evsel->sample_id == NULL)
745 return -ENOMEM; 792 return -ENOMEM;
@@ -767,13 +814,13 @@ int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
767 return evsel->counts != NULL ? 0 : -ENOMEM; 814 return evsel->counts != NULL ? 0 : -ENOMEM;
768} 815}
769 816
770void perf_evsel__free_fd(struct perf_evsel *evsel) 817static void perf_evsel__free_fd(struct perf_evsel *evsel)
771{ 818{
772 xyarray__delete(evsel->fd); 819 xyarray__delete(evsel->fd);
773 evsel->fd = NULL; 820 evsel->fd = NULL;
774} 821}
775 822
776void perf_evsel__free_id(struct perf_evsel *evsel) 823static void perf_evsel__free_id(struct perf_evsel *evsel)
777{ 824{
778 xyarray__delete(evsel->sample_id); 825 xyarray__delete(evsel->sample_id);
779 evsel->sample_id = NULL; 826 evsel->sample_id = NULL;
@@ -784,6 +831,9 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
784{ 831{
785 int cpu, thread; 832 int cpu, thread;
786 833
834 if (evsel->system_wide)
835 nthreads = 1;
836
787 for (cpu = 0; cpu < ncpus; cpu++) 837 for (cpu = 0; cpu < ncpus; cpu++)
788 for (thread = 0; thread < nthreads; ++thread) { 838 for (thread = 0; thread < nthreads; ++thread) {
789 close(FD(evsel, cpu, thread)); 839 close(FD(evsel, cpu, thread));
@@ -801,16 +851,17 @@ void perf_evsel__exit(struct perf_evsel *evsel)
801 assert(list_empty(&evsel->node)); 851 assert(list_empty(&evsel->node));
802 perf_evsel__free_fd(evsel); 852 perf_evsel__free_fd(evsel);
803 perf_evsel__free_id(evsel); 853 perf_evsel__free_id(evsel);
804}
805
806void perf_evsel__delete(struct perf_evsel *evsel)
807{
808 perf_evsel__exit(evsel);
809 close_cgroup(evsel->cgrp); 854 close_cgroup(evsel->cgrp);
810 zfree(&evsel->group_name); 855 zfree(&evsel->group_name);
811 if (evsel->tp_format) 856 if (evsel->tp_format)
812 pevent_free_format(evsel->tp_format); 857 pevent_free_format(evsel->tp_format);
813 zfree(&evsel->name); 858 zfree(&evsel->name);
859 perf_evsel__object.fini(evsel);
860}
861
862void perf_evsel__delete(struct perf_evsel *evsel)
863{
864 perf_evsel__exit(evsel);
814 free(evsel); 865 free(evsel);
815} 866}
816 867
@@ -872,6 +923,9 @@ int __perf_evsel__read(struct perf_evsel *evsel,
872 int cpu, thread; 923 int cpu, thread;
873 struct perf_counts_values *aggr = &evsel->counts->aggr, count; 924 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
874 925
926 if (evsel->system_wide)
927 nthreads = 1;
928
875 aggr->val = aggr->ena = aggr->run = 0; 929 aggr->val = aggr->ena = aggr->run = 0;
876 930
877 for (cpu = 0; cpu < ncpus; cpu++) { 931 for (cpu = 0; cpu < ncpus; cpu++) {
@@ -994,13 +1048,18 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
994static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1048static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
995 struct thread_map *threads) 1049 struct thread_map *threads)
996{ 1050{
997 int cpu, thread; 1051 int cpu, thread, nthreads;
998 unsigned long flags = PERF_FLAG_FD_CLOEXEC; 1052 unsigned long flags = PERF_FLAG_FD_CLOEXEC;
999 int pid = -1, err; 1053 int pid = -1, err;
1000 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; 1054 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
1001 1055
1056 if (evsel->system_wide)
1057 nthreads = 1;
1058 else
1059 nthreads = threads->nr;
1060
1002 if (evsel->fd == NULL && 1061 if (evsel->fd == NULL &&
1003 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 1062 perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0)
1004 return -ENOMEM; 1063 return -ENOMEM;
1005 1064
1006 if (evsel->cgrp) { 1065 if (evsel->cgrp) {
@@ -1024,10 +1083,10 @@ retry_sample_id:
1024 1083
1025 for (cpu = 0; cpu < cpus->nr; cpu++) { 1084 for (cpu = 0; cpu < cpus->nr; cpu++) {
1026 1085
1027 for (thread = 0; thread < threads->nr; thread++) { 1086 for (thread = 0; thread < nthreads; thread++) {
1028 int group_fd; 1087 int group_fd;
1029 1088
1030 if (!evsel->cgrp) 1089 if (!evsel->cgrp && !evsel->system_wide)
1031 pid = threads->map[thread]; 1090 pid = threads->map[thread];
1032 1091
1033 group_fd = get_group_fd(evsel, cpu, thread); 1092 group_fd = get_group_fd(evsel, cpu, thread);
@@ -1100,7 +1159,7 @@ out_close:
1100 close(FD(evsel, cpu, thread)); 1159 close(FD(evsel, cpu, thread));
1101 FD(evsel, cpu, thread) = -1; 1160 FD(evsel, cpu, thread) = -1;
1102 } 1161 }
1103 thread = threads->nr; 1162 thread = nthreads;
1104 } while (--cpu >= 0); 1163 } while (--cpu >= 0);
1105 return err; 1164 return err;
1106} 1165}
@@ -2002,6 +2061,8 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2002int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 2061int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2003 int err, char *msg, size_t size) 2062 int err, char *msg, size_t size)
2004{ 2063{
2064 char sbuf[STRERR_BUFSIZE];
2065
2005 switch (err) { 2066 switch (err) {
2006 case EPERM: 2067 case EPERM:
2007 case EACCES: 2068 case EACCES:
@@ -2036,13 +2097,20 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2036 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); 2097 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.");
2037#endif 2098#endif
2038 break; 2099 break;
2100 case EBUSY:
2101 if (find_process("oprofiled"))
2102 return scnprintf(msg, size,
2103 "The PMU counters are busy/taken by another profiler.\n"
2104 "We found oprofile daemon running, please stop it and try again.");
2105 break;
2039 default: 2106 default:
2040 break; 2107 break;
2041 } 2108 }
2042 2109
2043 return scnprintf(msg, size, 2110 return scnprintf(msg, size,
2044 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" 2111 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2045 "/bin/dmesg may provide additional information.\n" 2112 "/bin/dmesg may provide additional information.\n"
2046 "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2113 "No CONFIG_PERF_EVENTS=y kernel support configured?\n",
2047 err, strerror(err), perf_evsel__name(evsel)); 2114 err, strerror_r(err, sbuf, sizeof(sbuf)),
2115 perf_evsel__name(evsel));
2048} 2116}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d7f93ce0ebc1..163c5604e5d1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -7,8 +7,6 @@
7#include <linux/perf_event.h> 7#include <linux/perf_event.h>
8#include <linux/types.h> 8#include <linux/types.h>
9#include "xyarray.h" 9#include "xyarray.h"
10#include "cgroup.h"
11#include "hist.h"
12#include "symbol.h" 10#include "symbol.h"
13 11
14struct perf_counts_values { 12struct perf_counts_values {
@@ -43,6 +41,8 @@ struct perf_sample_id {
43 u64 period; 41 u64 period;
44}; 42};
45 43
44struct cgroup_sel;
45
46/** struct perf_evsel - event selector 46/** struct perf_evsel - event selector
47 * 47 *
48 * @name - Can be set to retain the original event name passed by the user, 48 * @name - Can be set to retain the original event name passed by the user,
@@ -66,7 +66,6 @@ struct perf_evsel {
66 struct perf_counts *prev_raw_counts; 66 struct perf_counts *prev_raw_counts;
67 int idx; 67 int idx;
68 u32 ids; 68 u32 ids;
69 struct hists hists;
70 char *name; 69 char *name;
71 double scale; 70 double scale;
72 const char *unit; 71 const char *unit;
@@ -85,6 +84,8 @@ struct perf_evsel {
85 bool needs_swap; 84 bool needs_swap;
86 bool no_aux_samples; 85 bool no_aux_samples;
87 bool immediate; 86 bool immediate;
87 bool system_wide;
88 bool tracking;
88 /* parse modifier helper */ 89 /* parse modifier helper */
89 int exclude_GH; 90 int exclude_GH;
90 int nr_members; 91 int nr_members;
@@ -98,13 +99,16 @@ union u64_swap {
98 u32 val32[2]; 99 u32 val32[2];
99}; 100};
100 101
101#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
102
103struct cpu_map; 102struct cpu_map;
103struct target;
104struct thread_map; 104struct thread_map;
105struct perf_evlist; 105struct perf_evlist;
106struct record_opts; 106struct record_opts;
107 107
108int perf_evsel__object_config(size_t object_size,
109 int (*init)(struct perf_evsel *evsel),
110 void (*fini)(struct perf_evsel *evsel));
111
108struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); 112struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
109 113
110static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) 114static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
@@ -151,12 +155,9 @@ const char *perf_evsel__name(struct perf_evsel *evsel);
151const char *perf_evsel__group_name(struct perf_evsel *evsel); 155const char *perf_evsel__group_name(struct perf_evsel *evsel);
152int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); 156int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
153 157
154int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
155int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 158int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
156int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); 159int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
157void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus); 160void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
158void perf_evsel__free_fd(struct perf_evsel *evsel);
159void perf_evsel__free_id(struct perf_evsel *evsel);
160void perf_evsel__free_counts(struct perf_evsel *evsel); 161void perf_evsel__free_counts(struct perf_evsel *evsel);
161void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 162void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
162 163
@@ -279,8 +280,6 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
279 return __perf_evsel__read(evsel, ncpus, nthreads, true); 280 return __perf_evsel__read(evsel, ncpus, nthreads, true);
280} 281}
281 282
282void hists__init(struct hists *hists);
283
284int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, 283int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
285 struct perf_sample *sample); 284 struct perf_sample *sample);
286 285
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 158c787ce0c4..26f5b2fe5dc8 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -214,11 +214,11 @@ static int machine__hit_all_dsos(struct machine *machine)
214{ 214{
215 int err; 215 int err;
216 216
217 err = __dsos__hit_all(&machine->kernel_dsos); 217 err = __dsos__hit_all(&machine->kernel_dsos.head);
218 if (err) 218 if (err)
219 return err; 219 return err;
220 220
221 return __dsos__hit_all(&machine->user_dsos); 221 return __dsos__hit_all(&machine->user_dsos.head);
222} 222}
223 223
224int dsos__hit_all(struct perf_session *session) 224int dsos__hit_all(struct perf_session *session)
@@ -288,11 +288,12 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
288 umisc = PERF_RECORD_MISC_GUEST_USER; 288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 } 289 }
290 290
291 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine, 291 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
292 machine->pid, kmisc, fd); 292 machine->pid, kmisc, fd);
293 if (err == 0) 293 if (err == 0)
294 err = __dsos__write_buildid_table(&machine->user_dsos, machine, 294 err = __dsos__write_buildid_table(&machine->user_dsos.head,
295 machine->pid, umisc, fd); 295 machine, machine->pid, umisc,
296 fd);
296 return err; 297 return err;
297} 298}
298 299
@@ -455,9 +456,10 @@ static int __dsos__cache_build_ids(struct list_head *head,
455 456
456static int machine__cache_build_ids(struct machine *machine, const char *debugdir) 457static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
457{ 458{
458 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine, 459 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
459 debugdir); 460 debugdir);
460 ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir); 461 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
462 debugdir);
461 return ret; 463 return ret;
462} 464}
463 465
@@ -483,8 +485,10 @@ static int perf_session__cache_build_ids(struct perf_session *session)
483 485
484static bool machine__read_build_ids(struct machine *machine, bool with_hits) 486static bool machine__read_build_ids(struct machine *machine, bool with_hits)
485{ 487{
486 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits); 488 bool ret;
487 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits); 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);
488 return ret; 492 return ret;
489} 493}
490 494
@@ -575,16 +579,12 @@ static int write_version(int fd, struct perf_header *h __maybe_unused,
575 return do_write_string(fd, perf_version_string); 579 return do_write_string(fd, perf_version_string);
576} 580}
577 581
578static int write_cpudesc(int fd, struct perf_header *h __maybe_unused, 582static int __write_cpudesc(int fd, const char *cpuinfo_proc)
579 struct perf_evlist *evlist __maybe_unused)
580{ 583{
581#ifndef CPUINFO_PROC
582#define CPUINFO_PROC NULL
583#endif
584 FILE *file; 584 FILE *file;
585 char *buf = NULL; 585 char *buf = NULL;
586 char *s, *p; 586 char *s, *p;
587 const char *search = CPUINFO_PROC; 587 const char *search = cpuinfo_proc;
588 size_t len = 0; 588 size_t len = 0;
589 int ret = -1; 589 int ret = -1;
590 590
@@ -634,6 +634,25 @@ done:
634 return ret; 634 return ret;
635} 635}
636 636
637static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
638 struct perf_evlist *evlist __maybe_unused)
639{
640#ifndef CPUINFO_PROC
641#define CPUINFO_PROC {"model name", }
642#endif
643 const char *cpuinfo_procs[] = CPUINFO_PROC;
644 unsigned int i;
645
646 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
647 int ret;
648 ret = __write_cpudesc(fd, cpuinfo_procs[i]);
649 if (ret >= 0)
650 return ret;
651 }
652 return -1;
653}
654
655
637static int write_nrcpus(int fd, struct perf_header *h __maybe_unused, 656static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
638 struct perf_evlist *evlist __maybe_unused) 657 struct perf_evlist *evlist __maybe_unused)
639{ 658{
@@ -1548,7 +1567,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1548 struct perf_session *session) 1567 struct perf_session *session)
1549{ 1568{
1550 int err = -1; 1569 int err = -1;
1551 struct list_head *head; 1570 struct dsos *dsos;
1552 struct machine *machine; 1571 struct machine *machine;
1553 u16 misc; 1572 u16 misc;
1554 struct dso *dso; 1573 struct dso *dso;
@@ -1563,22 +1582,22 @@ static int __event_process_build_id(struct build_id_event *bev,
1563 switch (misc) { 1582 switch (misc) {
1564 case PERF_RECORD_MISC_KERNEL: 1583 case PERF_RECORD_MISC_KERNEL:
1565 dso_type = DSO_TYPE_KERNEL; 1584 dso_type = DSO_TYPE_KERNEL;
1566 head = &machine->kernel_dsos; 1585 dsos = &machine->kernel_dsos;
1567 break; 1586 break;
1568 case PERF_RECORD_MISC_GUEST_KERNEL: 1587 case PERF_RECORD_MISC_GUEST_KERNEL:
1569 dso_type = DSO_TYPE_GUEST_KERNEL; 1588 dso_type = DSO_TYPE_GUEST_KERNEL;
1570 head = &machine->kernel_dsos; 1589 dsos = &machine->kernel_dsos;
1571 break; 1590 break;
1572 case PERF_RECORD_MISC_USER: 1591 case PERF_RECORD_MISC_USER:
1573 case PERF_RECORD_MISC_GUEST_USER: 1592 case PERF_RECORD_MISC_GUEST_USER:
1574 dso_type = DSO_TYPE_USER; 1593 dso_type = DSO_TYPE_USER;
1575 head = &machine->user_dsos; 1594 dsos = &machine->user_dsos;
1576 break; 1595 break;
1577 default: 1596 default:
1578 goto out; 1597 goto out;
1579 } 1598 }
1580 1599
1581 dso = __dsos__findnew(head, filename); 1600 dso = __dsos__findnew(dsos, filename);
1582 if (dso != NULL) { 1601 if (dso != NULL) {
1583 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1602 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1584 1603
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 30df6187ee02..6e88b9e395df 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -3,6 +3,7 @@
3#include "hist.h" 3#include "hist.h"
4#include "session.h" 4#include "session.h"
5#include "sort.h" 5#include "sort.h"
6#include "evlist.h"
6#include "evsel.h" 7#include "evsel.h"
7#include "annotate.h" 8#include "annotate.h"
8#include <math.h> 9#include <math.h>
@@ -14,13 +15,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
14static bool hists__filter_entry_by_symbol(struct hists *hists, 15static bool hists__filter_entry_by_symbol(struct hists *hists,
15 struct hist_entry *he); 16 struct hist_entry *he);
16 17
17struct callchain_param callchain_param = {
18 .mode = CHAIN_GRAPH_REL,
19 .min_percent = 0.5,
20 .order = ORDER_CALLEE,
21 .key = CCKEY_FUNCTION
22};
23
24u16 hists__col_len(struct hists *hists, enum hist_column col) 18u16 hists__col_len(struct hists *hists, enum hist_column col)
25{ 19{
26 return hists->col_len[col]; 20 return hists->col_len[col];
@@ -277,6 +271,28 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
277 } 271 }
278} 272}
279 273
274void hists__delete_entries(struct hists *hists)
275{
276 struct rb_node *next = rb_first(&hists->entries);
277 struct hist_entry *n;
278
279 while (next) {
280 n = rb_entry(next, struct hist_entry, rb_node);
281 next = rb_next(&n->rb_node);
282
283 rb_erase(&n->rb_node, &hists->entries);
284
285 if (sort__need_collapse)
286 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
287
288 --hists->nr_entries;
289 if (!n->filtered)
290 --hists->nr_non_filtered_entries;
291
292 hist_entry__free(n);
293 }
294}
295
280/* 296/*
281 * histogram, sorted on item, collects periods 297 * histogram, sorted on item, collects periods
282 */ 298 */
@@ -494,6 +510,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
494{ 510{
495 u64 cost; 511 u64 cost;
496 struct mem_info *mi = iter->priv; 512 struct mem_info *mi = iter->priv;
513 struct hists *hists = evsel__hists(iter->evsel);
497 struct hist_entry *he; 514 struct hist_entry *he;
498 515
499 if (mi == NULL) 516 if (mi == NULL)
@@ -510,7 +527,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
510 * and this is indirectly achieved by passing period=weight here 527 * and this is indirectly achieved by passing period=weight here
511 * and the he_stat__add_period() function. 528 * and the he_stat__add_period() function.
512 */ 529 */
513 he = __hists__add_entry(&iter->evsel->hists, al, iter->parent, NULL, mi, 530 he = __hists__add_entry(hists, al, iter->parent, NULL, mi,
514 cost, cost, 0, true); 531 cost, cost, 0, true);
515 if (!he) 532 if (!he)
516 return -ENOMEM; 533 return -ENOMEM;
@@ -524,13 +541,14 @@ iter_finish_mem_entry(struct hist_entry_iter *iter,
524 struct addr_location *al __maybe_unused) 541 struct addr_location *al __maybe_unused)
525{ 542{
526 struct perf_evsel *evsel = iter->evsel; 543 struct perf_evsel *evsel = iter->evsel;
544 struct hists *hists = evsel__hists(evsel);
527 struct hist_entry *he = iter->he; 545 struct hist_entry *he = iter->he;
528 int err = -EINVAL; 546 int err = -EINVAL;
529 547
530 if (he == NULL) 548 if (he == NULL)
531 goto out; 549 goto out;
532 550
533 hists__inc_nr_samples(&evsel->hists, he->filtered); 551 hists__inc_nr_samples(hists, he->filtered);
534 552
535 err = hist_entry__append_callchain(he, iter->sample); 553 err = hist_entry__append_callchain(he, iter->sample);
536 554
@@ -596,6 +614,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
596{ 614{
597 struct branch_info *bi; 615 struct branch_info *bi;
598 struct perf_evsel *evsel = iter->evsel; 616 struct perf_evsel *evsel = iter->evsel;
617 struct hists *hists = evsel__hists(evsel);
599 struct hist_entry *he = NULL; 618 struct hist_entry *he = NULL;
600 int i = iter->curr; 619 int i = iter->curr;
601 int err = 0; 620 int err = 0;
@@ -609,12 +628,12 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
609 * The report shows the percentage of total branches captured 628 * The report shows the percentage of total branches captured
610 * and not events sampled. Thus we use a pseudo period of 1. 629 * and not events sampled. Thus we use a pseudo period of 1.
611 */ 630 */
612 he = __hists__add_entry(&evsel->hists, al, iter->parent, &bi[i], NULL, 631 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
613 1, 1, 0, true); 632 1, 1, 0, true);
614 if (he == NULL) 633 if (he == NULL)
615 return -ENOMEM; 634 return -ENOMEM;
616 635
617 hists__inc_nr_samples(&evsel->hists, he->filtered); 636 hists__inc_nr_samples(hists, he->filtered);
618 637
619out: 638out:
620 iter->he = he; 639 iter->he = he;
@@ -646,7 +665,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
646 struct perf_sample *sample = iter->sample; 665 struct perf_sample *sample = iter->sample;
647 struct hist_entry *he; 666 struct hist_entry *he;
648 667
649 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 668 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
650 sample->period, sample->weight, 669 sample->period, sample->weight,
651 sample->transaction, true); 670 sample->transaction, true);
652 if (he == NULL) 671 if (he == NULL)
@@ -669,7 +688,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter,
669 688
670 iter->he = NULL; 689 iter->he = NULL;
671 690
672 hists__inc_nr_samples(&evsel->hists, he->filtered); 691 hists__inc_nr_samples(evsel__hists(evsel), he->filtered);
673 692
674 return hist_entry__append_callchain(he, sample); 693 return hist_entry__append_callchain(he, sample);
675} 694}
@@ -702,12 +721,13 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
702 struct addr_location *al) 721 struct addr_location *al)
703{ 722{
704 struct perf_evsel *evsel = iter->evsel; 723 struct perf_evsel *evsel = iter->evsel;
724 struct hists *hists = evsel__hists(evsel);
705 struct perf_sample *sample = iter->sample; 725 struct perf_sample *sample = iter->sample;
706 struct hist_entry **he_cache = iter->priv; 726 struct hist_entry **he_cache = iter->priv;
707 struct hist_entry *he; 727 struct hist_entry *he;
708 int err = 0; 728 int err = 0;
709 729
710 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 730 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL,
711 sample->period, sample->weight, 731 sample->period, sample->weight,
712 sample->transaction, true); 732 sample->transaction, true);
713 if (he == NULL) 733 if (he == NULL)
@@ -724,7 +744,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
724 */ 744 */
725 callchain_cursor_commit(&callchain_cursor); 745 callchain_cursor_commit(&callchain_cursor);
726 746
727 hists__inc_nr_samples(&evsel->hists, he->filtered); 747 hists__inc_nr_samples(hists, he->filtered);
728 748
729 return err; 749 return err;
730} 750}
@@ -780,7 +800,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
780 } 800 }
781 } 801 }
782 802
783 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 803 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
784 sample->period, sample->weight, 804 sample->period, sample->weight,
785 sample->transaction, false); 805 sample->transaction, false);
786 if (he == NULL) 806 if (he == NULL)
@@ -1386,6 +1406,21 @@ int hists__link(struct hists *leader, struct hists *other)
1386 return 0; 1406 return 0;
1387} 1407}
1388 1408
1409
1410size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp)
1411{
1412 struct perf_evsel *pos;
1413 size_t ret = 0;
1414
1415 evlist__for_each(evlist, pos) {
1416 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1417 ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp);
1418 }
1419
1420 return ret;
1421}
1422
1423
1389u64 hists__total_period(struct hists *hists) 1424u64 hists__total_period(struct hists *hists)
1390{ 1425{
1391 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period : 1426 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
@@ -1412,3 +1447,31 @@ int perf_hist_config(const char *var, const char *value)
1412 1447
1413 return 0; 1448 return 0;
1414} 1449}
1450
1451static int hists_evsel__init(struct perf_evsel *evsel)
1452{
1453 struct hists *hists = evsel__hists(evsel);
1454
1455 memset(hists, 0, sizeof(*hists));
1456 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
1457 hists->entries_in = &hists->entries_in_array[0];
1458 hists->entries_collapsed = RB_ROOT;
1459 hists->entries = RB_ROOT;
1460 pthread_mutex_init(&hists->lock, NULL);
1461 return 0;
1462}
1463
1464/*
1465 * XXX We probably need a hists_evsel__exit() to free the hist_entries
1466 * stored in the rbtree...
1467 */
1468
1469int hists__init(void)
1470{
1471 int err = perf_evsel__object_config(sizeof(struct hists_evsel),
1472 hists_evsel__init, NULL);
1473 if (err)
1474 fputs("FATAL ERROR: Couldn't setup hists class\n", stderr);
1475
1476 return err;
1477}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 742f49a85725..d0ef9a19a744 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -4,12 +4,11 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include <pthread.h> 5#include <pthread.h>
6#include "callchain.h" 6#include "callchain.h"
7#include "evsel.h"
7#include "header.h" 8#include "header.h"
8#include "color.h" 9#include "color.h"
9#include "ui/progress.h" 10#include "ui/progress.h"
10 11
11extern struct callchain_param callchain_param;
12
13struct hist_entry; 12struct hist_entry;
14struct addr_location; 13struct addr_location;
15struct symbol; 14struct symbol;
@@ -23,32 +22,6 @@ enum hist_filter {
23 HIST_FILTER__HOST, 22 HIST_FILTER__HOST,
24}; 23};
25 24
26/*
27 * The kernel collects the number of events it couldn't send in a stretch and
28 * when possible sends this number in a PERF_RECORD_LOST event. The number of
29 * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
30 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
31 * the sum of all struct lost_event.lost fields reported.
32 *
33 * The total_period is needed because by default auto-freq is used, so
34 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
35 * the total number of low level events, it is necessary to to sum all struct
36 * sample_event.period and stash the result in total_period.
37 */
38struct events_stats {
39 u64 total_period;
40 u64 total_non_filtered_period;
41 u64 total_lost;
42 u64 total_invalid_chains;
43 u32 nr_events[PERF_RECORD_HEADER_MAX];
44 u32 nr_non_filtered_samples;
45 u32 nr_lost_warned;
46 u32 nr_unknown_events;
47 u32 nr_invalid_chains;
48 u32 nr_unknown_id;
49 u32 nr_unprocessable_samples;
50};
51
52enum hist_column { 25enum hist_column {
53 HISTC_SYMBOL, 26 HISTC_SYMBOL,
54 HISTC_DSO, 27 HISTC_DSO,
@@ -152,6 +125,7 @@ void hists__output_resort(struct hists *hists);
152void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 125void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
153 126
154void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 127void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
128void hists__delete_entries(struct hists *hists);
155void hists__output_recalc_col_len(struct hists *hists, int max_rows); 129void hists__output_recalc_col_len(struct hists *hists, int max_rows);
156 130
157u64 hists__total_period(struct hists *hists); 131u64 hists__total_period(struct hists *hists);
@@ -164,6 +138,7 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
164 138
165size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 139size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
166 int max_cols, float min_pcnt, FILE *fp); 140 int max_cols, float min_pcnt, FILE *fp);
141size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp);
167 142
168void hists__filter_by_dso(struct hists *hists); 143void hists__filter_by_dso(struct hists *hists);
169void hists__filter_by_thread(struct hists *hists); 144void hists__filter_by_thread(struct hists *hists);
@@ -184,6 +159,25 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
184void hists__match(struct hists *leader, struct hists *other); 159void hists__match(struct hists *leader, struct hists *other);
185int hists__link(struct hists *leader, struct hists *other); 160int hists__link(struct hists *leader, struct hists *other);
186 161
162struct hists_evsel {
163 struct perf_evsel evsel;
164 struct hists hists;
165};
166
167static inline struct perf_evsel *hists_to_evsel(struct hists *hists)
168{
169 struct hists_evsel *hevsel = container_of(hists, struct hists_evsel, hists);
170 return &hevsel->evsel;
171}
172
173static inline struct hists *evsel__hists(struct perf_evsel *evsel)
174{
175 struct hists_evsel *hevsel = (struct hists_evsel *)evsel;
176 return &hevsel->hists;
177}
178
179int hists__init(void);
180
187struct perf_hpp { 181struct perf_hpp {
188 char *buf; 182 char *buf;
189 size_t size; 183 size_t size;
@@ -192,6 +186,7 @@ struct perf_hpp {
192}; 186};
193 187
194struct perf_hpp_fmt { 188struct perf_hpp_fmt {
189 const char *name;
195 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 190 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
196 struct perf_evsel *evsel); 191 struct perf_evsel *evsel);
197 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 192 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -207,6 +202,8 @@ struct perf_hpp_fmt {
207 struct list_head list; 202 struct list_head list;
208 struct list_head sort_list; 203 struct list_head sort_list;
209 bool elide; 204 bool elide;
205 int len;
206 int user_len;
210}; 207};
211 208
212extern struct list_head perf_hpp__list; 209extern struct list_head perf_hpp__list;
@@ -261,17 +258,19 @@ static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format)
261} 258}
262 259
263void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 260void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
261void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists);
262void perf_hpp__set_user_width(const char *width_list_str);
264 263
265typedef u64 (*hpp_field_fn)(struct hist_entry *he); 264typedef u64 (*hpp_field_fn)(struct hist_entry *he);
266typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); 265typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
267typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...); 266typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...);
268 267
269int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 268int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
270 hpp_field_fn get_field, const char *fmt, 269 struct hist_entry *he, hpp_field_fn get_field,
271 hpp_snprint_fn print_fn, bool fmt_percent); 270 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
272int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 271int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
273 hpp_field_fn get_field, const char *fmt, 272 struct hist_entry *he, hpp_field_fn get_field,
274 hpp_snprint_fn print_fn, bool fmt_percent); 273 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
275 274
276static inline void advance_hpp(struct perf_hpp *hpp, int inc) 275static inline void advance_hpp(struct perf_hpp *hpp, int inc)
277{ 276{
diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h
index 97a800738226..6f19c548ecc0 100644
--- a/tools/perf/util/include/linux/string.h
+++ b/tools/perf/util/include/linux/string.h
@@ -1,4 +1,3 @@
1#include <string.h> 1#include <string.h>
2 2
3void *memdup(const void *src, size_t len); 3void *memdup(const void *src, size_t len);
4int str_append(char **s, int *len, const char *a);
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index 0b5a8cd2ee79..cf1d7913783b 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -92,7 +92,6 @@ struct perf_kvm_stat {
92 u64 lost_events; 92 u64 lost_events;
93 u64 duration; 93 u64 duration;
94 94
95 const char *pid_str;
96 struct intlist *pid_list; 95 struct intlist *pid_list;
97 96
98 struct rb_root result; 97 struct rb_root result;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 16bba9fff2c8..34fc7c8672e4 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -13,12 +13,18 @@
13#include <symbol/kallsyms.h> 13#include <symbol/kallsyms.h>
14#include "unwind.h" 14#include "unwind.h"
15 15
16static void dsos__init(struct dsos *dsos)
17{
18 INIT_LIST_HEAD(&dsos->head);
19 dsos->root = RB_ROOT;
20}
21
16int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 22int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
17{ 23{
18 map_groups__init(&machine->kmaps); 24 map_groups__init(&machine->kmaps);
19 RB_CLEAR_NODE(&machine->rb_node); 25 RB_CLEAR_NODE(&machine->rb_node);
20 INIT_LIST_HEAD(&machine->user_dsos); 26 dsos__init(&machine->user_dsos);
21 INIT_LIST_HEAD(&machine->kernel_dsos); 27 dsos__init(&machine->kernel_dsos);
22 28
23 machine->threads = RB_ROOT; 29 machine->threads = RB_ROOT;
24 INIT_LIST_HEAD(&machine->dead_threads); 30 INIT_LIST_HEAD(&machine->dead_threads);
@@ -31,6 +37,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
31 37
32 machine->symbol_filter = NULL; 38 machine->symbol_filter = NULL;
33 machine->id_hdr_size = 0; 39 machine->id_hdr_size = 0;
40 machine->comm_exec = false;
41 machine->kernel_start = 0;
34 42
35 machine->root_dir = strdup(root_dir); 43 machine->root_dir = strdup(root_dir);
36 if (machine->root_dir == NULL) 44 if (machine->root_dir == NULL)
@@ -70,11 +78,12 @@ out_delete:
70 return NULL; 78 return NULL;
71} 79}
72 80
73static void dsos__delete(struct list_head *dsos) 81static void dsos__delete(struct dsos *dsos)
74{ 82{
75 struct dso *pos, *n; 83 struct dso *pos, *n;
76 84
77 list_for_each_entry_safe(pos, n, dsos, node) { 85 list_for_each_entry_safe(pos, n, &dsos->head, node) {
86 RB_CLEAR_NODE(&pos->rb_node);
78 list_del(&pos->node); 87 list_del(&pos->node);
79 dso__delete(pos); 88 dso__delete(pos);
80 } 89 }
@@ -179,6 +188,19 @@ void machines__set_symbol_filter(struct machines *machines,
179 } 188 }
180} 189}
181 190
191void machines__set_comm_exec(struct machines *machines, bool comm_exec)
192{
193 struct rb_node *nd;
194
195 machines->host.comm_exec = comm_exec;
196
197 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
198 struct machine *machine = rb_entry(nd, struct machine, rb_node);
199
200 machine->comm_exec = comm_exec;
201 }
202}
203
182struct machine *machines__find(struct machines *machines, pid_t pid) 204struct machine *machines__find(struct machines *machines, pid_t pid)
183{ 205{
184 struct rb_node **p = &machines->guests.rb_node; 206 struct rb_node **p = &machines->guests.rb_node;
@@ -398,17 +420,31 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid,
398 return __machine__findnew_thread(machine, pid, tid, false); 420 return __machine__findnew_thread(machine, pid, tid, false);
399} 421}
400 422
423struct comm *machine__thread_exec_comm(struct machine *machine,
424 struct thread *thread)
425{
426 if (machine->comm_exec)
427 return thread__exec_comm(thread);
428 else
429 return thread__comm(thread);
430}
431
401int machine__process_comm_event(struct machine *machine, union perf_event *event, 432int machine__process_comm_event(struct machine *machine, union perf_event *event,
402 struct perf_sample *sample) 433 struct perf_sample *sample)
403{ 434{
404 struct thread *thread = machine__findnew_thread(machine, 435 struct thread *thread = machine__findnew_thread(machine,
405 event->comm.pid, 436 event->comm.pid,
406 event->comm.tid); 437 event->comm.tid);
438 bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC;
439
440 if (exec)
441 machine->comm_exec = true;
407 442
408 if (dump_trace) 443 if (dump_trace)
409 perf_event__fprintf_comm(event, stdout); 444 perf_event__fprintf_comm(event, stdout);
410 445
411 if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) { 446 if (thread == NULL ||
447 __thread__set_comm(thread, event->comm.comm, sample->time, exec)) {
412 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 448 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
413 return -1; 449 return -1;
414 } 450 }
@@ -448,23 +484,23 @@ struct map *machine__new_module(struct machine *machine, u64 start,
448size_t machines__fprintf_dsos(struct machines *machines, FILE *fp) 484size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
449{ 485{
450 struct rb_node *nd; 486 struct rb_node *nd;
451 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos, fp) + 487 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos.head, fp) +
452 __dsos__fprintf(&machines->host.user_dsos, fp); 488 __dsos__fprintf(&machines->host.user_dsos.head, fp);
453 489
454 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 490 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
455 struct machine *pos = rb_entry(nd, struct machine, rb_node); 491 struct machine *pos = rb_entry(nd, struct machine, rb_node);
456 ret += __dsos__fprintf(&pos->kernel_dsos, fp); 492 ret += __dsos__fprintf(&pos->kernel_dsos.head, fp);
457 ret += __dsos__fprintf(&pos->user_dsos, fp); 493 ret += __dsos__fprintf(&pos->user_dsos.head, fp);
458 } 494 }
459 495
460 return ret; 496 return ret;
461} 497}
462 498
463size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 499size_t machine__fprintf_dsos_buildid(struct machine *m, FILE *fp,
464 bool (skip)(struct dso *dso, int parm), int parm) 500 bool (skip)(struct dso *dso, int parm), int parm)
465{ 501{
466 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) + 502 return __dsos__fprintf_buildid(&m->kernel_dsos.head, fp, skip, parm) +
467 __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm); 503 __dsos__fprintf_buildid(&m->user_dsos.head, fp, skip, parm);
468} 504}
469 505
470size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp, 506size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
@@ -565,8 +601,8 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
565 * Returns the name of the start symbol in *symbol_name. Pass in NULL as 601 * Returns the name of the start symbol in *symbol_name. Pass in NULL as
566 * symbol_name if it's not that important. 602 * symbol_name if it's not that important.
567 */ 603 */
568static u64 machine__get_kernel_start_addr(struct machine *machine, 604static u64 machine__get_running_kernel_start(struct machine *machine,
569 const char **symbol_name) 605 const char **symbol_name)
570{ 606{
571 char filename[PATH_MAX]; 607 char filename[PATH_MAX];
572 int i; 608 int i;
@@ -593,7 +629,7 @@ static u64 machine__get_kernel_start_addr(struct machine *machine,
593int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 629int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
594{ 630{
595 enum map_type type; 631 enum map_type type;
596 u64 start = machine__get_kernel_start_addr(machine, NULL); 632 u64 start = machine__get_running_kernel_start(machine, NULL);
597 633
598 for (type = 0; type < MAP__NR_TYPES; ++type) { 634 for (type = 0; type < MAP__NR_TYPES; ++type) {
599 struct kmap *kmap; 635 struct kmap *kmap;
@@ -912,7 +948,7 @@ int machine__create_kernel_maps(struct machine *machine)
912{ 948{
913 struct dso *kernel = machine__get_kernel(machine); 949 struct dso *kernel = machine__get_kernel(machine);
914 const char *name; 950 const char *name;
915 u64 addr = machine__get_kernel_start_addr(machine, &name); 951 u64 addr = machine__get_running_kernel_start(machine, &name);
916 if (!addr) 952 if (!addr)
917 return -1; 953 return -1;
918 954
@@ -965,7 +1001,7 @@ static bool machine__uses_kcore(struct machine *machine)
965{ 1001{
966 struct dso *dso; 1002 struct dso *dso;
967 1003
968 list_for_each_entry(dso, &machine->kernel_dsos, node) { 1004 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
969 if (dso__is_kcore(dso)) 1005 if (dso__is_kcore(dso))
970 return true; 1006 return true;
971 } 1007 }
@@ -1285,6 +1321,16 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread,
1285 1321
1286 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, 1322 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr,
1287 &al); 1323 &al);
1324 if (al.map == NULL) {
1325 /*
1326 * some shared data regions have execute bit set which puts
1327 * their mapping in the MAP__FUNCTION type array.
1328 * Check there as a fallback option before dropping the sample.
1329 */
1330 thread__find_addr_location(thread, machine, m, MAP__FUNCTION, addr,
1331 &al);
1332 }
1333
1288 ams->addr = addr; 1334 ams->addr = addr;
1289 ams->al_addr = al.addr; 1335 ams->al_addr = al.addr;
1290 ams->sym = al.sym; 1336 ams->sym = al.sym;
@@ -1531,3 +1577,25 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
1531 1577
1532 return 0; 1578 return 0;
1533} 1579}
1580
1581int machine__get_kernel_start(struct machine *machine)
1582{
1583 struct map *map = machine__kernel_map(machine, MAP__FUNCTION);
1584 int err = 0;
1585
1586 /*
1587 * The only addresses above 2^63 are kernel addresses of a 64-bit
1588 * kernel. Note that addresses are unsigned so that on a 32-bit system
1589 * all addresses including kernel addresses are less than 2^32. In
1590 * that case (32-bit system), if the kernel mapping is unknown, all
1591 * addresses will be assumed to be in user space - see
1592 * machine__kernel_ip().
1593 */
1594 machine->kernel_start = 1ULL << 63;
1595 if (map) {
1596 err = map__load(map, machine->symbol_filter);
1597 if (map->start)
1598 machine->kernel_start = map->start;
1599 }
1600 return err;
1601}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index b972824e6294..2b651a7f5d0d 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -4,6 +4,7 @@
4#include <sys/types.h> 4#include <sys/types.h>
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include "map.h" 6#include "map.h"
7#include "dso.h"
7#include "event.h" 8#include "event.h"
8 9
9struct addr_location; 10struct addr_location;
@@ -26,15 +27,17 @@ struct machine {
26 struct rb_node rb_node; 27 struct rb_node rb_node;
27 pid_t pid; 28 pid_t pid;
28 u16 id_hdr_size; 29 u16 id_hdr_size;
30 bool comm_exec;
29 char *root_dir; 31 char *root_dir;
30 struct rb_root threads; 32 struct rb_root threads;
31 struct list_head dead_threads; 33 struct list_head dead_threads;
32 struct thread *last_match; 34 struct thread *last_match;
33 struct vdso_info *vdso_info; 35 struct vdso_info *vdso_info;
34 struct list_head user_dsos; 36 struct dsos user_dsos;
35 struct list_head kernel_dsos; 37 struct dsos kernel_dsos;
36 struct map_groups kmaps; 38 struct map_groups kmaps;
37 struct map *vmlinux_maps[MAP__NR_TYPES]; 39 struct map *vmlinux_maps[MAP__NR_TYPES];
40 u64 kernel_start;
38 symbol_filter_t symbol_filter; 41 symbol_filter_t symbol_filter;
39 pid_t *current_tid; 42 pid_t *current_tid;
40}; 43};
@@ -45,8 +48,26 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
45 return machine->vmlinux_maps[type]; 48 return machine->vmlinux_maps[type];
46} 49}
47 50
51int machine__get_kernel_start(struct machine *machine);
52
53static inline u64 machine__kernel_start(struct machine *machine)
54{
55 if (!machine->kernel_start)
56 machine__get_kernel_start(machine);
57 return machine->kernel_start;
58}
59
60static inline bool machine__kernel_ip(struct machine *machine, u64 ip)
61{
62 u64 kernel_start = machine__kernel_start(machine);
63
64 return ip >= kernel_start;
65}
66
48struct thread *machine__find_thread(struct machine *machine, pid_t pid, 67struct thread *machine__find_thread(struct machine *machine, pid_t pid,
49 pid_t tid); 68 pid_t tid);
69struct comm *machine__thread_exec_comm(struct machine *machine,
70 struct thread *thread);
50 71
51int machine__process_comm_event(struct machine *machine, union perf_event *event, 72int machine__process_comm_event(struct machine *machine, union perf_event *event,
52 struct perf_sample *sample); 73 struct perf_sample *sample);
@@ -88,6 +109,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
88 109
89void machines__set_symbol_filter(struct machines *machines, 110void machines__set_symbol_filter(struct machines *machines,
90 symbol_filter_t symbol_filter); 111 symbol_filter_t symbol_filter);
112void machines__set_comm_exec(struct machines *machines, bool comm_exec);
91 113
92struct machine *machine__new_host(void); 114struct machine *machine__new_host(void);
93int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 115int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 31b8905dd863..2137c4596ec7 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -31,6 +31,7 @@ static inline int is_anon_memory(const char *filename)
31static inline int is_no_dso_memory(const char *filename) 31static inline int is_no_dso_memory(const char *filename)
32{ 32{
33 return !strncmp(filename, "[stack", 6) || 33 return !strncmp(filename, "[stack", 6) ||
34 !strncmp(filename, "/SYSV",5) ||
34 !strcmp(filename, "[heap]"); 35 !strcmp(filename, "[heap]");
35} 36}
36 37
@@ -555,7 +556,7 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
555 556
556int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) 557int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
557{ 558{
558 if (ams->addr < ams->map->start || ams->addr > ams->map->end) { 559 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
559 if (ams->map->groups == NULL) 560 if (ams->map->groups == NULL)
560 return -1; 561 return -1;
561 ams->map = map_groups__find(ams->map->groups, ams->map->type, 562 ams->map = map_groups__find(ams->map->groups, ams->map->type,
@@ -663,7 +664,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
663 goto move_map; 664 goto move_map;
664 } 665 }
665 666
666 before->end = map->start - 1; 667 before->end = map->start;
667 map_groups__insert(mg, before); 668 map_groups__insert(mg, before);
668 if (verbose >= 2) 669 if (verbose >= 2)
669 map__fprintf(before, fp); 670 map__fprintf(before, fp);
@@ -677,7 +678,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
677 goto move_map; 678 goto move_map;
678 } 679 }
679 680
680 after->start = map->end + 1; 681 after->start = map->end;
681 map_groups__insert(mg, after); 682 map_groups__insert(mg, after);
682 if (verbose >= 2) 683 if (verbose >= 2)
683 map__fprintf(after, fp); 684 map__fprintf(after, fp);
@@ -751,7 +752,7 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
751 m = rb_entry(parent, struct map, rb_node); 752 m = rb_entry(parent, struct map, rb_node);
752 if (ip < m->start) 753 if (ip < m->start)
753 p = &(*p)->rb_left; 754 p = &(*p)->rb_left;
754 else if (ip > m->end) 755 else if (ip >= m->end)
755 p = &(*p)->rb_right; 756 p = &(*p)->rb_right;
756 else 757 else
757 return m; 758 return m;
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
new file mode 100644
index 000000000000..fd4be94125fb
--- /dev/null
+++ b/tools/perf/util/ordered-events.c
@@ -0,0 +1,286 @@
1#include <linux/list.h>
2#include <linux/compiler.h>
3#include <linux/string.h>
4#include "ordered-events.h"
5#include "evlist.h"
6#include "session.h"
7#include "asm/bug.h"
8#include "debug.h"
9
10#define pr_N(n, fmt, ...) \
11 eprintf(n, debug_ordered_events, fmt, ##__VA_ARGS__)
12
13#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
14
15static void queue_event(struct ordered_events *oe, struct ordered_event *new)
16{
17 struct ordered_event *last = oe->last;
18 u64 timestamp = new->timestamp;
19 struct list_head *p;
20
21 ++oe->nr_events;
22 oe->last = new;
23
24 pr_oe_time2(timestamp, "queue_event nr_events %u\n", oe->nr_events);
25
26 if (!last) {
27 list_add(&new->list, &oe->events);
28 oe->max_timestamp = timestamp;
29 return;
30 }
31
32 /*
33 * last event might point to some random place in the list as it's
34 * the last queued event. We expect that the new event is close to
35 * this.
36 */
37 if (last->timestamp <= timestamp) {
38 while (last->timestamp <= timestamp) {
39 p = last->list.next;
40 if (p == &oe->events) {
41 list_add_tail(&new->list, &oe->events);
42 oe->max_timestamp = timestamp;
43 return;
44 }
45 last = list_entry(p, struct ordered_event, list);
46 }
47 list_add_tail(&new->list, &last->list);
48 } else {
49 while (last->timestamp > timestamp) {
50 p = last->list.prev;
51 if (p == &oe->events) {
52 list_add(&new->list, &oe->events);
53 return;
54 }
55 last = list_entry(p, struct ordered_event, list);
56 }
57 list_add(&new->list, &last->list);
58 }
59}
60
61static union perf_event *__dup_event(struct ordered_events *oe,
62 union perf_event *event)
63{
64 union perf_event *new_event = NULL;
65
66 if (oe->cur_alloc_size < oe->max_alloc_size) {
67 new_event = memdup(event, event->header.size);
68 if (new_event)
69 oe->cur_alloc_size += event->header.size;
70 }
71
72 return new_event;
73}
74
75static union perf_event *dup_event(struct ordered_events *oe,
76 union perf_event *event)
77{
78 return oe->copy_on_queue ? __dup_event(oe, event) : event;
79}
80
81static void free_dup_event(struct ordered_events *oe, union perf_event *event)
82{
83 if (oe->copy_on_queue) {
84 oe->cur_alloc_size -= event->header.size;
85 free(event);
86 }
87}
88
89#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
90static struct ordered_event *alloc_event(struct ordered_events *oe,
91 union perf_event *event)
92{
93 struct list_head *cache = &oe->cache;
94 struct ordered_event *new = NULL;
95 union perf_event *new_event;
96
97 new_event = dup_event(oe, event);
98 if (!new_event)
99 return NULL;
100
101 if (!list_empty(cache)) {
102 new = list_entry(cache->next, struct ordered_event, list);
103 list_del(&new->list);
104 } else if (oe->buffer) {
105 new = oe->buffer + oe->buffer_idx;
106 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
107 oe->buffer = NULL;
108 } else if (oe->cur_alloc_size < oe->max_alloc_size) {
109 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
110
111 oe->buffer = malloc(size);
112 if (!oe->buffer) {
113 free_dup_event(oe, new_event);
114 return NULL;
115 }
116
117 pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n",
118 oe->cur_alloc_size, size, oe->max_alloc_size);
119
120 oe->cur_alloc_size += size;
121 list_add(&oe->buffer->list, &oe->to_free);
122
123 /* First entry is abused to maintain the to_free list. */
124 oe->buffer_idx = 2;
125 new = oe->buffer + 1;
126 } else {
127 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
128 }
129
130 new->event = new_event;
131 return new;
132}
133
134struct ordered_event *
135ordered_events__new(struct ordered_events *oe, u64 timestamp,
136 union perf_event *event)
137{
138 struct ordered_event *new;
139
140 new = alloc_event(oe, event);
141 if (new) {
142 new->timestamp = timestamp;
143 queue_event(oe, new);
144 }
145
146 return new;
147}
148
149void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event)
150{
151 list_move(&event->list, &oe->cache);
152 oe->nr_events--;
153 free_dup_event(oe, event->event);
154}
155
156static int __ordered_events__flush(struct perf_session *s,
157 struct perf_tool *tool)
158{
159 struct ordered_events *oe = &s->ordered_events;
160 struct list_head *head = &oe->events;
161 struct ordered_event *tmp, *iter;
162 struct perf_sample sample;
163 u64 limit = oe->next_flush;
164 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
165 bool show_progress = limit == ULLONG_MAX;
166 struct ui_progress prog;
167 int ret;
168
169 if (!tool->ordered_events || !limit)
170 return 0;
171
172 if (show_progress)
173 ui_progress__init(&prog, oe->nr_events, "Processing time ordered events...");
174
175 list_for_each_entry_safe(iter, tmp, head, list) {
176 if (session_done())
177 return 0;
178
179 if (iter->timestamp > limit)
180 break;
181
182 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
183 if (ret)
184 pr_err("Can't parse sample, err = %d\n", ret);
185 else {
186 ret = perf_session__deliver_event(s, iter->event, &sample, tool,
187 iter->file_offset);
188 if (ret)
189 return ret;
190 }
191
192 ordered_events__delete(oe, iter);
193 oe->last_flush = iter->timestamp;
194
195 if (show_progress)
196 ui_progress__update(&prog, 1);
197 }
198
199 if (list_empty(head))
200 oe->last = NULL;
201 else if (last_ts <= limit)
202 oe->last = list_entry(head->prev, struct ordered_event, list);
203
204 return 0;
205}
206
207int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
208 enum oe_flush how)
209{
210 struct ordered_events *oe = &s->ordered_events;
211 static const char * const str[] = {
212 "NONE",
213 "FINAL",
214 "ROUND",
215 "HALF ",
216 };
217 int err;
218
219 switch (how) {
220 case OE_FLUSH__FINAL:
221 oe->next_flush = ULLONG_MAX;
222 break;
223
224 case OE_FLUSH__HALF:
225 {
226 struct ordered_event *first, *last;
227 struct list_head *head = &oe->events;
228
229 first = list_entry(head->next, struct ordered_event, list);
230 last = oe->last;
231
232 /* Warn if we are called before any event got allocated. */
233 if (WARN_ONCE(!last || list_empty(head), "empty queue"))
234 return 0;
235
236 oe->next_flush = first->timestamp;
237 oe->next_flush += (last->timestamp - first->timestamp) / 2;
238 break;
239 }
240
241 case OE_FLUSH__ROUND:
242 case OE_FLUSH__NONE:
243 default:
244 break;
245 };
246
247 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush PRE %s, nr_events %u\n",
248 str[how], oe->nr_events);
249 pr_oe_time(oe->max_timestamp, "max_timestamp\n");
250
251 err = __ordered_events__flush(s, tool);
252
253 if (!err) {
254 if (how == OE_FLUSH__ROUND)
255 oe->next_flush = oe->max_timestamp;
256
257 oe->last_flush_type = how;
258 }
259
260 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush POST %s, nr_events %u\n",
261 str[how], oe->nr_events);
262 pr_oe_time(oe->last_flush, "last_flush\n");
263
264 return err;
265}
266
267void ordered_events__init(struct ordered_events *oe)
268{
269 INIT_LIST_HEAD(&oe->events);
270 INIT_LIST_HEAD(&oe->cache);
271 INIT_LIST_HEAD(&oe->to_free);
272 oe->max_alloc_size = (u64) -1;
273 oe->cur_alloc_size = 0;
274}
275
276void ordered_events__free(struct ordered_events *oe)
277{
278 while (!list_empty(&oe->to_free)) {
279 struct ordered_event *event;
280
281 event = list_entry(oe->to_free.next, struct ordered_event, list);
282 list_del(&event->list);
283 free_dup_event(oe, event->event);
284 free(event);
285 }
286}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
new file mode 100644
index 000000000000..7b8f9b011f38
--- /dev/null
+++ b/tools/perf/util/ordered-events.h
@@ -0,0 +1,59 @@
1#ifndef __ORDERED_EVENTS_H
2#define __ORDERED_EVENTS_H
3
4#include <linux/types.h>
5#include "tool.h"
6
7struct perf_session;
8
9struct ordered_event {
10 u64 timestamp;
11 u64 file_offset;
12 union perf_event *event;
13 struct list_head list;
14};
15
16enum oe_flush {
17 OE_FLUSH__NONE,
18 OE_FLUSH__FINAL,
19 OE_FLUSH__ROUND,
20 OE_FLUSH__HALF,
21};
22
23struct ordered_events {
24 u64 last_flush;
25 u64 next_flush;
26 u64 max_timestamp;
27 u64 max_alloc_size;
28 u64 cur_alloc_size;
29 struct list_head events;
30 struct list_head cache;
31 struct list_head to_free;
32 struct ordered_event *buffer;
33 struct ordered_event *last;
34 int buffer_idx;
35 unsigned int nr_events;
36 enum oe_flush last_flush_type;
37 bool copy_on_queue;
38};
39
40struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp,
41 union perf_event *event);
42void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
43int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
44 enum oe_flush how);
45void ordered_events__init(struct ordered_events *oe);
46void ordered_events__free(struct ordered_events *oe);
47
48static inline
49void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
50{
51 oe->max_alloc_size = size;
52}
53
54static inline
55void ordered_events__set_copy_on_queue(struct ordered_events *oe, bool copy)
56{
57 oe->copy_on_queue = copy;
58}
59#endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1e15df10a88c..c659a3ca1283 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -6,10 +6,11 @@
6#include "parse-options.h" 6#include "parse-options.h"
7#include "parse-events.h" 7#include "parse-events.h"
8#include "exec_cmd.h" 8#include "exec_cmd.h"
9#include "linux/string.h" 9#include "string.h"
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debug.h"
13#include <api/fs/debugfs.h> 14#include <api/fs/debugfs.h>
14#include "parse-events-bison.h" 15#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int 16#define YY_EXTRA_TYPE int
@@ -29,6 +30,15 @@ extern int parse_events_debug;
29#endif 30#endif
30int parse_events_parse(void *data, void *scanner); 31int parse_events_parse(void *data, void *scanner);
31 32
33static struct perf_pmu_event_symbol *perf_pmu_events_list;
34/*
35 * The variable indicates the number of supported pmu event symbols.
36 * 0 means not initialized and ready to init
37 * -1 means failed to init, don't try anymore
38 * >0 is the number of supported pmu event symbols
39 */
40static int perf_pmu_events_list_num;
41
32static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 42static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
33 [PERF_COUNT_HW_CPU_CYCLES] = { 43 [PERF_COUNT_HW_CPU_CYCLES] = {
34 .symbol = "cpu-cycles", 44 .symbol = "cpu-cycles",
@@ -633,18 +643,28 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
633 char *name, struct list_head *head_config) 643 char *name, struct list_head *head_config)
634{ 644{
635 struct perf_event_attr attr; 645 struct perf_event_attr attr;
646 struct perf_pmu_info info;
636 struct perf_pmu *pmu; 647 struct perf_pmu *pmu;
637 struct perf_evsel *evsel; 648 struct perf_evsel *evsel;
638 const char *unit;
639 double scale;
640 649
641 pmu = perf_pmu__find(name); 650 pmu = perf_pmu__find(name);
642 if (!pmu) 651 if (!pmu)
643 return -EINVAL; 652 return -EINVAL;
644 653
645 memset(&attr, 0, sizeof(attr)); 654 if (pmu->default_config) {
655 memcpy(&attr, pmu->default_config,
656 sizeof(struct perf_event_attr));
657 } else {
658 memset(&attr, 0, sizeof(attr));
659 }
646 660
647 if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) 661 if (!head_config) {
662 attr.type = pmu->type;
663 evsel = __add_event(list, idx, &attr, NULL, pmu->cpus);
664 return evsel ? 0 : -ENOMEM;
665 }
666
667 if (perf_pmu__check_alias(pmu, head_config, &info))
648 return -EINVAL; 668 return -EINVAL;
649 669
650 /* 670 /*
@@ -659,8 +679,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
659 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config), 679 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config),
660 pmu->cpus); 680 pmu->cpus);
661 if (evsel) { 681 if (evsel) {
662 evsel->unit = unit; 682 evsel->unit = info.unit;
663 evsel->scale = scale; 683 evsel->scale = info.scale;
664 } 684 }
665 685
666 return evsel ? 0 : -ENOMEM; 686 return evsel ? 0 : -ENOMEM;
@@ -852,30 +872,111 @@ int parse_events_name(struct list_head *list, char *name)
852 return 0; 872 return 0;
853} 873}
854 874
855static int parse_events__scanner(const char *str, void *data, int start_token); 875static int
876comp_pmu(const void *p1, const void *p2)
877{
878 struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1;
879 struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2;
856 880
857static int parse_events_fixup(int ret, const char *str, void *data, 881 return strcmp(pmu1->symbol, pmu2->symbol);
858 int start_token) 882}
883
884static void perf_pmu__parse_cleanup(void)
859{ 885{
860 char *o = strdup(str); 886 if (perf_pmu_events_list_num > 0) {
861 char *s = NULL; 887 struct perf_pmu_event_symbol *p;
862 char *t = o; 888 int i;
863 char *p; 889
890 for (i = 0; i < perf_pmu_events_list_num; i++) {
891 p = perf_pmu_events_list + i;
892 free(p->symbol);
893 }
894 free(perf_pmu_events_list);
895 perf_pmu_events_list = NULL;
896 perf_pmu_events_list_num = 0;
897 }
898}
899
900#define SET_SYMBOL(str, stype) \
901do { \
902 p->symbol = str; \
903 if (!p->symbol) \
904 goto err; \
905 p->type = stype; \
906} while (0)
907
908/*
909 * Read the pmu events list from sysfs
910 * Save it into perf_pmu_events_list
911 */
912static void perf_pmu__parse_init(void)
913{
914
915 struct perf_pmu *pmu = NULL;
916 struct perf_pmu_alias *alias;
864 int len = 0; 917 int len = 0;
865 918
866 if (!o) 919 pmu = perf_pmu__find("cpu");
867 return ret; 920 if ((pmu == NULL) || list_empty(&pmu->aliases)) {
868 while ((p = strsep(&t, ",")) != NULL) { 921 perf_pmu_events_list_num = -1;
869 if (s) 922 return;
870 str_append(&s, &len, ",");
871 str_append(&s, &len, "cpu/");
872 str_append(&s, &len, p);
873 str_append(&s, &len, "/");
874 } 923 }
875 free(o); 924 list_for_each_entry(alias, &pmu->aliases, list) {
876 if (!s) 925 if (strchr(alias->name, '-'))
877 return -ENOMEM; 926 len++;
878 return parse_events__scanner(s, data, start_token); 927 len++;
928 }
929 perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len);
930 if (!perf_pmu_events_list)
931 return;
932 perf_pmu_events_list_num = len;
933
934 len = 0;
935 list_for_each_entry(alias, &pmu->aliases, list) {
936 struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
937 char *tmp = strchr(alias->name, '-');
938
939 if (tmp != NULL) {
940 SET_SYMBOL(strndup(alias->name, tmp - alias->name),
941 PMU_EVENT_SYMBOL_PREFIX);
942 p++;
943 SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX);
944 len += 2;
945 } else {
946 SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL);
947 len++;
948 }
949 }
950 qsort(perf_pmu_events_list, len,
951 sizeof(struct perf_pmu_event_symbol), comp_pmu);
952
953 return;
954err:
955 perf_pmu__parse_cleanup();
956}
957
958enum perf_pmu_event_symbol_type
959perf_pmu__parse_check(const char *name)
960{
961 struct perf_pmu_event_symbol p, *r;
962
963 /* scan kernel pmu events from sysfs if needed */
964 if (perf_pmu_events_list_num == 0)
965 perf_pmu__parse_init();
966 /*
967 * name "cpu" could be prefix of cpu-cycles or cpu// events.
968 * cpu-cycles has been handled by hardcode.
969 * So it must be cpu// events, not kernel pmu event.
970 */
971 if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu"))
972 return PMU_EVENT_SYMBOL_ERR;
973
974 p.symbol = strdup(name);
975 r = bsearch(&p, perf_pmu_events_list,
976 (size_t) perf_pmu_events_list_num,
977 sizeof(struct perf_pmu_event_symbol), comp_pmu);
978 free(p.symbol);
979 return r ? r->type : PMU_EVENT_SYMBOL_ERR;
879} 980}
880 981
881static int parse_events__scanner(const char *str, void *data, int start_token) 982static int parse_events__scanner(const char *str, void *data, int start_token)
@@ -898,8 +999,6 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
898 parse_events__flush_buffer(buffer, scanner); 999 parse_events__flush_buffer(buffer, scanner);
899 parse_events__delete_buffer(buffer, scanner); 1000 parse_events__delete_buffer(buffer, scanner);
900 parse_events_lex_destroy(scanner); 1001 parse_events_lex_destroy(scanner);
901 if (ret && !strchr(str, '/'))
902 ret = parse_events_fixup(ret, str, data, start_token);
903 return ret; 1002 return ret;
904} 1003}
905 1004
@@ -934,6 +1033,7 @@ int parse_events(struct perf_evlist *evlist, const char *str)
934 int ret; 1033 int ret;
935 1034
936 ret = parse_events__scanner(str, &data, PE_START_EVENTS); 1035 ret = parse_events__scanner(str, &data, PE_START_EVENTS);
1036 perf_pmu__parse_cleanup();
937 if (!ret) { 1037 if (!ret) {
938 int entries = data.idx - evlist->nr_entries; 1038 int entries = data.idx - evlist->nr_entries;
939 perf_evlist__splice_list_tail(evlist, &data.list, entries); 1039 perf_evlist__splice_list_tail(evlist, &data.list, entries);
@@ -973,7 +1073,7 @@ int parse_filter(const struct option *opt, const char *str,
973 1073
974 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 1074 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
975 fprintf(stderr, 1075 fprintf(stderr,
976 "-F option should follow a -e tracepoint option\n"); 1076 "--filter option should follow a -e tracepoint option\n");
977 return -1; 1077 return -1;
978 } 1078 }
979 1079
@@ -1006,9 +1106,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1006 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1106 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1007 char evt_path[MAXPATHLEN]; 1107 char evt_path[MAXPATHLEN];
1008 char dir_path[MAXPATHLEN]; 1108 char dir_path[MAXPATHLEN];
1109 char sbuf[STRERR_BUFSIZE];
1009 1110
1010 if (debugfs_valid_mountpoint(tracing_events_path)) { 1111 if (debugfs_valid_mountpoint(tracing_events_path)) {
1011 printf(" [ Tracepoints not available: %s ]\n", strerror(errno)); 1112 printf(" [ Tracepoints not available: %s ]\n",
1113 strerror_r(errno, sbuf, sizeof(sbuf)));
1012 return; 1114 return;
1013 } 1115 }
1014 1116
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index df094b4ed5ed..db2cf78ff0f3 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -35,6 +35,18 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
35 35
36#define EVENTS_HELP_MAX (128*1024) 36#define EVENTS_HELP_MAX (128*1024)
37 37
38enum perf_pmu_event_symbol_type {
39 PMU_EVENT_SYMBOL_ERR, /* not a PMU EVENT */
40 PMU_EVENT_SYMBOL, /* normal style PMU event */
41 PMU_EVENT_SYMBOL_PREFIX, /* prefix of pre-suf style event */
42 PMU_EVENT_SYMBOL_SUFFIX, /* suffix of pre-suf style event */
43};
44
45struct perf_pmu_event_symbol {
46 char *symbol;
47 enum perf_pmu_event_symbol_type type;
48};
49
38enum { 50enum {
39 PARSE_EVENTS__TERM_TYPE_NUM, 51 PARSE_EVENTS__TERM_TYPE_NUM,
40 PARSE_EVENTS__TERM_TYPE_STR, 52 PARSE_EVENTS__TERM_TYPE_STR,
@@ -95,6 +107,8 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
95 void *ptr, char *type); 107 void *ptr, char *type);
96int parse_events_add_pmu(struct list_head *list, int *idx, 108int parse_events_add_pmu(struct list_head *list, int *idx,
97 char *pmu , struct list_head *head_config); 109 char *pmu , struct list_head *head_config);
110enum perf_pmu_event_symbol_type
111perf_pmu__parse_check(const char *name);
98void parse_events__set_leader(char *name, struct list_head *list); 112void parse_events__set_leader(char *name, struct list_head *list);
99void parse_events_update_lists(struct list_head *list_event, 113void parse_events_update_lists(struct list_head *list_event,
100 struct list_head *list_all); 114 struct list_head *list_all);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 343299575b30..906630bbf8eb 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -51,6 +51,24 @@ static int str(yyscan_t scanner, int token)
51 return token; 51 return token;
52} 52}
53 53
54static int pmu_str_check(yyscan_t scanner)
55{
56 YYSTYPE *yylval = parse_events_get_lval(scanner);
57 char *text = parse_events_get_text(scanner);
58
59 yylval->str = strdup(text);
60 switch (perf_pmu__parse_check(text)) {
61 case PMU_EVENT_SYMBOL_PREFIX:
62 return PE_PMU_EVENT_PRE;
63 case PMU_EVENT_SYMBOL_SUFFIX:
64 return PE_PMU_EVENT_SUF;
65 case PMU_EVENT_SYMBOL:
66 return PE_KERNEL_PMU_EVENT;
67 default:
68 return PE_NAME;
69 }
70}
71
54static int sym(yyscan_t scanner, int type, int config) 72static int sym(yyscan_t scanner, int type, int config)
55{ 73{
56 YYSTYPE *yylval = parse_events_get_lval(scanner); 74 YYSTYPE *yylval = parse_events_get_lval(scanner);
@@ -178,6 +196,16 @@ alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_AL
178emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 196emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
179dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } 197dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
180 198
199 /*
200 * We have to handle the kernel PMU event cycles-ct/cycles-t/mem-loads/mem-stores separately.
201 * Because the prefix cycles is mixed up with cpu-cycles.
202 * loads and stores are mixed up with cache event
203 */
204cycles-ct { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
205cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
206mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
207mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
208
181L1-dcache|l1-d|l1d|L1-data | 209L1-dcache|l1-d|l1d|L1-data |
182L1-icache|l1-i|l1i|L1-instruction | 210L1-icache|l1-i|l1i|L1-instruction |
183LLC|L2 | 211LLC|L2 |
@@ -199,7 +227,7 @@ r{num_raw_hex} { return raw(yyscanner); }
199{num_hex} { return value(yyscanner, 16); } 227{num_hex} { return value(yyscanner, 16); }
200 228
201{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 229{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
202{name} { return str(yyscanner, PE_NAME); } 230{name} { return pmu_str_check(yyscanner); }
203"/" { BEGIN(config); return '/'; } 231"/" { BEGIN(config); return '/'; }
204- { return '-'; } 232- { return '-'; }
205, { BEGIN(event); return ','; } 233, { BEGIN(event); return ','; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 0bc87ba46bf3..93c4c9fbc922 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -47,6 +47,7 @@ static inc_group_count(struct list_head *list,
47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
49%token PE_ERROR 49%token PE_ERROR
50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
50%type <num> PE_VALUE 51%type <num> PE_VALUE
51%type <num> PE_VALUE_SYM_HW 52%type <num> PE_VALUE_SYM_HW
52%type <num> PE_VALUE_SYM_SW 53%type <num> PE_VALUE_SYM_SW
@@ -58,6 +59,7 @@ static inc_group_count(struct list_head *list,
58%type <str> PE_MODIFIER_EVENT 59%type <str> PE_MODIFIER_EVENT
59%type <str> PE_MODIFIER_BP 60%type <str> PE_MODIFIER_BP
60%type <str> PE_EVENT_NAME 61%type <str> PE_EVENT_NAME
62%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
61%type <num> value_sym 63%type <num> value_sym
62%type <head> event_config 64%type <head> event_config
63%type <term> event_term 65%type <term> event_term
@@ -210,6 +212,54 @@ PE_NAME '/' event_config '/'
210 parse_events__free_terms($3); 212 parse_events__free_terms($3);
211 $$ = list; 213 $$ = list;
212} 214}
215|
216PE_NAME '/' '/'
217{
218 struct parse_events_evlist *data = _data;
219 struct list_head *list;
220
221 ALLOC_LIST(list);
222 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL));
223 $$ = list;
224}
225|
226PE_KERNEL_PMU_EVENT sep_dc
227{
228 struct parse_events_evlist *data = _data;
229 struct list_head *head;
230 struct parse_events_term *term;
231 struct list_head *list;
232
233 ALLOC_LIST(head);
234 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
235 $1, 1));
236 list_add_tail(&term->list, head);
237
238 ALLOC_LIST(list);
239 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
240 parse_events__free_terms(head);
241 $$ = list;
242}
243|
244PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
245{
246 struct parse_events_evlist *data = _data;
247 struct list_head *head;
248 struct parse_events_term *term;
249 struct list_head *list;
250 char pmu_name[128];
251 snprintf(&pmu_name, 128, "%s-%s", $1, $3);
252
253 ALLOC_LIST(head);
254 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
255 &pmu_name, 1));
256 list_add_tail(&term->list, head);
257
258 ALLOC_LIST(list);
259 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
260 parse_events__free_terms(head);
261 $$ = list;
262}
213 263
214value_sym: 264value_sym:
215PE_VALUE_SYM_HW 265PE_VALUE_SYM_HW
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 7a811eb61f75..e243ad962a4d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -2,6 +2,8 @@
2#include <sys/types.h> 2#include <sys/types.h>
3#include <unistd.h> 3#include <unistd.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h>
6#include <stdarg.h>
5#include <dirent.h> 7#include <dirent.h>
6#include <api/fs/fs.h> 8#include <api/fs/fs.h>
7#include <locale.h> 9#include <locale.h>
@@ -10,16 +12,6 @@
10#include "parse-events.h" 12#include "parse-events.h"
11#include "cpumap.h" 13#include "cpumap.h"
12 14
13#define UNIT_MAX_LEN 31 /* max length for event unit name */
14
15struct perf_pmu_alias {
16 char *name;
17 struct list_head terms;
18 struct list_head list;
19 char unit[UNIT_MAX_LEN+1];
20 double scale;
21};
22
23struct perf_pmu_format { 15struct perf_pmu_format {
24 char *name; 16 char *name;
25 int value; 17 int value;
@@ -208,6 +200,19 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
208 return 0; 200 return 0;
209} 201}
210 202
203static inline bool pmu_alias_info_file(char *name)
204{
205 size_t len;
206
207 len = strlen(name);
208 if (len > 5 && !strcmp(name + len - 5, ".unit"))
209 return true;
210 if (len > 6 && !strcmp(name + len - 6, ".scale"))
211 return true;
212
213 return false;
214}
215
211/* 216/*
212 * Process all the sysfs attributes located under the directory 217 * Process all the sysfs attributes located under the directory
213 * specified in 'dir' parameter. 218 * specified in 'dir' parameter.
@@ -216,7 +221,6 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
216{ 221{
217 struct dirent *evt_ent; 222 struct dirent *evt_ent;
218 DIR *event_dir; 223 DIR *event_dir;
219 size_t len;
220 int ret = 0; 224 int ret = 0;
221 225
222 event_dir = opendir(dir); 226 event_dir = opendir(dir);
@@ -232,13 +236,9 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
232 continue; 236 continue;
233 237
234 /* 238 /*
235 * skip .unit and .scale info files 239 * skip info files parsed in perf_pmu__new_alias()
236 * parsed in perf_pmu__new_alias()
237 */ 240 */
238 len = strlen(name); 241 if (pmu_alias_info_file(name))
239 if (len > 5 && !strcmp(name + len - 5, ".unit"))
240 continue;
241 if (len > 6 && !strcmp(name + len - 6, ".scale"))
242 continue; 242 continue;
243 243
244 snprintf(path, PATH_MAX, "%s/%s", dir, name); 244 snprintf(path, PATH_MAX, "%s/%s", dir, name);
@@ -387,6 +387,12 @@ static struct cpu_map *pmu_cpumask(const char *name)
387 return cpus; 387 return cpus;
388} 388}
389 389
390struct perf_event_attr *__attribute__((weak))
391perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
392{
393 return NULL;
394}
395
390static struct perf_pmu *pmu_lookup(const char *name) 396static struct perf_pmu *pmu_lookup(const char *name)
391{ 397{
392 struct perf_pmu *pmu; 398 struct perf_pmu *pmu;
@@ -421,6 +427,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
421 pmu->name = strdup(name); 427 pmu->name = strdup(name);
422 pmu->type = type; 428 pmu->type = type;
423 list_add_tail(&pmu->list, &pmus); 429 list_add_tail(&pmu->list, &pmus);
430
431 pmu->default_config = perf_pmu__get_default_config(pmu);
432
424 return pmu; 433 return pmu;
425} 434}
426 435
@@ -479,28 +488,24 @@ pmu_find_format(struct list_head *formats, char *name)
479} 488}
480 489
481/* 490/*
482 * Returns value based on the format definition (format parameter) 491 * Sets value based on the format definition (format parameter)
483 * and unformated value (value parameter). 492 * and unformated value (value parameter).
484 *
485 * TODO maybe optimize a little ;)
486 */ 493 */
487static __u64 pmu_format_value(unsigned long *format, __u64 value) 494static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
495 bool zero)
488{ 496{
489 unsigned long fbit, vbit; 497 unsigned long fbit, vbit;
490 __u64 v = 0;
491 498
492 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 499 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
493 500
494 if (!test_bit(fbit, format)) 501 if (!test_bit(fbit, format))
495 continue; 502 continue;
496 503
497 if (!(value & (1llu << vbit++))) 504 if (value & (1llu << vbit++))
498 continue; 505 *v |= (1llu << fbit);
499 506 else if (zero)
500 v |= (1llu << fbit); 507 *v &= ~(1llu << fbit);
501 } 508 }
502
503 return v;
504} 509}
505 510
506/* 511/*
@@ -509,7 +514,8 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
509 */ 514 */
510static int pmu_config_term(struct list_head *formats, 515static int pmu_config_term(struct list_head *formats,
511 struct perf_event_attr *attr, 516 struct perf_event_attr *attr,
512 struct parse_events_term *term) 517 struct parse_events_term *term,
518 bool zero)
513{ 519{
514 struct perf_pmu_format *format; 520 struct perf_pmu_format *format;
515 __u64 *vp; 521 __u64 *vp;
@@ -548,18 +554,19 @@ static int pmu_config_term(struct list_head *formats,
548 * non-hardcoded terms, here's the place to translate 554 * non-hardcoded terms, here's the place to translate
549 * them into value. 555 * them into value.
550 */ 556 */
551 *vp |= pmu_format_value(format->bits, term->val.num); 557 pmu_format_value(format->bits, term->val.num, vp, zero);
552 return 0; 558 return 0;
553} 559}
554 560
555int perf_pmu__config_terms(struct list_head *formats, 561int perf_pmu__config_terms(struct list_head *formats,
556 struct perf_event_attr *attr, 562 struct perf_event_attr *attr,
557 struct list_head *head_terms) 563 struct list_head *head_terms,
564 bool zero)
558{ 565{
559 struct parse_events_term *term; 566 struct parse_events_term *term;
560 567
561 list_for_each_entry(term, head_terms, list) 568 list_for_each_entry(term, head_terms, list)
562 if (pmu_config_term(formats, attr, term)) 569 if (pmu_config_term(formats, attr, term, zero))
563 return -EINVAL; 570 return -EINVAL;
564 571
565 return 0; 572 return 0;
@@ -573,8 +580,10 @@ int perf_pmu__config_terms(struct list_head *formats,
573int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 580int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
574 struct list_head *head_terms) 581 struct list_head *head_terms)
575{ 582{
583 bool zero = !!pmu->default_config;
584
576 attr->type = pmu->type; 585 attr->type = pmu->type;
577 return perf_pmu__config_terms(&pmu->format, attr, head_terms); 586 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
578} 587}
579 588
580static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 589static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
@@ -634,7 +643,7 @@ static int check_unit_scale(struct perf_pmu_alias *alias,
634 * defined for the alias 643 * defined for the alias
635 */ 644 */
636int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 645int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
637 const char **unit, double *scale) 646 struct perf_pmu_info *info)
638{ 647{
639 struct parse_events_term *term, *h; 648 struct parse_events_term *term, *h;
640 struct perf_pmu_alias *alias; 649 struct perf_pmu_alias *alias;
@@ -644,8 +653,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
644 * Mark unit and scale as not set 653 * Mark unit and scale as not set
645 * (different from default values, see below) 654 * (different from default values, see below)
646 */ 655 */
647 *unit = NULL; 656 info->unit = NULL;
648 *scale = 0.0; 657 info->scale = 0.0;
649 658
650 list_for_each_entry_safe(term, h, head_terms, list) { 659 list_for_each_entry_safe(term, h, head_terms, list) {
651 alias = pmu_find_alias(pmu, term); 660 alias = pmu_find_alias(pmu, term);
@@ -655,7 +664,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
655 if (ret) 664 if (ret)
656 return ret; 665 return ret;
657 666
658 ret = check_unit_scale(alias, unit, scale); 667 ret = check_unit_scale(alias, &info->unit, &info->scale);
659 if (ret) 668 if (ret)
660 return ret; 669 return ret;
661 670
@@ -668,11 +677,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
668 * set defaults as for evsel 677 * set defaults as for evsel
669 * unit cannot left to NULL 678 * unit cannot left to NULL
670 */ 679 */
671 if (*unit == NULL) 680 if (info->unit == NULL)
672 *unit = ""; 681 info->unit = "";
673 682
674 if (*scale == 0.0) 683 if (info->scale == 0.0)
675 *scale = 1.0; 684 info->scale = 1.0;
676 685
677 return 0; 686 return 0;
678} 687}
@@ -794,3 +803,39 @@ bool pmu_have_event(const char *pname, const char *name)
794 } 803 }
795 return false; 804 return false;
796} 805}
806
807static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
808{
809 struct stat st;
810 char path[PATH_MAX];
811 const char *sysfs;
812
813 sysfs = sysfs__mountpoint();
814 if (!sysfs)
815 return NULL;
816
817 snprintf(path, PATH_MAX,
818 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
819
820 if (stat(path, &st) < 0)
821 return NULL;
822
823 return fopen(path, "r");
824}
825
826int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
827 ...)
828{
829 va_list args;
830 FILE *file;
831 int ret = EOF;
832
833 va_start(args, fmt);
834 file = perf_pmu__open_file(pmu, name);
835 if (file) {
836 ret = vfscanf(file, fmt, args);
837 fclose(file);
838 }
839 va_end(args);
840 return ret;
841}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index c14a543ce1f3..fe9dfbee8eed 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -13,13 +13,31 @@ enum {
13 13
14#define PERF_PMU_FORMAT_BITS 64 14#define PERF_PMU_FORMAT_BITS 64
15 15
16struct perf_event_attr;
17
16struct perf_pmu { 18struct perf_pmu {
17 char *name; 19 char *name;
18 __u32 type; 20 __u32 type;
21 struct perf_event_attr *default_config;
19 struct cpu_map *cpus; 22 struct cpu_map *cpus;
20 struct list_head format; 23 struct list_head format; /* HEAD struct perf_pmu_format -> list */
21 struct list_head aliases; 24 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
22 struct list_head list; 25 struct list_head list; /* ELEM */
26};
27
28struct perf_pmu_info {
29 const char *unit;
30 double scale;
31};
32
33#define UNIT_MAX_LEN 31 /* max length for event unit name */
34
35struct perf_pmu_alias {
36 char *name;
37 struct list_head terms; /* HEAD struct parse_events_term -> list */
38 struct list_head list; /* ELEM */
39 char unit[UNIT_MAX_LEN+1];
40 double scale;
23}; 41};
24 42
25struct perf_pmu *perf_pmu__find(const char *name); 43struct perf_pmu *perf_pmu__find(const char *name);
@@ -27,9 +45,10 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
27 struct list_head *head_terms); 45 struct list_head *head_terms);
28int perf_pmu__config_terms(struct list_head *formats, 46int perf_pmu__config_terms(struct list_head *formats,
29 struct perf_event_attr *attr, 47 struct perf_event_attr *attr,
30 struct list_head *head_terms); 48 struct list_head *head_terms,
49 bool zero);
31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 50int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
32 const char **unit, double *scale); 51 struct perf_pmu_info *info);
33struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 52struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
34 struct list_head *head_terms); 53 struct list_head *head_terms);
35int perf_pmu_wrap(void); 54int perf_pmu_wrap(void);
@@ -45,5 +64,11 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
45void print_pmu_events(const char *event_glob, bool name_only); 64void print_pmu_events(const char *event_glob, bool name_only);
46bool pmu_have_event(const char *pname, const char *name); 65bool pmu_have_event(const char *pname, const char *name);
47 66
67int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
68 ...) __attribute__((format(scanf, 3, 4)));
69
48int perf_pmu__test(void); 70int perf_pmu__test(void);
71
72struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
73
49#endif /* __PMU_H */ 74#endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9a0a1839a377..c150ca4343eb 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -79,7 +79,7 @@ static int init_symbol_maps(bool user_only)
79 int ret; 79 int ret;
80 80
81 symbol_conf.sort_by_name = true; 81 symbol_conf.sort_by_name = true;
82 ret = symbol__init(); 82 ret = symbol__init(NULL);
83 if (ret < 0) { 83 if (ret < 0) {
84 pr_debug("Failed to init symbol map.\n"); 84 pr_debug("Failed to init symbol map.\n");
85 goto out; 85 goto out;
@@ -184,7 +184,8 @@ static struct dso *kernel_get_module_dso(const char *module)
184 const char *vmlinux_name; 184 const char *vmlinux_name;
185 185
186 if (module) { 186 if (module) {
187 list_for_each_entry(dso, &host_machine->kernel_dsos, node) { 187 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
188 node) {
188 if (strncmp(dso->short_name + 1, module, 189 if (strncmp(dso->short_name + 1, module,
189 dso->short_name_len - 2) == 0) 190 dso->short_name_len - 2) == 0)
190 goto found; 191 goto found;
@@ -258,21 +259,33 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
258#ifdef HAVE_DWARF_SUPPORT 259#ifdef HAVE_DWARF_SUPPORT
259 260
260/* Open new debuginfo of given module */ 261/* Open new debuginfo of given module */
261static struct debuginfo *open_debuginfo(const char *module) 262static struct debuginfo *open_debuginfo(const char *module, bool silent)
262{ 263{
263 const char *path = module; 264 const char *path = module;
265 struct debuginfo *ret;
264 266
265 if (!module || !strchr(module, '/')) { 267 if (!module || !strchr(module, '/')) {
266 path = kernel_get_module_path(module); 268 path = kernel_get_module_path(module);
267 if (!path) { 269 if (!path) {
268 pr_err("Failed to find path of %s module.\n", 270 if (!silent)
269 module ?: "kernel"); 271 pr_err("Failed to find path of %s module.\n",
272 module ?: "kernel");
270 return NULL; 273 return NULL;
271 } 274 }
272 } 275 }
273 return debuginfo__new(path); 276 ret = debuginfo__new(path);
277 if (!ret && !silent) {
278 pr_warning("The %s file has no debug information.\n", path);
279 if (!module || !strtailcmp(path, ".ko"))
280 pr_warning("Rebuild with CONFIG_DEBUG_INFO=y, ");
281 else
282 pr_warning("Rebuild with -g, ");
283 pr_warning("or install an appropriate debuginfo package.\n");
284 }
285 return ret;
274} 286}
275 287
288
276static int get_text_start_address(const char *exec, unsigned long *address) 289static int get_text_start_address(const char *exec, unsigned long *address)
277{ 290{
278 Elf *elf; 291 Elf *elf;
@@ -333,15 +346,13 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
333 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 346 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
334 tp->module ? : "kernel"); 347 tp->module ? : "kernel");
335 348
336 dinfo = open_debuginfo(tp->module); 349 dinfo = open_debuginfo(tp->module, verbose == 0);
337 if (dinfo) { 350 if (dinfo) {
338 ret = debuginfo__find_probe_point(dinfo, 351 ret = debuginfo__find_probe_point(dinfo,
339 (unsigned long)addr, pp); 352 (unsigned long)addr, pp);
340 debuginfo__delete(dinfo); 353 debuginfo__delete(dinfo);
341 } else { 354 } else
342 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", addr);
343 ret = -ENOENT; 355 ret = -ENOENT;
344 }
345 356
346 if (ret > 0) { 357 if (ret > 0) {
347 pp->retprobe = tp->retprobe; 358 pp->retprobe = tp->retprobe;
@@ -457,13 +468,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
457 struct debuginfo *dinfo; 468 struct debuginfo *dinfo;
458 int ntevs, ret = 0; 469 int ntevs, ret = 0;
459 470
460 dinfo = open_debuginfo(target); 471 dinfo = open_debuginfo(target, !need_dwarf);
461 472
462 if (!dinfo) { 473 if (!dinfo) {
463 if (need_dwarf) { 474 if (need_dwarf)
464 pr_warning("Failed to open debuginfo file.\n");
465 return -ENOENT; 475 return -ENOENT;
466 }
467 pr_debug("Could not open debuginfo. Try to use symbols.\n"); 476 pr_debug("Could not open debuginfo. Try to use symbols.\n");
468 return 0; 477 return 0;
469 } 478 }
@@ -565,7 +574,7 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
565 574
566static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 575static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
567{ 576{
568 char buf[LINEBUF_SIZE]; 577 char buf[LINEBUF_SIZE], sbuf[STRERR_BUFSIZE];
569 const char *color = show_num ? "" : PERF_COLOR_BLUE; 578 const char *color = show_num ? "" : PERF_COLOR_BLUE;
570 const char *prefix = NULL; 579 const char *prefix = NULL;
571 580
@@ -585,7 +594,8 @@ static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
585 return 1; 594 return 1;
586error: 595error:
587 if (ferror(fp)) { 596 if (ferror(fp)) {
588 pr_warning("File read error: %s\n", strerror(errno)); 597 pr_warning("File read error: %s\n",
598 strerror_r(errno, sbuf, sizeof(sbuf)));
589 return -1; 599 return -1;
590 } 600 }
591 return 0; 601 return 0;
@@ -618,13 +628,12 @@ static int __show_line_range(struct line_range *lr, const char *module)
618 FILE *fp; 628 FILE *fp;
619 int ret; 629 int ret;
620 char *tmp; 630 char *tmp;
631 char sbuf[STRERR_BUFSIZE];
621 632
622 /* Search a line range */ 633 /* Search a line range */
623 dinfo = open_debuginfo(module); 634 dinfo = open_debuginfo(module, false);
624 if (!dinfo) { 635 if (!dinfo)
625 pr_warning("Failed to open debuginfo file.\n");
626 return -ENOENT; 636 return -ENOENT;
627 }
628 637
629 ret = debuginfo__find_line_range(dinfo, lr); 638 ret = debuginfo__find_line_range(dinfo, lr);
630 debuginfo__delete(dinfo); 639 debuginfo__delete(dinfo);
@@ -656,7 +665,7 @@ static int __show_line_range(struct line_range *lr, const char *module)
656 fp = fopen(lr->path, "r"); 665 fp = fopen(lr->path, "r");
657 if (fp == NULL) { 666 if (fp == NULL) {
658 pr_warning("Failed to open %s: %s\n", lr->path, 667 pr_warning("Failed to open %s: %s\n", lr->path,
659 strerror(errno)); 668 strerror_r(errno, sbuf, sizeof(sbuf)));
660 return -errno; 669 return -errno;
661 } 670 }
662 /* Skip to starting line number */ 671 /* Skip to starting line number */
@@ -689,11 +698,11 @@ end:
689 return ret; 698 return ret;
690} 699}
691 700
692int show_line_range(struct line_range *lr, const char *module) 701int show_line_range(struct line_range *lr, const char *module, bool user)
693{ 702{
694 int ret; 703 int ret;
695 704
696 ret = init_symbol_maps(false); 705 ret = init_symbol_maps(user);
697 if (ret < 0) 706 if (ret < 0)
698 return ret; 707 return ret;
699 ret = __show_line_range(lr, module); 708 ret = __show_line_range(lr, module);
@@ -768,13 +777,12 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
768 int i, ret = 0; 777 int i, ret = 0;
769 struct debuginfo *dinfo; 778 struct debuginfo *dinfo;
770 779
771 ret = init_symbol_maps(false); 780 ret = init_symbol_maps(pevs->uprobes);
772 if (ret < 0) 781 if (ret < 0)
773 return ret; 782 return ret;
774 783
775 dinfo = open_debuginfo(module); 784 dinfo = open_debuginfo(module, false);
776 if (!dinfo) { 785 if (!dinfo) {
777 pr_warning("Failed to open debuginfo file.\n");
778 ret = -ENOENT; 786 ret = -ENOENT;
779 goto out; 787 goto out;
780 } 788 }
@@ -815,7 +823,8 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
815} 823}
816 824
817int show_line_range(struct line_range *lr __maybe_unused, 825int show_line_range(struct line_range *lr __maybe_unused,
818 const char *module __maybe_unused) 826 const char *module __maybe_unused,
827 bool user __maybe_unused)
819{ 828{
820 pr_warning("Debuginfo-analysis is not supported.\n"); 829 pr_warning("Debuginfo-analysis is not supported.\n");
821 return -ENOSYS; 830 return -ENOSYS;
@@ -1405,8 +1414,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1405 1414
1406 return tmp - buf; 1415 return tmp - buf;
1407error: 1416error:
1408 pr_debug("Failed to synthesize perf probe argument: %s\n", 1417 pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
1409 strerror(-ret));
1410 return ret; 1418 return ret;
1411} 1419}
1412 1420
@@ -1455,8 +1463,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1455 1463
1456 return buf; 1464 return buf;
1457error: 1465error:
1458 pr_debug("Failed to synthesize perf probe point: %s\n", 1466 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
1459 strerror(-ret));
1460 free(buf); 1467 free(buf);
1461 return NULL; 1468 return NULL;
1462} 1469}
@@ -1780,10 +1787,11 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1780 memset(tev, 0, sizeof(*tev)); 1787 memset(tev, 0, sizeof(*tev));
1781} 1788}
1782 1789
1783static void print_warn_msg(const char *file, bool is_kprobe) 1790static void print_open_warning(int err, bool is_kprobe)
1784{ 1791{
1792 char sbuf[STRERR_BUFSIZE];
1785 1793
1786 if (errno == ENOENT) { 1794 if (err == -ENOENT) {
1787 const char *config; 1795 const char *config;
1788 1796
1789 if (!is_kprobe) 1797 if (!is_kprobe)
@@ -1791,25 +1799,43 @@ static void print_warn_msg(const char *file, bool is_kprobe)
1791 else 1799 else
1792 config = "CONFIG_KPROBE_EVENTS"; 1800 config = "CONFIG_KPROBE_EVENTS";
1793 1801
1794 pr_warning("%s file does not exist - please rebuild kernel" 1802 pr_warning("%cprobe_events file does not exist"
1795 " with %s.\n", file, config); 1803 " - please rebuild kernel with %s.\n",
1796 } else 1804 is_kprobe ? 'k' : 'u', config);
1797 pr_warning("Failed to open %s file: %s\n", file, 1805 } else if (err == -ENOTSUP)
1798 strerror(errno)); 1806 pr_warning("Debugfs is not mounted.\n");
1807 else
1808 pr_warning("Failed to open %cprobe_events: %s\n",
1809 is_kprobe ? 'k' : 'u',
1810 strerror_r(-err, sbuf, sizeof(sbuf)));
1811}
1812
1813static void print_both_open_warning(int kerr, int uerr)
1814{
1815 /* Both kprobes and uprobes are disabled, warn it. */
1816 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1817 pr_warning("Debugfs is not mounted.\n");
1818 else if (kerr == -ENOENT && uerr == -ENOENT)
1819 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1820 "or/and CONFIG_UPROBE_EVENTS.\n");
1821 else {
1822 char sbuf[STRERR_BUFSIZE];
1823 pr_warning("Failed to open kprobe events: %s.\n",
1824 strerror_r(-kerr, sbuf, sizeof(sbuf)));
1825 pr_warning("Failed to open uprobe events: %s.\n",
1826 strerror_r(-uerr, sbuf, sizeof(sbuf)));
1827 }
1799} 1828}
1800 1829
1801static int open_probe_events(const char *trace_file, bool readwrite, 1830static int open_probe_events(const char *trace_file, bool readwrite)
1802 bool is_kprobe)
1803{ 1831{
1804 char buf[PATH_MAX]; 1832 char buf[PATH_MAX];
1805 const char *__debugfs; 1833 const char *__debugfs;
1806 int ret; 1834 int ret;
1807 1835
1808 __debugfs = debugfs_find_mountpoint(); 1836 __debugfs = debugfs_find_mountpoint();
1809 if (__debugfs == NULL) { 1837 if (__debugfs == NULL)
1810 pr_warning("Debugfs is not mounted.\n"); 1838 return -ENOTSUP;
1811 return -ENOENT;
1812 }
1813 1839
1814 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1840 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
1815 if (ret >= 0) { 1841 if (ret >= 0) {
@@ -1820,19 +1846,19 @@ static int open_probe_events(const char *trace_file, bool readwrite,
1820 ret = open(buf, O_RDONLY, 0); 1846 ret = open(buf, O_RDONLY, 0);
1821 1847
1822 if (ret < 0) 1848 if (ret < 0)
1823 print_warn_msg(buf, is_kprobe); 1849 ret = -errno;
1824 } 1850 }
1825 return ret; 1851 return ret;
1826} 1852}
1827 1853
1828static int open_kprobe_events(bool readwrite) 1854static int open_kprobe_events(bool readwrite)
1829{ 1855{
1830 return open_probe_events("tracing/kprobe_events", readwrite, true); 1856 return open_probe_events("tracing/kprobe_events", readwrite);
1831} 1857}
1832 1858
1833static int open_uprobe_events(bool readwrite) 1859static int open_uprobe_events(bool readwrite)
1834{ 1860{
1835 return open_probe_events("tracing/uprobe_events", readwrite, false); 1861 return open_probe_events("tracing/uprobe_events", readwrite);
1836} 1862}
1837 1863
1838/* Get raw string list of current kprobe_events or uprobe_events */ 1864/* Get raw string list of current kprobe_events or uprobe_events */
@@ -1857,7 +1883,7 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1857 p[idx] = '\0'; 1883 p[idx] = '\0';
1858 ret = strlist__add(sl, buf); 1884 ret = strlist__add(sl, buf);
1859 if (ret < 0) { 1885 if (ret < 0) {
1860 pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1886 pr_debug("strlist__add failed (%d)\n", ret);
1861 strlist__delete(sl); 1887 strlist__delete(sl);
1862 return NULL; 1888 return NULL;
1863 } 1889 }
@@ -1916,7 +1942,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1916 1942
1917 rawlist = get_probe_trace_command_rawlist(fd); 1943 rawlist = get_probe_trace_command_rawlist(fd);
1918 if (!rawlist) 1944 if (!rawlist)
1919 return -ENOENT; 1945 return -ENOMEM;
1920 1946
1921 strlist__for_each(ent, rawlist) { 1947 strlist__for_each(ent, rawlist) {
1922 ret = parse_probe_trace_command(ent->s, &tev); 1948 ret = parse_probe_trace_command(ent->s, &tev);
@@ -1940,27 +1966,34 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1940/* List up current perf-probe events */ 1966/* List up current perf-probe events */
1941int show_perf_probe_events(void) 1967int show_perf_probe_events(void)
1942{ 1968{
1943 int fd, ret; 1969 int kp_fd, up_fd, ret;
1944 1970
1945 setup_pager(); 1971 setup_pager();
1946 fd = open_kprobe_events(false);
1947
1948 if (fd < 0)
1949 return fd;
1950 1972
1951 ret = init_symbol_maps(false); 1973 ret = init_symbol_maps(false);
1952 if (ret < 0) 1974 if (ret < 0)
1953 return ret; 1975 return ret;
1954 1976
1955 ret = __show_perf_probe_events(fd, true); 1977 kp_fd = open_kprobe_events(false);
1956 close(fd); 1978 if (kp_fd >= 0) {
1979 ret = __show_perf_probe_events(kp_fd, true);
1980 close(kp_fd);
1981 if (ret < 0)
1982 goto out;
1983 }
1957 1984
1958 fd = open_uprobe_events(false); 1985 up_fd = open_uprobe_events(false);
1959 if (fd >= 0) { 1986 if (kp_fd < 0 && up_fd < 0) {
1960 ret = __show_perf_probe_events(fd, false); 1987 print_both_open_warning(kp_fd, up_fd);
1961 close(fd); 1988 ret = kp_fd;
1989 goto out;
1962 } 1990 }
1963 1991
1992 if (up_fd >= 0) {
1993 ret = __show_perf_probe_events(up_fd, false);
1994 close(up_fd);
1995 }
1996out:
1964 exit_symbol_maps(); 1997 exit_symbol_maps();
1965 return ret; 1998 return ret;
1966} 1999}
@@ -1976,6 +2009,8 @@ static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1976 2009
1977 memset(&tev, 0, sizeof(tev)); 2010 memset(&tev, 0, sizeof(tev));
1978 rawlist = get_probe_trace_command_rawlist(fd); 2011 rawlist = get_probe_trace_command_rawlist(fd);
2012 if (!rawlist)
2013 return NULL;
1979 sl = strlist__new(true, NULL); 2014 sl = strlist__new(true, NULL);
1980 strlist__for_each(ent, rawlist) { 2015 strlist__for_each(ent, rawlist) {
1981 ret = parse_probe_trace_command(ent->s, &tev); 2016 ret = parse_probe_trace_command(ent->s, &tev);
@@ -2005,6 +2040,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2005{ 2040{
2006 int ret = 0; 2041 int ret = 0;
2007 char *buf = synthesize_probe_trace_command(tev); 2042 char *buf = synthesize_probe_trace_command(tev);
2043 char sbuf[STRERR_BUFSIZE];
2008 2044
2009 if (!buf) { 2045 if (!buf) {
2010 pr_debug("Failed to synthesize probe trace event.\n"); 2046 pr_debug("Failed to synthesize probe trace event.\n");
@@ -2016,7 +2052,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2016 ret = write(fd, buf, strlen(buf)); 2052 ret = write(fd, buf, strlen(buf));
2017 if (ret <= 0) 2053 if (ret <= 0)
2018 pr_warning("Failed to write event: %s\n", 2054 pr_warning("Failed to write event: %s\n",
2019 strerror(errno)); 2055 strerror_r(errno, sbuf, sizeof(sbuf)));
2020 } 2056 }
2021 free(buf); 2057 free(buf);
2022 return ret; 2058 return ret;
@@ -2030,7 +2066,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2030 /* Try no suffix */ 2066 /* Try no suffix */
2031 ret = e_snprintf(buf, len, "%s", base); 2067 ret = e_snprintf(buf, len, "%s", base);
2032 if (ret < 0) { 2068 if (ret < 0) {
2033 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2069 pr_debug("snprintf() failed: %d\n", ret);
2034 return ret; 2070 return ret;
2035 } 2071 }
2036 if (!strlist__has_entry(namelist, buf)) 2072 if (!strlist__has_entry(namelist, buf))
@@ -2046,7 +2082,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2046 for (i = 1; i < MAX_EVENT_INDEX; i++) { 2082 for (i = 1; i < MAX_EVENT_INDEX; i++) {
2047 ret = e_snprintf(buf, len, "%s_%d", base, i); 2083 ret = e_snprintf(buf, len, "%s_%d", base, i);
2048 if (ret < 0) { 2084 if (ret < 0) {
2049 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2085 pr_debug("snprintf() failed: %d\n", ret);
2050 return ret; 2086 return ret;
2051 } 2087 }
2052 if (!strlist__has_entry(namelist, buf)) 2088 if (!strlist__has_entry(namelist, buf))
@@ -2075,8 +2111,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2075 else 2111 else
2076 fd = open_kprobe_events(true); 2112 fd = open_kprobe_events(true);
2077 2113
2078 if (fd < 0) 2114 if (fd < 0) {
2115 print_open_warning(fd, !pev->uprobes);
2079 return fd; 2116 return fd;
2117 }
2118
2080 /* Get current event names */ 2119 /* Get current event names */
2081 namelist = get_probe_trace_event_names(fd, false); 2120 namelist = get_probe_trace_event_names(fd, false);
2082 if (!namelist) { 2121 if (!namelist) {
@@ -2408,7 +2447,8 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
2408 printf("Removed event: %s\n", ent->s); 2447 printf("Removed event: %s\n", ent->s);
2409 return 0; 2448 return 0;
2410error: 2449error:
2411 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 2450 pr_warning("Failed to delete event: %s\n",
2451 strerror_r(-ret, buf, sizeof(buf)));
2412 return ret; 2452 return ret;
2413} 2453}
2414 2454
@@ -2449,15 +2489,18 @@ int del_perf_probe_events(struct strlist *dellist)
2449 2489
2450 /* Get current event names */ 2490 /* Get current event names */
2451 kfd = open_kprobe_events(true); 2491 kfd = open_kprobe_events(true);
2452 if (kfd < 0) 2492 if (kfd >= 0)
2453 return kfd; 2493 namelist = get_probe_trace_event_names(kfd, true);
2454 2494
2455 namelist = get_probe_trace_event_names(kfd, true);
2456 ufd = open_uprobe_events(true); 2495 ufd = open_uprobe_events(true);
2457
2458 if (ufd >= 0) 2496 if (ufd >= 0)
2459 unamelist = get_probe_trace_event_names(ufd, true); 2497 unamelist = get_probe_trace_event_names(ufd, true);
2460 2498
2499 if (kfd < 0 && ufd < 0) {
2500 print_both_open_warning(kfd, ufd);
2501 goto error;
2502 }
2503
2461 if (namelist == NULL && unamelist == NULL) 2504 if (namelist == NULL && unamelist == NULL)
2462 goto error; 2505 goto error;
2463 2506
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 776c9347a3b6..e01e9943139f 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -128,7 +128,8 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
128 bool force_add); 128 bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist); 129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void); 130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module); 131extern int show_line_range(struct line_range *lr, const char *module,
132 bool user);
132extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 133extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
133 int max_probe_points, const char *module, 134 int max_probe_points, const char *module,
134 struct strfilter *filter, bool externs); 135 struct strfilter *filter, bool externs);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index dca9145d704c..c7918f83b300 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -281,6 +281,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
282 Dwarf_Die type; 282 Dwarf_Die type;
283 char buf[16]; 283 char buf[16];
284 char sbuf[STRERR_BUFSIZE];
284 int bsize, boffs, total; 285 int bsize, boffs, total;
285 int ret; 286 int ret;
286 287
@@ -367,7 +368,7 @@ formatted:
367 if (ret >= 16) 368 if (ret >= 16)
368 ret = -E2BIG; 369 ret = -E2BIG;
369 pr_warning("Failed to convert variable type: %s\n", 370 pr_warning("Failed to convert variable type: %s\n",
370 strerror(-ret)); 371 strerror_r(-ret, sbuf, sizeof(sbuf)));
371 return ret; 372 return ret;
372 } 373 }
373 tvar->type = strdup(buf); 374 tvar->type = strdup(buf);
@@ -608,14 +609,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
608 return -EINVAL; 609 return -EINVAL;
609 } 610 }
610 611
611 /* Get an appropriate symbol from symtab */ 612 symbol = dwarf_diename(sp_die);
612 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
613 if (!symbol) { 613 if (!symbol) {
614 pr_warning("Failed to find symbol at 0x%lx\n", 614 /* Try to get the symbol name from symtab */
615 (unsigned long)paddr); 615 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
616 return -ENOENT; 616 if (!symbol) {
617 pr_warning("Failed to find symbol at 0x%lx\n",
618 (unsigned long)paddr);
619 return -ENOENT;
620 }
621 eaddr = sym.st_value;
617 } 622 }
618 tp->offset = (unsigned long)(paddr - sym.st_value); 623 tp->offset = (unsigned long)(paddr - eaddr);
619 tp->address = (unsigned long)paddr; 624 tp->address = (unsigned long)paddr;
620 tp->symbol = strdup(symbol); 625 tp->symbol = strdup(symbol);
621 if (!tp->symbol) 626 if (!tp->symbol)
@@ -779,10 +784,12 @@ static int find_lazy_match_lines(struct intlist *list,
779 size_t line_len; 784 size_t line_len;
780 ssize_t len; 785 ssize_t len;
781 int count = 0, linenum = 1; 786 int count = 0, linenum = 1;
787 char sbuf[STRERR_BUFSIZE];
782 788
783 fp = fopen(fname, "r"); 789 fp = fopen(fname, "r");
784 if (!fp) { 790 if (!fp) {
785 pr_warning("Failed to open %s: %s\n", fname, strerror(errno)); 791 pr_warning("Failed to open %s: %s\n", fname,
792 strerror_r(errno, sbuf, sizeof(sbuf)));
786 return -errno; 793 return -errno;
787 } 794 }
788 795
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 12aa9b0d0ba1..3dda85ca50c1 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -736,7 +736,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) 736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
737 return NULL; 737 return NULL;
738 738
739 n = poll(evlist->pollfd, evlist->nr_fds, timeout); 739 n = perf_evlist__poll(evlist, timeout);
740 if (n < 0) { 740 if (n < 0) {
741 PyErr_SetFromErrno(PyExc_OSError); 741 PyErr_SetFromErrno(PyExc_OSError);
742 return NULL; 742 return NULL;
@@ -753,9 +753,9 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
753 PyObject *list = PyList_New(0); 753 PyObject *list = PyList_New(0);
754 int i; 754 int i;
755 755
756 for (i = 0; i < evlist->nr_fds; ++i) { 756 for (i = 0; i < evlist->pollfd.nr; ++i) {
757 PyObject *file; 757 PyObject *file;
758 FILE *fp = fdopen(evlist->pollfd[i].fd, "r"); 758 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
759 759
760 if (fp == NULL) 760 if (fp == NULL)
761 goto free_list; 761 goto free_list;
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index fe8079edbdc1..cf69325b985f 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -14,6 +14,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
14 struct perf_evsel *evsel; 14 struct perf_evsel *evsel;
15 unsigned long flags = perf_event_open_cloexec_flag(); 15 unsigned long flags = perf_event_open_cloexec_flag();
16 int err = -EAGAIN, fd; 16 int err = -EAGAIN, fd;
17 static pid_t pid = -1;
17 18
18 evlist = perf_evlist__new(); 19 evlist = perf_evlist__new();
19 if (!evlist) 20 if (!evlist)
@@ -24,14 +25,22 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
24 25
25 evsel = perf_evlist__first(evlist); 26 evsel = perf_evlist__first(evlist);
26 27
27 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 28 while (1) {
28 if (fd < 0) 29 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
29 goto out_delete; 30 if (fd < 0) {
31 if (pid == -1 && errno == EACCES) {
32 pid = 0;
33 continue;
34 }
35 goto out_delete;
36 }
37 break;
38 }
30 close(fd); 39 close(fd);
31 40
32 fn(evsel); 41 fn(evsel);
33 42
34 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 43 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
35 if (fd < 0) { 44 if (fd < 0) {
36 if (errno == EINVAL) 45 if (errno == EINVAL)
37 err = -EINVAL; 46 err = -EINVAL;
@@ -47,7 +56,7 @@ out_delete:
47 56
48static bool perf_probe_api(setup_probe_fn_t fn) 57static bool perf_probe_api(setup_probe_fn_t fn)
49{ 58{
50 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock", NULL}; 59 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
51 struct cpu_map *cpus; 60 struct cpu_map *cpus;
52 int cpu, ret, i = 0; 61 int cpu, ret, i = 0;
53 62
@@ -106,7 +115,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
106 115
107 evlist__for_each(evlist, evsel) { 116 evlist__for_each(evlist, evsel) {
108 perf_evsel__config(evsel, opts); 117 perf_evsel__config(evsel, opts);
109 if (!evsel->idx && use_comm_exec) 118 if (evsel->tracking && use_comm_exec)
110 evsel->attr.comm_exec = 1; 119 evsel->attr.comm_exec = 1;
111 } 120 }
112 121
@@ -201,6 +210,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
201 struct perf_evsel *evsel; 210 struct perf_evsel *evsel;
202 int err, fd, cpu; 211 int err, fd, cpu;
203 bool ret = false; 212 bool ret = false;
213 pid_t pid = -1;
204 214
205 temp_evlist = perf_evlist__new(); 215 temp_evlist = perf_evlist__new();
206 if (!temp_evlist) 216 if (!temp_evlist)
@@ -221,12 +231,20 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
221 cpu = evlist->cpus->map[0]; 231 cpu = evlist->cpus->map[0];
222 } 232 }
223 233
224 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 234 while (1) {
225 perf_event_open_cloexec_flag()); 235 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
226 if (fd >= 0) { 236 perf_event_open_cloexec_flag());
227 close(fd); 237 if (fd < 0) {
228 ret = true; 238 if (pid == -1 && errno == EACCES) {
239 pid = 0;
240 continue;
241 }
242 goto out_delete;
243 }
244 break;
229 } 245 }
246 close(fd);
247 ret = true;
230 248
231out_delete: 249out_delete:
232 perf_evlist__delete(temp_evlist); 250 perf_evlist__delete(temp_evlist);
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index da8e9b285f51..34622b53e733 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -1,6 +1,7 @@
1#include "cache.h" 1#include "cache.h"
2#include "run-command.h" 2#include "run-command.h"
3#include "exec_cmd.h" 3#include "exec_cmd.h"
4#include "debug.h"
4 5
5static inline void close_pair(int fd[2]) 6static inline void close_pair(int fd[2])
6{ 7{
@@ -19,6 +20,7 @@ int start_command(struct child_process *cmd)
19{ 20{
20 int need_in, need_out, need_err; 21 int need_in, need_out, need_err;
21 int fdin[2], fdout[2], fderr[2]; 22 int fdin[2], fdout[2], fderr[2];
23 char sbuf[STRERR_BUFSIZE];
22 24
23 /* 25 /*
24 * In case of errors we must keep the promise to close FDs 26 * In case of errors we must keep the promise to close FDs
@@ -99,7 +101,7 @@ int start_command(struct child_process *cmd)
99 101
100 if (cmd->dir && chdir(cmd->dir)) 102 if (cmd->dir && chdir(cmd->dir))
101 die("exec %s: cd to %s failed (%s)", cmd->argv[0], 103 die("exec %s: cd to %s failed (%s)", cmd->argv[0],
102 cmd->dir, strerror(errno)); 104 cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf)));
103 if (cmd->env) { 105 if (cmd->env) {
104 for (; *cmd->env; cmd->env++) { 106 for (; *cmd->env; cmd->env++) {
105 if (strchr(*cmd->env, '=')) 107 if (strchr(*cmd->env, '='))
@@ -153,6 +155,8 @@ int start_command(struct child_process *cmd)
153 155
154static int wait_or_whine(pid_t pid) 156static int wait_or_whine(pid_t pid)
155{ 157{
158 char sbuf[STRERR_BUFSIZE];
159
156 for (;;) { 160 for (;;) {
157 int status, code; 161 int status, code;
158 pid_t waiting = waitpid(pid, &status, 0); 162 pid_t waiting = waitpid(pid, &status, 0);
@@ -160,7 +164,8 @@ static int wait_or_whine(pid_t pid)
160 if (waiting < 0) { 164 if (waiting < 0) {
161 if (errno == EINTR) 165 if (errno == EINTR)
162 continue; 166 continue;
163 error("waitpid failed (%s)", strerror(errno)); 167 error("waitpid failed (%s)",
168 strerror_r(errno, sbuf, sizeof(sbuf)));
164 return -ERR_RUN_COMMAND_WAITPID; 169 return -ERR_RUN_COMMAND_WAITPID;
165 } 170 }
166 if (waiting != pid) 171 if (waiting != pid)
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b2dba9c0a3a1..0a01bac4ce02 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -432,6 +432,11 @@ error:
432 return err; 432 return err;
433} 433}
434 434
435static int perl_flush_script(void)
436{
437 return 0;
438}
439
435/* 440/*
436 * Stop trace script 441 * Stop trace script
437 */ 442 */
@@ -633,6 +638,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
633struct scripting_ops perl_scripting_ops = { 638struct scripting_ops perl_scripting_ops = {
634 .name = "Perl", 639 .name = "Perl",
635 .start_script = perl_start_script, 640 .start_script = perl_start_script,
641 .flush_script = perl_flush_script,
636 .stop_script = perl_stop_script, 642 .stop_script = perl_stop_script,
637 .process_event = perl_process_event, 643 .process_event = perl_process_event,
638 .generate_script = perl_generate_script, 644 .generate_script = perl_generate_script,
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cbce2545da45..496f21cadd97 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -28,6 +28,7 @@
28 28
29#include "../../perf.h" 29#include "../../perf.h"
30#include "../debug.h" 30#include "../debug.h"
31#include "../callchain.h"
31#include "../evsel.h" 32#include "../evsel.h"
32#include "../util.h" 33#include "../util.h"
33#include "../event.h" 34#include "../event.h"
@@ -73,6 +74,35 @@ static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObj
73 Py_DECREF(val); 74 Py_DECREF(val);
74} 75}
75 76
77static PyObject *get_handler(const char *handler_name)
78{
79 PyObject *handler;
80
81 handler = PyDict_GetItemString(main_dict, handler_name);
82 if (handler && !PyCallable_Check(handler))
83 return NULL;
84 return handler;
85}
86
87static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
88{
89 PyObject *retval;
90
91 retval = PyObject_CallObject(handler, args);
92 if (retval == NULL)
93 handler_call_die(die_msg);
94 Py_DECREF(retval);
95}
96
97static void try_call_object(const char *handler_name, PyObject *args)
98{
99 PyObject *handler;
100
101 handler = get_handler(handler_name);
102 if (handler)
103 call_object(handler, args, handler_name);
104}
105
76static void define_value(enum print_arg_type field_type, 106static void define_value(enum print_arg_type field_type,
77 const char *ev_name, 107 const char *ev_name,
78 const char *field_name, 108 const char *field_name,
@@ -80,7 +110,7 @@ static void define_value(enum print_arg_type field_type,
80 const char *field_str) 110 const char *field_str)
81{ 111{
82 const char *handler_name = "define_flag_value"; 112 const char *handler_name = "define_flag_value";
83 PyObject *handler, *t, *retval; 113 PyObject *t;
84 unsigned long long value; 114 unsigned long long value;
85 unsigned n = 0; 115 unsigned n = 0;
86 116
@@ -98,13 +128,7 @@ static void define_value(enum print_arg_type field_type,
98 PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 128 PyTuple_SetItem(t, n++, PyInt_FromLong(value));
99 PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 129 PyTuple_SetItem(t, n++, PyString_FromString(field_str));
100 130
101 handler = PyDict_GetItemString(main_dict, handler_name); 131 try_call_object(handler_name, t);
102 if (handler && PyCallable_Check(handler)) {
103 retval = PyObject_CallObject(handler, t);
104 if (retval == NULL)
105 handler_call_die(handler_name);
106 Py_DECREF(retval);
107 }
108 132
109 Py_DECREF(t); 133 Py_DECREF(t);
110} 134}
@@ -127,7 +151,7 @@ static void define_field(enum print_arg_type field_type,
127 const char *delim) 151 const char *delim)
128{ 152{
129 const char *handler_name = "define_flag_field"; 153 const char *handler_name = "define_flag_field";
130 PyObject *handler, *t, *retval; 154 PyObject *t;
131 unsigned n = 0; 155 unsigned n = 0;
132 156
133 if (field_type == PRINT_SYMBOL) 157 if (field_type == PRINT_SYMBOL)
@@ -145,13 +169,7 @@ static void define_field(enum print_arg_type field_type,
145 if (field_type == PRINT_FLAGS) 169 if (field_type == PRINT_FLAGS)
146 PyTuple_SetItem(t, n++, PyString_FromString(delim)); 170 PyTuple_SetItem(t, n++, PyString_FromString(delim));
147 171
148 handler = PyDict_GetItemString(main_dict, handler_name); 172 try_call_object(handler_name, t);
149 if (handler && PyCallable_Check(handler)) {
150 retval = PyObject_CallObject(handler, t);
151 if (retval == NULL)
152 handler_call_die(handler_name);
153 Py_DECREF(retval);
154 }
155 173
156 Py_DECREF(t); 174 Py_DECREF(t);
157} 175}
@@ -362,7 +380,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
362 struct thread *thread, 380 struct thread *thread,
363 struct addr_location *al) 381 struct addr_location *al)
364{ 382{
365 PyObject *handler, *retval, *context, *t, *obj, *callchain; 383 PyObject *handler, *context, *t, *obj, *callchain;
366 PyObject *dict = NULL; 384 PyObject *dict = NULL;
367 static char handler_name[256]; 385 static char handler_name[256];
368 struct format_field *field; 386 struct format_field *field;
@@ -387,9 +405,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
387 405
388 sprintf(handler_name, "%s__%s", event->system, event->name); 406 sprintf(handler_name, "%s__%s", event->system, event->name);
389 407
390 handler = PyDict_GetItemString(main_dict, handler_name); 408 handler = get_handler(handler_name);
391 if (handler && !PyCallable_Check(handler))
392 handler = NULL;
393 if (!handler) { 409 if (!handler) {
394 dict = PyDict_New(); 410 dict = PyDict_New();
395 if (!dict) 411 if (!dict)
@@ -450,19 +466,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
450 Py_FatalError("error resizing Python tuple"); 466 Py_FatalError("error resizing Python tuple");
451 467
452 if (handler) { 468 if (handler) {
453 retval = PyObject_CallObject(handler, t); 469 call_object(handler, t, handler_name);
454 if (retval == NULL)
455 handler_call_die(handler_name);
456 Py_DECREF(retval);
457 } else { 470 } else {
458 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 471 try_call_object("trace_unhandled", t);
459 if (handler && PyCallable_Check(handler)) {
460
461 retval = PyObject_CallObject(handler, t);
462 if (retval == NULL)
463 handler_call_die("trace_unhandled");
464 Py_DECREF(retval);
465 }
466 Py_DECREF(dict); 472 Py_DECREF(dict);
467 } 473 }
468 474
@@ -474,7 +480,7 @@ static void python_process_general_event(struct perf_sample *sample,
474 struct thread *thread, 480 struct thread *thread,
475 struct addr_location *al) 481 struct addr_location *al)
476{ 482{
477 PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; 483 PyObject *handler, *t, *dict, *callchain, *dict_sample;
478 static char handler_name[64]; 484 static char handler_name[64];
479 unsigned n = 0; 485 unsigned n = 0;
480 486
@@ -496,8 +502,8 @@ static void python_process_general_event(struct perf_sample *sample,
496 502
497 snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); 503 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
498 504
499 handler = PyDict_GetItemString(main_dict, handler_name); 505 handler = get_handler(handler_name);
500 if (!handler || !PyCallable_Check(handler)) 506 if (!handler)
501 goto exit; 507 goto exit;
502 508
503 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 509 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
@@ -539,10 +545,7 @@ static void python_process_general_event(struct perf_sample *sample,
539 if (_PyTuple_Resize(&t, n) == -1) 545 if (_PyTuple_Resize(&t, n) == -1)
540 Py_FatalError("error resizing Python tuple"); 546 Py_FatalError("error resizing Python tuple");
541 547
542 retval = PyObject_CallObject(handler, t); 548 call_object(handler, t, handler_name);
543 if (retval == NULL)
544 handler_call_die(handler_name);
545 Py_DECREF(retval);
546exit: 549exit:
547 Py_DECREF(dict); 550 Py_DECREF(dict);
548 Py_DECREF(t); 551 Py_DECREF(t);
@@ -566,36 +569,24 @@ static void python_process_event(union perf_event *event __maybe_unused,
566 569
567static int run_start_sub(void) 570static int run_start_sub(void)
568{ 571{
569 PyObject *handler, *retval;
570 int err = 0;
571
572 main_module = PyImport_AddModule("__main__"); 572 main_module = PyImport_AddModule("__main__");
573 if (main_module == NULL) 573 if (main_module == NULL)
574 return -1; 574 return -1;
575 Py_INCREF(main_module); 575 Py_INCREF(main_module);
576 576
577 main_dict = PyModule_GetDict(main_module); 577 main_dict = PyModule_GetDict(main_module);
578 if (main_dict == NULL) { 578 if (main_dict == NULL)
579 err = -1;
580 goto error; 579 goto error;
581 }
582 Py_INCREF(main_dict); 580 Py_INCREF(main_dict);
583 581
584 handler = PyDict_GetItemString(main_dict, "trace_begin"); 582 try_call_object("trace_begin", NULL);
585 if (handler == NULL || !PyCallable_Check(handler))
586 goto out;
587 583
588 retval = PyObject_CallObject(handler, NULL); 584 return 0;
589 if (retval == NULL)
590 handler_call_die("trace_begin");
591 585
592 Py_DECREF(retval);
593 return err;
594error: 586error:
595 Py_XDECREF(main_dict); 587 Py_XDECREF(main_dict);
596 Py_XDECREF(main_module); 588 Py_XDECREF(main_module);
597out: 589 return -1;
598 return err;
599} 590}
600 591
601/* 592/*
@@ -649,28 +640,23 @@ error:
649 return err; 640 return err;
650} 641}
651 642
643static int python_flush_script(void)
644{
645 return 0;
646}
647
652/* 648/*
653 * Stop trace script 649 * Stop trace script
654 */ 650 */
655static int python_stop_script(void) 651static int python_stop_script(void)
656{ 652{
657 PyObject *handler, *retval; 653 try_call_object("trace_end", NULL);
658 int err = 0;
659 654
660 handler = PyDict_GetItemString(main_dict, "trace_end");
661 if (handler == NULL || !PyCallable_Check(handler))
662 goto out;
663
664 retval = PyObject_CallObject(handler, NULL);
665 if (retval == NULL)
666 handler_call_die("trace_end");
667 Py_DECREF(retval);
668out:
669 Py_XDECREF(main_dict); 655 Py_XDECREF(main_dict);
670 Py_XDECREF(main_module); 656 Py_XDECREF(main_module);
671 Py_Finalize(); 657 Py_Finalize();
672 658
673 return err; 659 return 0;
674} 660}
675 661
676static int python_generate_script(struct pevent *pevent, const char *outfile) 662static int python_generate_script(struct pevent *pevent, const char *outfile)
@@ -843,6 +829,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
843struct scripting_ops python_scripting_ops = { 829struct scripting_ops python_scripting_ops = {
844 .name = "Python", 830 .name = "Python",
845 .start_script = python_start_script, 831 .start_script = python_start_script,
832 .flush_script = python_flush_script,
846 .stop_script = python_stop_script, 833 .stop_script = python_stop_script,
847 .process_event = python_process_event, 834 .process_event = python_process_event,
848 .generate_script = python_generate_script, 835 .generate_script = python_generate_script,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 88dfef70c13d..6702ac28754b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,7 @@
14#include "util.h" 14#include "util.h"
15#include "cpumap.h" 15#include "cpumap.h"
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "asm/bug.h"
17 18
18static int perf_session__open(struct perf_session *session) 19static int perf_session__open(struct perf_session *session)
19{ 20{
@@ -66,6 +67,25 @@ static void perf_session__destroy_kernel_maps(struct perf_session *session)
66 machines__destroy_kernel_maps(&session->machines); 67 machines__destroy_kernel_maps(&session->machines);
67} 68}
68 69
70static bool perf_session__has_comm_exec(struct perf_session *session)
71{
72 struct perf_evsel *evsel;
73
74 evlist__for_each(session->evlist, evsel) {
75 if (evsel->attr.comm_exec)
76 return true;
77 }
78
79 return false;
80}
81
82static void perf_session__set_comm_exec(struct perf_session *session)
83{
84 bool comm_exec = perf_session__has_comm_exec(session);
85
86 machines__set_comm_exec(&session->machines, comm_exec);
87}
88
69struct perf_session *perf_session__new(struct perf_data_file *file, 89struct perf_session *perf_session__new(struct perf_data_file *file,
70 bool repipe, struct perf_tool *tool) 90 bool repipe, struct perf_tool *tool)
71{ 91{
@@ -75,9 +95,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
75 goto out; 95 goto out;
76 96
77 session->repipe = repipe; 97 session->repipe = repipe;
78 INIT_LIST_HEAD(&session->ordered_samples.samples); 98 ordered_events__init(&session->ordered_events);
79 INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
80 INIT_LIST_HEAD(&session->ordered_samples.to_free);
81 machines__init(&session->machines); 99 machines__init(&session->machines);
82 100
83 if (file) { 101 if (file) {
@@ -91,6 +109,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
91 goto out_close; 109 goto out_close;
92 110
93 perf_session__set_id_hdr_size(session); 111 perf_session__set_id_hdr_size(session);
112 perf_session__set_comm_exec(session);
94 } 113 }
95 } 114 }
96 115
@@ -100,13 +119,13 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
100 * kernel MMAP event, in perf_event__process_mmap(). 119 * kernel MMAP event, in perf_event__process_mmap().
101 */ 120 */
102 if (perf_session__create_kernel_maps(session) < 0) 121 if (perf_session__create_kernel_maps(session) < 0)
103 goto out_delete; 122 pr_warning("Cannot read kernel map\n");
104 } 123 }
105 124
106 if (tool && tool->ordering_requires_timestamps && 125 if (tool && tool->ordering_requires_timestamps &&
107 tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) { 126 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
108 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 127 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
109 tool->ordered_samples = false; 128 tool->ordered_events = false;
110 } 129 }
111 130
112 return session; 131 return session;
@@ -238,7 +257,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
238 if (tool->build_id == NULL) 257 if (tool->build_id == NULL)
239 tool->build_id = process_finished_round_stub; 258 tool->build_id = process_finished_round_stub;
240 if (tool->finished_round == NULL) { 259 if (tool->finished_round == NULL) {
241 if (tool->ordered_samples) 260 if (tool->ordered_events)
242 tool->finished_round = process_finished_round; 261 tool->finished_round = process_finished_round;
243 else 262 else
244 tool->finished_round = process_finished_round_stub; 263 tool->finished_round = process_finished_round_stub;
@@ -444,87 +463,6 @@ static perf_event__swap_op perf_event__swap_ops[] = {
444 [PERF_RECORD_HEADER_MAX] = NULL, 463 [PERF_RECORD_HEADER_MAX] = NULL,
445}; 464};
446 465
447struct sample_queue {
448 u64 timestamp;
449 u64 file_offset;
450 union perf_event *event;
451 struct list_head list;
452};
453
454static void perf_session_free_sample_buffers(struct perf_session *session)
455{
456 struct ordered_samples *os = &session->ordered_samples;
457
458 while (!list_empty(&os->to_free)) {
459 struct sample_queue *sq;
460
461 sq = list_entry(os->to_free.next, struct sample_queue, list);
462 list_del(&sq->list);
463 free(sq);
464 }
465}
466
467static int perf_session_deliver_event(struct perf_session *session,
468 union perf_event *event,
469 struct perf_sample *sample,
470 struct perf_tool *tool,
471 u64 file_offset);
472
473static int flush_sample_queue(struct perf_session *s,
474 struct perf_tool *tool)
475{
476 struct ordered_samples *os = &s->ordered_samples;
477 struct list_head *head = &os->samples;
478 struct sample_queue *tmp, *iter;
479 struct perf_sample sample;
480 u64 limit = os->next_flush;
481 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
482 bool show_progress = limit == ULLONG_MAX;
483 struct ui_progress prog;
484 int ret;
485
486 if (!tool->ordered_samples || !limit)
487 return 0;
488
489 if (show_progress)
490 ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
491
492 list_for_each_entry_safe(iter, tmp, head, list) {
493 if (session_done())
494 return 0;
495
496 if (iter->timestamp > limit)
497 break;
498
499 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
500 if (ret)
501 pr_err("Can't parse sample, err = %d\n", ret);
502 else {
503 ret = perf_session_deliver_event(s, iter->event, &sample, tool,
504 iter->file_offset);
505 if (ret)
506 return ret;
507 }
508
509 os->last_flush = iter->timestamp;
510 list_del(&iter->list);
511 list_add(&iter->list, &os->sample_cache);
512 os->nr_samples--;
513
514 if (show_progress)
515 ui_progress__update(&prog, 1);
516 }
517
518 if (list_empty(head)) {
519 os->last_sample = NULL;
520 } else if (last_ts <= limit) {
521 os->last_sample =
522 list_entry(head->prev, struct sample_queue, list);
523 }
524
525 return 0;
526}
527
528/* 466/*
529 * When perf record finishes a pass on every buffers, it records this pseudo 467 * When perf record finishes a pass on every buffers, it records this pseudo
530 * event. 468 * event.
@@ -568,99 +506,42 @@ static int process_finished_round(struct perf_tool *tool,
568 union perf_event *event __maybe_unused, 506 union perf_event *event __maybe_unused,
569 struct perf_session *session) 507 struct perf_session *session)
570{ 508{
571 int ret = flush_sample_queue(session, tool); 509 return ordered_events__flush(session, tool, OE_FLUSH__ROUND);
572 if (!ret)
573 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
574
575 return ret;
576}
577
578/* The queue is ordered by time */
579static void __queue_event(struct sample_queue *new, struct perf_session *s)
580{
581 struct ordered_samples *os = &s->ordered_samples;
582 struct sample_queue *sample = os->last_sample;
583 u64 timestamp = new->timestamp;
584 struct list_head *p;
585
586 ++os->nr_samples;
587 os->last_sample = new;
588
589 if (!sample) {
590 list_add(&new->list, &os->samples);
591 os->max_timestamp = timestamp;
592 return;
593 }
594
595 /*
596 * last_sample might point to some random place in the list as it's
597 * the last queued event. We expect that the new event is close to
598 * this.
599 */
600 if (sample->timestamp <= timestamp) {
601 while (sample->timestamp <= timestamp) {
602 p = sample->list.next;
603 if (p == &os->samples) {
604 list_add_tail(&new->list, &os->samples);
605 os->max_timestamp = timestamp;
606 return;
607 }
608 sample = list_entry(p, struct sample_queue, list);
609 }
610 list_add_tail(&new->list, &sample->list);
611 } else {
612 while (sample->timestamp > timestamp) {
613 p = sample->list.prev;
614 if (p == &os->samples) {
615 list_add(&new->list, &os->samples);
616 return;
617 }
618 sample = list_entry(p, struct sample_queue, list);
619 }
620 list_add(&new->list, &sample->list);
621 }
622} 510}
623 511
624#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
625
626int perf_session_queue_event(struct perf_session *s, union perf_event *event, 512int perf_session_queue_event(struct perf_session *s, union perf_event *event,
627 struct perf_sample *sample, u64 file_offset) 513 struct perf_tool *tool, struct perf_sample *sample,
514 u64 file_offset)
628{ 515{
629 struct ordered_samples *os = &s->ordered_samples; 516 struct ordered_events *oe = &s->ordered_events;
630 struct list_head *sc = &os->sample_cache;
631 u64 timestamp = sample->time; 517 u64 timestamp = sample->time;
632 struct sample_queue *new; 518 struct ordered_event *new;
633 519
634 if (!timestamp || timestamp == ~0ULL) 520 if (!timestamp || timestamp == ~0ULL)
635 return -ETIME; 521 return -ETIME;
636 522
637 if (timestamp < s->ordered_samples.last_flush) { 523 if (timestamp < oe->last_flush) {
638 printf("Warning: Timestamp below last timeslice flush\n"); 524 WARN_ONCE(1, "Timestamp below last timeslice flush\n");
639 return -EINVAL;
640 }
641 525
642 if (!list_empty(sc)) { 526 pr_oe_time(timestamp, "out of order event");
643 new = list_entry(sc->next, struct sample_queue, list); 527 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
644 list_del(&new->list); 528 oe->last_flush_type);
645 } else if (os->sample_buffer) { 529
646 new = os->sample_buffer + os->sample_buffer_idx; 530 /* We could get out of order messages after forced flush. */
647 if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER) 531 if (oe->last_flush_type != OE_FLUSH__HALF)
648 os->sample_buffer = NULL; 532 return -EINVAL;
649 } else {
650 os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
651 if (!os->sample_buffer)
652 return -ENOMEM;
653 list_add(&os->sample_buffer->list, &os->to_free);
654 os->sample_buffer_idx = 2;
655 new = os->sample_buffer + 1;
656 } 533 }
657 534
658 new->timestamp = timestamp; 535 new = ordered_events__new(oe, timestamp, event);
659 new->file_offset = file_offset; 536 if (!new) {
660 new->event = event; 537 ordered_events__flush(s, tool, OE_FLUSH__HALF);
538 new = ordered_events__new(oe, timestamp, event);
539 }
661 540
662 __queue_event(new, s); 541 if (!new)
542 return -ENOMEM;
663 543
544 new->file_offset = file_offset;
664 return 0; 545 return 0;
665} 546}
666 547
@@ -920,11 +801,10 @@ perf_session__deliver_sample(struct perf_session *session,
920 &sample->read.one, machine); 801 &sample->read.one, machine);
921} 802}
922 803
923static int perf_session_deliver_event(struct perf_session *session, 804int perf_session__deliver_event(struct perf_session *session,
924 union perf_event *event, 805 union perf_event *event,
925 struct perf_sample *sample, 806 struct perf_sample *sample,
926 struct perf_tool *tool, 807 struct perf_tool *tool, u64 file_offset)
927 u64 file_offset)
928{ 808{
929 struct perf_evsel *evsel; 809 struct perf_evsel *evsel;
930 struct machine *machine; 810 struct machine *machine;
@@ -932,22 +812,6 @@ static int perf_session_deliver_event(struct perf_session *session,
932 dump_event(session, event, file_offset, sample); 812 dump_event(session, event, file_offset, sample);
933 813
934 evsel = perf_evlist__id2evsel(session->evlist, sample->id); 814 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
935 if (evsel != NULL && event->header.type != PERF_RECORD_SAMPLE) {
936 /*
937 * XXX We're leaving PERF_RECORD_SAMPLE unnacounted here
938 * because the tools right now may apply filters, discarding
939 * some of the samples. For consistency, in the future we
940 * should have something like nr_filtered_samples and remove
941 * the sample->period from total_sample_period, etc, KISS for
942 * now tho.
943 *
944 * Also testing against NULL allows us to handle files without
945 * attr.sample_id_all and/or without PERF_SAMPLE_ID. In the
946 * future probably it'll be a good idea to restrict event
947 * processing via perf_session to files with both set.
948 */
949 hists__inc_nr_events(&evsel->hists, event->header.type);
950 }
951 815
952 machine = perf_session__find_machine_for_cpumode(session, event, 816 machine = perf_session__find_machine_for_cpumode(session, event,
953 sample); 817 sample);
@@ -1005,8 +869,10 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1005 switch (event->header.type) { 869 switch (event->header.type) {
1006 case PERF_RECORD_HEADER_ATTR: 870 case PERF_RECORD_HEADER_ATTR:
1007 err = tool->attr(tool, event, &session->evlist); 871 err = tool->attr(tool, event, &session->evlist);
1008 if (err == 0) 872 if (err == 0) {
1009 perf_session__set_id_hdr_size(session); 873 perf_session__set_id_hdr_size(session);
874 perf_session__set_comm_exec(session);
875 }
1010 return err; 876 return err;
1011 case PERF_RECORD_HEADER_EVENT_TYPE: 877 case PERF_RECORD_HEADER_EVENT_TYPE:
1012 /* 878 /*
@@ -1036,6 +902,61 @@ static void event_swap(union perf_event *event, bool sample_id_all)
1036 swap(event, sample_id_all); 902 swap(event, sample_id_all);
1037} 903}
1038 904
905int perf_session__peek_event(struct perf_session *session, off_t file_offset,
906 void *buf, size_t buf_sz,
907 union perf_event **event_ptr,
908 struct perf_sample *sample)
909{
910 union perf_event *event;
911 size_t hdr_sz, rest;
912 int fd;
913
914 if (session->one_mmap && !session->header.needs_swap) {
915 event = file_offset - session->one_mmap_offset +
916 session->one_mmap_addr;
917 goto out_parse_sample;
918 }
919
920 if (perf_data_file__is_pipe(session->file))
921 return -1;
922
923 fd = perf_data_file__fd(session->file);
924 hdr_sz = sizeof(struct perf_event_header);
925
926 if (buf_sz < hdr_sz)
927 return -1;
928
929 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||
930 readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz)
931 return -1;
932
933 event = (union perf_event *)buf;
934
935 if (session->header.needs_swap)
936 perf_event_header__bswap(&event->header);
937
938 if (event->header.size < hdr_sz)
939 return -1;
940
941 rest = event->header.size - hdr_sz;
942
943 if (readn(fd, &buf, rest) != (ssize_t)rest)
944 return -1;
945
946 if (session->header.needs_swap)
947 event_swap(event, perf_evlist__sample_id_all(session->evlist));
948
949out_parse_sample:
950
951 if (sample && event->header.type < PERF_RECORD_USER_TYPE_START &&
952 perf_evlist__parse_sample(session->evlist, event, sample))
953 return -1;
954
955 *event_ptr = event;
956
957 return 0;
958}
959
1039static s64 perf_session__process_event(struct perf_session *session, 960static s64 perf_session__process_event(struct perf_session *session,
1040 union perf_event *event, 961 union perf_event *event,
1041 struct perf_tool *tool, 962 struct perf_tool *tool,
@@ -1062,15 +983,15 @@ static s64 perf_session__process_event(struct perf_session *session,
1062 if (ret) 983 if (ret)
1063 return ret; 984 return ret;
1064 985
1065 if (tool->ordered_samples) { 986 if (tool->ordered_events) {
1066 ret = perf_session_queue_event(session, event, &sample, 987 ret = perf_session_queue_event(session, event, tool, &sample,
1067 file_offset); 988 file_offset);
1068 if (ret != -ETIME) 989 if (ret != -ETIME)
1069 return ret; 990 return ret;
1070 } 991 }
1071 992
1072 return perf_session_deliver_event(session, event, &sample, tool, 993 return perf_session__deliver_event(session, event, &sample, tool,
1073 file_offset); 994 file_offset);
1074} 995}
1075 996
1076void perf_event_header__bswap(struct perf_event_header *hdr) 997void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1222,12 +1143,11 @@ more:
1222 goto more; 1143 goto more;
1223done: 1144done:
1224 /* do the final flush for ordered samples */ 1145 /* do the final flush for ordered samples */
1225 session->ordered_samples.next_flush = ULLONG_MAX; 1146 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1226 err = flush_sample_queue(session, tool);
1227out_err: 1147out_err:
1228 free(buf); 1148 free(buf);
1229 perf_session__warn_about_errors(session, tool); 1149 perf_session__warn_about_errors(session, tool);
1230 perf_session_free_sample_buffers(session); 1150 ordered_events__free(&session->ordered_events);
1231 return err; 1151 return err;
1232} 1152}
1233 1153
@@ -1368,12 +1288,11 @@ more:
1368 1288
1369out: 1289out:
1370 /* do the final flush for ordered samples */ 1290 /* do the final flush for ordered samples */
1371 session->ordered_samples.next_flush = ULLONG_MAX; 1291 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1372 err = flush_sample_queue(session, tool);
1373out_err: 1292out_err:
1374 ui_progress__finish(); 1293 ui_progress__finish();
1375 perf_session__warn_about_errors(session, tool); 1294 perf_session__warn_about_errors(session, tool);
1376 perf_session_free_sample_buffers(session); 1295 ordered_events__free(&session->ordered_events);
1377 session->one_mmap = false; 1296 session->one_mmap = false;
1378 return err; 1297 return err;
1379} 1298}
@@ -1455,16 +1374,9 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp
1455 1374
1456size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) 1375size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1457{ 1376{
1458 struct perf_evsel *pos;
1459 size_t ret = fprintf(fp, "Aggregated stats:\n"); 1377 size_t ret = fprintf(fp, "Aggregated stats:\n");
1460 1378
1461 ret += events_stats__fprintf(&session->stats, fp); 1379 ret += events_stats__fprintf(&session->stats, fp);
1462
1463 evlist__for_each(session->evlist, pos) {
1464 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1465 ret += events_stats__fprintf(&pos->hists.stats, fp);
1466 }
1467
1468 return ret; 1380 return ret;
1469} 1381}
1470 1382
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0321013bd9fd..a4be851f1a90 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -2,33 +2,19 @@
2#define __PERF_SESSION_H 2#define __PERF_SESSION_H
3 3
4#include "trace-event.h" 4#include "trace-event.h"
5#include "hist.h"
6#include "event.h" 5#include "event.h"
7#include "header.h" 6#include "header.h"
8#include "machine.h" 7#include "machine.h"
9#include "symbol.h" 8#include "symbol.h"
10#include "thread.h" 9#include "thread.h"
11#include "data.h" 10#include "data.h"
11#include "ordered-events.h"
12#include <linux/rbtree.h> 12#include <linux/rbtree.h>
13#include <linux/perf_event.h> 13#include <linux/perf_event.h>
14 14
15struct sample_queue;
16struct ip_callchain; 15struct ip_callchain;
17struct thread; 16struct thread;
18 17
19struct ordered_samples {
20 u64 last_flush;
21 u64 next_flush;
22 u64 max_timestamp;
23 struct list_head samples;
24 struct list_head sample_cache;
25 struct list_head to_free;
26 struct sample_queue *sample_buffer;
27 struct sample_queue *last_sample;
28 int sample_buffer_idx;
29 unsigned int nr_samples;
30};
31
32struct perf_session { 18struct perf_session {
33 struct perf_header header; 19 struct perf_header header;
34 struct machines machines; 20 struct machines machines;
@@ -39,7 +25,7 @@ struct perf_session {
39 bool one_mmap; 25 bool one_mmap;
40 void *one_mmap_addr; 26 void *one_mmap_addr;
41 u64 one_mmap_offset; 27 u64 one_mmap_offset;
42 struct ordered_samples ordered_samples; 28 struct ordered_events ordered_events;
43 struct perf_data_file *file; 29 struct perf_data_file *file;
44}; 30};
45 31
@@ -58,6 +44,11 @@ void perf_session__delete(struct perf_session *session);
58 44
59void perf_event_header__bswap(struct perf_event_header *hdr); 45void perf_event_header__bswap(struct perf_event_header *hdr);
60 46
47int perf_session__peek_event(struct perf_session *session, off_t file_offset,
48 void *buf, size_t buf_sz,
49 union perf_event **event_ptr,
50 struct perf_sample *sample);
51
61int __perf_session__process_events(struct perf_session *session, 52int __perf_session__process_events(struct perf_session *session,
62 u64 data_offset, u64 data_size, u64 size, 53 u64 data_offset, u64 data_size, u64 size,
63 struct perf_tool *tool); 54 struct perf_tool *tool);
@@ -65,10 +56,16 @@ int perf_session__process_events(struct perf_session *session,
65 struct perf_tool *tool); 56 struct perf_tool *tool);
66 57
67int perf_session_queue_event(struct perf_session *s, union perf_event *event, 58int perf_session_queue_event(struct perf_session *s, union perf_event *event,
68 struct perf_sample *sample, u64 file_offset); 59 struct perf_tool *tool, struct perf_sample *sample,
60 u64 file_offset);
69 61
70void perf_tool__fill_defaults(struct perf_tool *tool); 62void perf_tool__fill_defaults(struct perf_tool *tool);
71 63
64int perf_session__deliver_event(struct perf_session *session,
65 union perf_event *event,
66 struct perf_sample *sample,
67 struct perf_tool *tool, u64 file_offset);
68
72int perf_session__resolve_callchain(struct perf_session *session, 69int perf_session__resolve_callchain(struct perf_session *session,
73 struct perf_evsel *evsel, 70 struct perf_evsel *evsel,
74 struct thread *thread, 71 struct thread *thread,
@@ -128,5 +125,5 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
128 125
129extern volatile int session_done; 126extern volatile int session_done;
130 127
131#define session_done() (*(volatile int *)(&session_done)) 128#define session_done() ACCESS_ONCE(session_done)
132#endif /* __PERF_SESSION_H */ 129#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 14e5a039bc45..9402885a77f3 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -70,12 +70,14 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
70 size_t size, unsigned int width) 70 size_t size, unsigned int width)
71{ 71{
72 const char *comm = thread__comm_str(he->thread); 72 const char *comm = thread__comm_str(he->thread);
73 return repsep_snprintf(bf, size, "%*s:%5d", width - 6, 73
74 comm ?: "", he->thread->tid); 74 width = max(7U, width) - 6;
75 return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
76 width, width, comm ?: "");
75} 77}
76 78
77struct sort_entry sort_thread = { 79struct sort_entry sort_thread = {
78 .se_header = "Command: Pid", 80 .se_header = " Pid:Command",
79 .se_cmp = sort__thread_cmp, 81 .se_cmp = sort__thread_cmp,
80 .se_snprintf = hist_entry__thread_snprintf, 82 .se_snprintf = hist_entry__thread_snprintf,
81 .se_width_idx = HISTC_THREAD, 83 .se_width_idx = HISTC_THREAD,
@@ -106,7 +108,7 @@ sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
106static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, 108static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
107 size_t size, unsigned int width) 109 size_t size, unsigned int width)
108{ 110{
109 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm)); 111 return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
110} 112}
111 113
112struct sort_entry sort_comm = { 114struct sort_entry sort_comm = {
@@ -152,10 +154,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf,
152 if (map && map->dso) { 154 if (map && map->dso) {
153 const char *dso_name = !verbose ? map->dso->short_name : 155 const char *dso_name = !verbose ? map->dso->short_name :
154 map->dso->long_name; 156 map->dso->long_name;
155 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 157 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
156 } 158 }
157 159
158 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 160 return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
159} 161}
160 162
161static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, 163static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
@@ -257,7 +259,10 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
257 width - ret, ""); 259 width - ret, "");
258 } 260 }
259 261
260 return ret; 262 if (ret > width)
263 bf[width] = '\0';
264
265 return width;
261} 266}
262 267
263static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, 268static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
@@ -302,10 +307,9 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
302} 307}
303 308
304static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, 309static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
305 size_t size, 310 size_t size, unsigned int width)
306 unsigned int width __maybe_unused)
307{ 311{
308 return repsep_snprintf(bf, size, "%s", he->srcline); 312 return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline);
309} 313}
310 314
311struct sort_entry sort_srcline = { 315struct sort_entry sort_srcline = {
@@ -332,7 +336,7 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
332static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, 336static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
333 size_t size, unsigned int width) 337 size_t size, unsigned int width)
334{ 338{
335 return repsep_snprintf(bf, size, "%-*s", width, 339 return repsep_snprintf(bf, size, "%-*.*s", width, width,
336 he->parent ? he->parent->name : "[other]"); 340 he->parent ? he->parent->name : "[other]");
337} 341}
338 342
@@ -354,7 +358,7 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
354static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, 358static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
355 size_t size, unsigned int width) 359 size_t size, unsigned int width)
356{ 360{
357 return repsep_snprintf(bf, size, "%*d", width, he->cpu); 361 return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
358} 362}
359 363
360struct sort_entry sort_cpu = { 364struct sort_entry sort_cpu = {
@@ -369,6 +373,9 @@ struct sort_entry sort_cpu = {
369static int64_t 373static int64_t
370sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) 374sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
371{ 375{
376 if (!left->branch_info || !right->branch_info)
377 return cmp_null(left->branch_info, right->branch_info);
378
372 return _sort__dso_cmp(left->branch_info->from.map, 379 return _sort__dso_cmp(left->branch_info->from.map,
373 right->branch_info->from.map); 380 right->branch_info->from.map);
374} 381}
@@ -376,13 +383,19 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
376static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, 383static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
377 size_t size, unsigned int width) 384 size_t size, unsigned int width)
378{ 385{
379 return _hist_entry__dso_snprintf(he->branch_info->from.map, 386 if (he->branch_info)
380 bf, size, width); 387 return _hist_entry__dso_snprintf(he->branch_info->from.map,
388 bf, size, width);
389 else
390 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
381} 391}
382 392
383static int64_t 393static int64_t
384sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right) 394sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
385{ 395{
396 if (!left->branch_info || !right->branch_info)
397 return cmp_null(left->branch_info, right->branch_info);
398
386 return _sort__dso_cmp(left->branch_info->to.map, 399 return _sort__dso_cmp(left->branch_info->to.map,
387 right->branch_info->to.map); 400 right->branch_info->to.map);
388} 401}
@@ -390,8 +403,11 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
390static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, 403static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
391 size_t size, unsigned int width) 404 size_t size, unsigned int width)
392{ 405{
393 return _hist_entry__dso_snprintf(he->branch_info->to.map, 406 if (he->branch_info)
394 bf, size, width); 407 return _hist_entry__dso_snprintf(he->branch_info->to.map,
408 bf, size, width);
409 else
410 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
395} 411}
396 412
397static int64_t 413static int64_t
@@ -400,6 +416,12 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
400 struct addr_map_symbol *from_l = &left->branch_info->from; 416 struct addr_map_symbol *from_l = &left->branch_info->from;
401 struct addr_map_symbol *from_r = &right->branch_info->from; 417 struct addr_map_symbol *from_r = &right->branch_info->from;
402 418
419 if (!left->branch_info || !right->branch_info)
420 return cmp_null(left->branch_info, right->branch_info);
421
422 from_l = &left->branch_info->from;
423 from_r = &right->branch_info->from;
424
403 if (!from_l->sym && !from_r->sym) 425 if (!from_l->sym && !from_r->sym)
404 return _sort__addr_cmp(from_l->addr, from_r->addr); 426 return _sort__addr_cmp(from_l->addr, from_r->addr);
405 427
@@ -409,8 +431,13 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
409static int64_t 431static int64_t
410sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) 432sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
411{ 433{
412 struct addr_map_symbol *to_l = &left->branch_info->to; 434 struct addr_map_symbol *to_l, *to_r;
413 struct addr_map_symbol *to_r = &right->branch_info->to; 435
436 if (!left->branch_info || !right->branch_info)
437 return cmp_null(left->branch_info, right->branch_info);
438
439 to_l = &left->branch_info->to;
440 to_r = &right->branch_info->to;
414 441
415 if (!to_l->sym && !to_r->sym) 442 if (!to_l->sym && !to_r->sym)
416 return _sort__addr_cmp(to_l->addr, to_r->addr); 443 return _sort__addr_cmp(to_l->addr, to_r->addr);
@@ -421,19 +448,27 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
421static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, 448static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
422 size_t size, unsigned int width) 449 size_t size, unsigned int width)
423{ 450{
424 struct addr_map_symbol *from = &he->branch_info->from; 451 if (he->branch_info) {
425 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, 452 struct addr_map_symbol *from = &he->branch_info->from;
426 he->level, bf, size, width);
427 453
454 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
455 he->level, bf, size, width);
456 }
457
458 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
428} 459}
429 460
430static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf, 461static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
431 size_t size, unsigned int width) 462 size_t size, unsigned int width)
432{ 463{
433 struct addr_map_symbol *to = &he->branch_info->to; 464 if (he->branch_info) {
434 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, 465 struct addr_map_symbol *to = &he->branch_info->to;
435 he->level, bf, size, width);
436 466
467 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
468 he->level, bf, size, width);
469 }
470
471 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
437} 472}
438 473
439struct sort_entry sort_dso_from = { 474struct sort_entry sort_dso_from = {
@@ -467,11 +502,13 @@ struct sort_entry sort_sym_to = {
467static int64_t 502static int64_t
468sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right) 503sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
469{ 504{
470 const unsigned char mp = left->branch_info->flags.mispred != 505 unsigned char mp, p;
471 right->branch_info->flags.mispred;
472 const unsigned char p = left->branch_info->flags.predicted !=
473 right->branch_info->flags.predicted;
474 506
507 if (!left->branch_info || !right->branch_info)
508 return cmp_null(left->branch_info, right->branch_info);
509
510 mp = left->branch_info->flags.mispred != right->branch_info->flags.mispred;
511 p = left->branch_info->flags.predicted != right->branch_info->flags.predicted;
475 return mp || p; 512 return mp || p;
476} 513}
477 514
@@ -479,12 +516,14 @@ static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
479 size_t size, unsigned int width){ 516 size_t size, unsigned int width){
480 static const char *out = "N/A"; 517 static const char *out = "N/A";
481 518
482 if (he->branch_info->flags.predicted) 519 if (he->branch_info) {
483 out = "N"; 520 if (he->branch_info->flags.predicted)
484 else if (he->branch_info->flags.mispred) 521 out = "N";
485 out = "Y"; 522 else if (he->branch_info->flags.mispred)
523 out = "Y";
524 }
486 525
487 return repsep_snprintf(bf, size, "%-*s", width, out); 526 return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
488} 527}
489 528
490/* --sort daddr_sym */ 529/* --sort daddr_sym */
@@ -985,6 +1024,9 @@ struct sort_entry sort_mem_dcacheline = {
985static int64_t 1024static int64_t
986sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) 1025sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
987{ 1026{
1027 if (!left->branch_info || !right->branch_info)
1028 return cmp_null(left->branch_info, right->branch_info);
1029
988 return left->branch_info->flags.abort != 1030 return left->branch_info->flags.abort !=
989 right->branch_info->flags.abort; 1031 right->branch_info->flags.abort;
990} 1032}
@@ -992,10 +1034,15 @@ sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
992static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf, 1034static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
993 size_t size, unsigned int width) 1035 size_t size, unsigned int width)
994{ 1036{
995 static const char *out = "."; 1037 static const char *out = "N/A";
1038
1039 if (he->branch_info) {
1040 if (he->branch_info->flags.abort)
1041 out = "A";
1042 else
1043 out = ".";
1044 }
996 1045
997 if (he->branch_info->flags.abort)
998 out = "A";
999 return repsep_snprintf(bf, size, "%-*s", width, out); 1046 return repsep_snprintf(bf, size, "%-*s", width, out);
1000} 1047}
1001 1048
@@ -1009,6 +1056,9 @@ struct sort_entry sort_abort = {
1009static int64_t 1056static int64_t
1010sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right) 1057sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
1011{ 1058{
1059 if (!left->branch_info || !right->branch_info)
1060 return cmp_null(left->branch_info, right->branch_info);
1061
1012 return left->branch_info->flags.in_tx != 1062 return left->branch_info->flags.in_tx !=
1013 right->branch_info->flags.in_tx; 1063 right->branch_info->flags.in_tx;
1014} 1064}
@@ -1016,10 +1066,14 @@ sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
1016static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf, 1066static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
1017 size_t size, unsigned int width) 1067 size_t size, unsigned int width)
1018{ 1068{
1019 static const char *out = "."; 1069 static const char *out = "N/A";
1020 1070
1021 if (he->branch_info->flags.in_tx) 1071 if (he->branch_info) {
1022 out = "T"; 1072 if (he->branch_info->flags.in_tx)
1073 out = "T";
1074 else
1075 out = ".";
1076 }
1023 1077
1024 return repsep_snprintf(bf, size, "%-*s", width, out); 1078 return repsep_snprintf(bf, size, "%-*s", width, out);
1025} 1079}
@@ -1194,7 +1248,7 @@ bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1194 return hse_a->se == hse_b->se; 1248 return hse_a->se == hse_b->se;
1195} 1249}
1196 1250
1197void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) 1251void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1198{ 1252{
1199 struct hpp_sort_entry *hse; 1253 struct hpp_sort_entry *hse;
1200 1254
@@ -1202,20 +1256,21 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1202 return; 1256 return;
1203 1257
1204 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1258 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1205 hists__new_col_len(hists, hse->se->se_width_idx, 1259 hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
1206 strlen(hse->se->se_header));
1207} 1260}
1208 1261
1209static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1262static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1210 struct perf_evsel *evsel) 1263 struct perf_evsel *evsel)
1211{ 1264{
1212 struct hpp_sort_entry *hse; 1265 struct hpp_sort_entry *hse;
1213 size_t len; 1266 size_t len = fmt->user_len;
1214 1267
1215 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1268 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1216 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1217 1269
1218 return scnprintf(hpp->buf, hpp->size, "%-*s", len, hse->se->se_header); 1270 if (!len)
1271 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1272
1273 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1219} 1274}
1220 1275
1221static int __sort__hpp_width(struct perf_hpp_fmt *fmt, 1276static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
@@ -1223,20 +1278,26 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1223 struct perf_evsel *evsel) 1278 struct perf_evsel *evsel)
1224{ 1279{
1225 struct hpp_sort_entry *hse; 1280 struct hpp_sort_entry *hse;
1281 size_t len = fmt->user_len;
1226 1282
1227 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1283 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1228 1284
1229 return hists__col_len(&evsel->hists, hse->se->se_width_idx); 1285 if (!len)
1286 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1287
1288 return len;
1230} 1289}
1231 1290
1232static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1291static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1233 struct hist_entry *he) 1292 struct hist_entry *he)
1234{ 1293{
1235 struct hpp_sort_entry *hse; 1294 struct hpp_sort_entry *hse;
1236 size_t len; 1295 size_t len = fmt->user_len;
1237 1296
1238 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1297 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1239 len = hists__col_len(he->hists, hse->se->se_width_idx); 1298
1299 if (!len)
1300 len = hists__col_len(he->hists, hse->se->se_width_idx);
1240 1301
1241 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); 1302 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1242} 1303}
@@ -1253,6 +1314,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1253 } 1314 }
1254 1315
1255 hse->se = sd->entry; 1316 hse->se = sd->entry;
1317 hse->hpp.name = sd->entry->se_header;
1256 hse->hpp.header = __sort__hpp_header; 1318 hse->hpp.header = __sort__hpp_header;
1257 hse->hpp.width = __sort__hpp_width; 1319 hse->hpp.width = __sort__hpp_width;
1258 hse->hpp.entry = __sort__hpp_entry; 1320 hse->hpp.entry = __sort__hpp_entry;
@@ -1265,6 +1327,8 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1265 INIT_LIST_HEAD(&hse->hpp.list); 1327 INIT_LIST_HEAD(&hse->hpp.list);
1266 INIT_LIST_HEAD(&hse->hpp.sort_list); 1328 INIT_LIST_HEAD(&hse->hpp.sort_list);
1267 hse->hpp.elide = false; 1329 hse->hpp.elide = false;
1330 hse->hpp.len = 0;
1331 hse->hpp.user_len = 0;
1268 1332
1269 return hse; 1333 return hse;
1270} 1334}
@@ -1432,14 +1496,49 @@ static const char *get_default_sort_order(void)
1432 return default_sort_orders[sort__mode]; 1496 return default_sort_orders[sort__mode];
1433} 1497}
1434 1498
1499static int setup_sort_order(void)
1500{
1501 char *new_sort_order;
1502
1503 /*
1504 * Append '+'-prefixed sort order to the default sort
1505 * order string.
1506 */
1507 if (!sort_order || is_strict_order(sort_order))
1508 return 0;
1509
1510 if (sort_order[1] == '\0') {
1511 error("Invalid --sort key: `+'");
1512 return -EINVAL;
1513 }
1514
1515 /*
1516 * We allocate new sort_order string, but we never free it,
1517 * because it's checked over the rest of the code.
1518 */
1519 if (asprintf(&new_sort_order, "%s,%s",
1520 get_default_sort_order(), sort_order + 1) < 0) {
1521 error("Not enough memory to set up --sort");
1522 return -ENOMEM;
1523 }
1524
1525 sort_order = new_sort_order;
1526 return 0;
1527}
1528
1435static int __setup_sorting(void) 1529static int __setup_sorting(void)
1436{ 1530{
1437 char *tmp, *tok, *str; 1531 char *tmp, *tok, *str;
1438 const char *sort_keys = sort_order; 1532 const char *sort_keys;
1439 int ret = 0; 1533 int ret = 0;
1440 1534
1535 ret = setup_sort_order();
1536 if (ret)
1537 return ret;
1538
1539 sort_keys = sort_order;
1441 if (sort_keys == NULL) { 1540 if (sort_keys == NULL) {
1442 if (field_order) { 1541 if (is_strict_order(field_order)) {
1443 /* 1542 /*
1444 * If user specified field order but no sort order, 1543 * If user specified field order but no sort order,
1445 * we'll honor it and not add default sort orders. 1544 * we'll honor it and not add default sort orders.
@@ -1625,23 +1724,36 @@ static void reset_dimensions(void)
1625 memory_sort_dimensions[i].taken = 0; 1724 memory_sort_dimensions[i].taken = 0;
1626} 1725}
1627 1726
1727bool is_strict_order(const char *order)
1728{
1729 return order && (*order != '+');
1730}
1731
1628static int __setup_output_field(void) 1732static int __setup_output_field(void)
1629{ 1733{
1630 char *tmp, *tok, *str; 1734 char *tmp, *tok, *str, *strp;
1631 int ret = 0; 1735 int ret = -EINVAL;
1632 1736
1633 if (field_order == NULL) 1737 if (field_order == NULL)
1634 return 0; 1738 return 0;
1635 1739
1636 reset_dimensions(); 1740 reset_dimensions();
1637 1741
1638 str = strdup(field_order); 1742 strp = str = strdup(field_order);
1639 if (str == NULL) { 1743 if (str == NULL) {
1640 error("Not enough memory to setup output fields"); 1744 error("Not enough memory to setup output fields");
1641 return -ENOMEM; 1745 return -ENOMEM;
1642 } 1746 }
1643 1747
1644 for (tok = strtok_r(str, ", ", &tmp); 1748 if (!is_strict_order(field_order))
1749 strp++;
1750
1751 if (!strlen(strp)) {
1752 error("Invalid --fields key: `+'");
1753 goto out;
1754 }
1755
1756 for (tok = strtok_r(strp, ", ", &tmp);
1645 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1757 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1646 ret = output_field_add(tok); 1758 ret = output_field_add(tok);
1647 if (ret == -EINVAL) { 1759 if (ret == -EINVAL) {
@@ -1653,6 +1765,7 @@ static int __setup_output_field(void)
1653 } 1765 }
1654 } 1766 }
1655 1767
1768out:
1656 free(str); 1769 free(str);
1657 return ret; 1770 return ret;
1658} 1771}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 041f0c9cea2b..c03e4ff8beff 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -218,4 +218,5 @@ void perf_hpp__set_elide(int idx, bool elide);
218 218
219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
220 220
221bool is_strict_order(const char *order);
221#endif /* __PERF_SORT_H */ 222#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 2553e5b55b89..6afd6106ceb5 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -9,78 +9,48 @@
9 */ 9 */
10s64 perf_atoll(const char *str) 10s64 perf_atoll(const char *str)
11{ 11{
12 unsigned int i; 12 s64 length;
13 s64 length = -1, unit = 1; 13 char *p;
14 char c;
14 15
15 if (!isdigit(str[0])) 16 if (!isdigit(str[0]))
16 goto out_err; 17 goto out_err;
17 18
18 for (i = 1; i < strlen(str); i++) { 19 length = strtoll(str, &p, 10);
19 switch (str[i]) { 20 switch (c = *p++) {
20 case 'B': 21 case 'b': case 'B':
21 case 'b': 22 if (*p)
22 break;
23 case 'K':
24 if (str[i + 1] != 'B')
25 goto out_err;
26 else
27 goto kilo;
28 case 'k':
29 if (str[i + 1] != 'b')
30 goto out_err;
31kilo:
32 unit = K;
33 break;
34 case 'M':
35 if (str[i + 1] != 'B')
36 goto out_err;
37 else
38 goto mega;
39 case 'm':
40 if (str[i + 1] != 'b')
41 goto out_err;
42mega:
43 unit = K * K;
44 break;
45 case 'G':
46 if (str[i + 1] != 'B')
47 goto out_err; 23 goto out_err;
48 else 24 case '\0':
49 goto giga; 25 return length;
50 case 'g': 26 default:
51 if (str[i + 1] != 'b') 27 goto out_err;
52 goto out_err; 28 /* two-letter suffices */
53giga: 29 case 'k': case 'K':
54 unit = K * K * K; 30 length <<= 10;
55 break; 31 break;
56 case 'T': 32 case 'm': case 'M':
57 if (str[i + 1] != 'B') 33 length <<= 20;
58 goto out_err;
59 else
60 goto tera;
61 case 't':
62 if (str[i + 1] != 'b')
63 goto out_err;
64tera:
65 unit = K * K * K * K;
66 break; 34 break;
67 case '\0': /* only specified figures */ 35 case 'g': case 'G':
68 unit = 1; 36 length <<= 30;
69 break; 37 break;
70 default: 38 case 't': case 'T':
71 if (!isdigit(str[i])) 39 length <<= 40;
72 goto out_err;
73 break; 40 break;
74 }
75 } 41 }
76 42 /* we want the cases to match */
77 length = atoll(str) * unit; 43 if (islower(c)) {
78 goto out; 44 if (strcmp(p, "b") != 0)
45 goto out_err;
46 } else {
47 if (strcmp(p, "B") != 0)
48 goto out_err;
49 }
50 return length;
79 51
80out_err: 52out_err:
81 length = -1; 53 return -1;
82out:
83 return length;
84} 54}
85 55
86/* 56/*
@@ -387,27 +357,3 @@ void *memdup(const void *src, size_t len)
387 357
388 return p; 358 return p;
389} 359}
390
391/**
392 * str_append - reallocate string and append another
393 * @s: pointer to string pointer
394 * @len: pointer to len (initialized)
395 * @a: string to append.
396 */
397int str_append(char **s, int *len, const char *a)
398{
399 int olen = *s ? strlen(*s) : 0;
400 int nlen = olen + strlen(a) + 1;
401 if (*len < nlen) {
402 *len = *len * 2;
403 if (*len < nlen)
404 *len = nlen;
405 *s = realloc(*s, *len);
406 if (!*s)
407 return -ENOMEM;
408 if (olen == 0)
409 **s = 0;
410 }
411 strcat(*s, a);
412 return 0;
413}
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index d75349979e65..1e23a5bfb044 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,6 +6,7 @@
6#include <inttypes.h> 6#include <inttypes.h>
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include "machine.h"
9#include "vdso.h" 10#include "vdso.h"
10#include <symbol/kallsyms.h> 11#include <symbol/kallsyms.h>
11#include "debug.h" 12#include "debug.h"
@@ -680,6 +681,11 @@ static u64 ref_reloc(struct kmap *kmap)
680 return 0; 681 return 0;
681} 682}
682 683
684static bool want_demangle(bool is_kernel_sym)
685{
686 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
687}
688
683int dso__load_sym(struct dso *dso, struct map *map, 689int dso__load_sym(struct dso *dso, struct map *map,
684 struct symsrc *syms_ss, struct symsrc *runtime_ss, 690 struct symsrc *syms_ss, struct symsrc *runtime_ss,
685 symbol_filter_t filter, int kmodule) 691 symbol_filter_t filter, int kmodule)
@@ -712,6 +718,14 @@ int dso__load_sym(struct dso *dso, struct map *map,
712 symbols__delete(&dso->symbols[map->type]); 718 symbols__delete(&dso->symbols[map->type]);
713 719
714 if (!syms_ss->symtab) { 720 if (!syms_ss->symtab) {
721 /*
722 * If the vmlinux is stripped, fail so we will fall back
723 * to using kallsyms. The vmlinux runtime symbols aren't
724 * of much use.
725 */
726 if (dso->kernel)
727 goto out_elf_end;
728
715 syms_ss->symtab = syms_ss->dynsym; 729 syms_ss->symtab = syms_ss->dynsym;
716 syms_ss->symshdr = syms_ss->dynshdr; 730 syms_ss->symshdr = syms_ss->dynshdr;
717 } 731 }
@@ -736,7 +750,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
736 if (symstrs == NULL) 750 if (symstrs == NULL)
737 goto out_elf_end; 751 goto out_elf_end;
738 752
739 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 753 sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx);
740 if (sec_strndx == NULL) 754 if (sec_strndx == NULL)
741 goto out_elf_end; 755 goto out_elf_end;
742 756
@@ -916,7 +930,11 @@ int dso__load_sym(struct dso *dso, struct map *map,
916 } 930 }
917 curr_dso->symtab_type = dso->symtab_type; 931 curr_dso->symtab_type = dso->symtab_type;
918 map_groups__insert(kmap->kmaps, curr_map); 932 map_groups__insert(kmap->kmaps, curr_map);
919 dsos__add(&dso->node, curr_dso); 933 /*
934 * The new DSO should go to the kernel DSOS
935 */
936 dsos__add(&map->groups->machine->kernel_dsos,
937 curr_dso);
920 dso__set_loaded(curr_dso, map->type); 938 dso__set_loaded(curr_dso, map->type);
921 } else 939 } else
922 curr_dso = curr_map->dso; 940 curr_dso = curr_map->dso;
@@ -938,9 +956,12 @@ new_symbol:
938 * DWARF DW_compile_unit has this, but we don't always have access 956 * DWARF DW_compile_unit has this, but we don't always have access
939 * to it... 957 * to it...
940 */ 958 */
941 if (symbol_conf.demangle) { 959 if (want_demangle(dso->kernel || kmodule)) {
942 demangled = bfd_demangle(NULL, elf_name, 960 int demangle_flags = DMGL_NO_OPTS;
943 DMGL_PARAMS | DMGL_ANSI); 961 if (verbose)
962 demangle_flags = DMGL_PARAMS | DMGL_ANSI;
963
964 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
944 if (demangled != NULL) 965 if (demangled != NULL)
945 elf_name = demangled; 966 elf_name = demangled;
946 } 967 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index eb06746b06b2..078331140d8c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,6 +15,7 @@
15#include "machine.h" 15#include "machine.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
18#include "header.h"
18 19
19#include <elf.h> 20#include <elf.h>
20#include <limits.h> 21#include <limits.h>
@@ -33,6 +34,7 @@ struct symbol_conf symbol_conf = {
33 .try_vmlinux_path = true, 34 .try_vmlinux_path = true,
34 .annotate_src = true, 35 .annotate_src = true,
35 .demangle = true, 36 .demangle = true,
37 .demangle_kernel = false,
36 .cumulate_callchain = true, 38 .cumulate_callchain = true,
37 .show_hist_headers = true, 39 .show_hist_headers = true,
38 .symfs = "", 40 .symfs = "",
@@ -184,7 +186,7 @@ void symbols__fixup_end(struct rb_root *symbols)
184 curr = rb_entry(nd, struct symbol, rb_node); 186 curr = rb_entry(nd, struct symbol, rb_node);
185 187
186 if (prev->end == prev->start && prev->end != curr->start) 188 if (prev->end == prev->start && prev->end != curr->start)
187 prev->end = curr->start - 1; 189 prev->end = curr->start;
188 } 190 }
189 191
190 /* Last entry */ 192 /* Last entry */
@@ -205,7 +207,7 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
205 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 207 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
206 prev = curr; 208 prev = curr;
207 curr = rb_entry(nd, struct map, rb_node); 209 curr = rb_entry(nd, struct map, rb_node);
208 prev->end = curr->start - 1; 210 prev->end = curr->start;
209 } 211 }
210 212
211 /* 213 /*
@@ -227,7 +229,7 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
227 sym = ((void *)sym) + symbol_conf.priv_size; 229 sym = ((void *)sym) + symbol_conf.priv_size;
228 230
229 sym->start = start; 231 sym->start = start;
230 sym->end = len ? start + len - 1 : start; 232 sym->end = len ? start + len : start;
231 sym->binding = binding; 233 sym->binding = binding;
232 sym->namelen = namelen - 1; 234 sym->namelen = namelen - 1;
233 235
@@ -323,7 +325,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
323 325
324 if (ip < s->start) 326 if (ip < s->start)
325 n = n->rb_left; 327 n = n->rb_left;
326 else if (ip > s->end) 328 else if (ip >= s->end)
327 n = n->rb_right; 329 n = n->rb_right;
328 else 330 else
329 return s; 331 return s;
@@ -523,10 +525,15 @@ struct process_kallsyms_args {
523 struct dso *dso; 525 struct dso *dso;
524}; 526};
525 527
528/*
529 * These are symbols in the kernel image, so make sure that
530 * sym is from a kernel DSO.
531 */
526bool symbol__is_idle(struct symbol *sym) 532bool symbol__is_idle(struct symbol *sym)
527{ 533{
528 const char * const idle_symbols[] = { 534 const char * const idle_symbols[] = {
529 "cpu_idle", 535 "cpu_idle",
536 "cpu_startup_entry",
530 "intel_idle", 537 "intel_idle",
531 "default_idle", 538 "default_idle",
532 "native_safe_halt", 539 "native_safe_halt",
@@ -1468,8 +1475,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1468 if (vmlinux[0] == '/') 1475 if (vmlinux[0] == '/')
1469 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux); 1476 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux);
1470 else 1477 else
1471 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1478 symbol__join_symfs(symfs_vmlinux, vmlinux);
1472 symbol_conf.symfs, vmlinux);
1473 1479
1474 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1480 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1475 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1481 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
@@ -1745,12 +1751,13 @@ static void vmlinux_path__exit(void)
1745 zfree(&vmlinux_path); 1751 zfree(&vmlinux_path);
1746} 1752}
1747 1753
1748static int vmlinux_path__init(void) 1754static int vmlinux_path__init(struct perf_session_env *env)
1749{ 1755{
1750 struct utsname uts; 1756 struct utsname uts;
1751 char bf[PATH_MAX]; 1757 char bf[PATH_MAX];
1758 char *kernel_version;
1752 1759
1753 vmlinux_path = malloc(sizeof(char *) * 5); 1760 vmlinux_path = malloc(sizeof(char *) * 6);
1754 if (vmlinux_path == NULL) 1761 if (vmlinux_path == NULL)
1755 return -1; 1762 return -1;
1756 1763
@@ -1763,25 +1770,37 @@ static int vmlinux_path__init(void)
1763 goto out_fail; 1770 goto out_fail;
1764 ++vmlinux_path__nr_entries; 1771 ++vmlinux_path__nr_entries;
1765 1772
1766 /* only try running kernel version if no symfs was given */ 1773 /* only try kernel version if no symfs was given */
1767 if (symbol_conf.symfs[0] != 0) 1774 if (symbol_conf.symfs[0] != 0)
1768 return 0; 1775 return 0;
1769 1776
1770 if (uname(&uts) < 0) 1777 if (env) {
1771 return -1; 1778 kernel_version = env->os_release;
1779 } else {
1780 if (uname(&uts) < 0)
1781 goto out_fail;
1772 1782
1773 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 1783 kernel_version = uts.release;
1784 }
1785
1786 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", kernel_version);
1774 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1787 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1775 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1788 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1776 goto out_fail; 1789 goto out_fail;
1777 ++vmlinux_path__nr_entries; 1790 ++vmlinux_path__nr_entries;
1778 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); 1791 snprintf(bf, sizeof(bf), "/usr/lib/debug/boot/vmlinux-%s",
1792 kernel_version);
1793 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1794 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1795 goto out_fail;
1796 ++vmlinux_path__nr_entries;
1797 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version);
1779 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1798 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1780 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1799 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1781 goto out_fail; 1800 goto out_fail;
1782 ++vmlinux_path__nr_entries; 1801 ++vmlinux_path__nr_entries;
1783 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", 1802 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1784 uts.release); 1803 kernel_version);
1785 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1804 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1786 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1805 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1787 goto out_fail; 1806 goto out_fail;
@@ -1827,7 +1846,7 @@ static bool symbol__read_kptr_restrict(void)
1827 return value; 1846 return value;
1828} 1847}
1829 1848
1830int symbol__init(void) 1849int symbol__init(struct perf_session_env *env)
1831{ 1850{
1832 const char *symfs; 1851 const char *symfs;
1833 1852
@@ -1842,7 +1861,7 @@ int symbol__init(void)
1842 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 1861 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
1843 sizeof(struct symbol)); 1862 sizeof(struct symbol));
1844 1863
1845 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) 1864 if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0)
1846 return -1; 1865 return -1;
1847 1866
1848 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 1867 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index e7295e93cff9..eb2c19bf8d90 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,6 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15#include "event.h" 15#include "event.h"
16#include "util.h"
16 17
17#ifdef HAVE_LIBELF_SUPPORT 18#ifdef HAVE_LIBELF_SUPPORT
18#include <libelf.h> 19#include <libelf.h>
@@ -59,6 +60,7 @@ extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
59#endif 60#endif
60 61
61#ifndef DMGL_PARAMS 62#ifndef DMGL_PARAMS
63#define DMGL_NO_OPTS 0 /* For readability... */
62#define DMGL_PARAMS (1 << 0) /* Include function args */ 64#define DMGL_PARAMS (1 << 0) /* Include function args */
63#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 65#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
64#endif 66#endif
@@ -93,7 +95,7 @@ void symbols__delete(struct rb_root *symbols);
93 95
94static inline size_t symbol__size(const struct symbol *sym) 96static inline size_t symbol__size(const struct symbol *sym)
95{ 97{
96 return sym->end - sym->start + 1; 98 return sym->end - sym->start;
97} 99}
98 100
99struct strlist; 101struct strlist;
@@ -118,6 +120,7 @@ struct symbol_conf {
118 annotate_src, 120 annotate_src,
119 event_group, 121 event_group,
120 demangle, 122 demangle,
123 demangle_kernel,
121 filter_relative, 124 filter_relative,
122 show_hist_headers; 125 show_hist_headers;
123 const char *vmlinux_name, 126 const char *vmlinux_name,
@@ -143,6 +146,14 @@ struct symbol_conf {
143}; 146};
144 147
145extern struct symbol_conf symbol_conf; 148extern struct symbol_conf symbol_conf;
149
150static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
151{
152 return path__join(bf, size, symbol_conf.symfs, path);
153}
154
155#define symbol__join_symfs(bf, path) __symbol__join_symfs(bf, sizeof(bf), path)
156
146extern int vmlinux_path__nr_entries; 157extern int vmlinux_path__nr_entries;
147extern char **vmlinux_path; 158extern char **vmlinux_path;
148 159
@@ -253,7 +264,8 @@ int modules__parse(const char *filename, void *arg,
253int filename__read_debuglink(const char *filename, char *debuglink, 264int filename__read_debuglink(const char *filename, char *debuglink,
254 size_t size); 265 size_t size);
255 266
256int symbol__init(void); 267struct perf_session_env;
268int symbol__init(struct perf_session_env *env);
257void symbol__exit(void); 269void symbol__exit(void);
258void symbol__elf_init(void); 270void symbol__elf_init(void);
259struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 271struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 12c7a253a63c..c41411726c7a 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,6 +7,7 @@
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9#include "comm.h" 9#include "comm.h"
10#include "unwind.h"
10 11
11int thread__init_map_groups(struct thread *thread, struct machine *machine) 12int thread__init_map_groups(struct thread *thread, struct machine *machine)
12{ 13{
@@ -37,17 +38,21 @@ struct thread *thread__new(pid_t pid, pid_t tid)
37 thread->cpu = -1; 38 thread->cpu = -1;
38 INIT_LIST_HEAD(&thread->comm_list); 39 INIT_LIST_HEAD(&thread->comm_list);
39 40
41 if (unwind__prepare_access(thread) < 0)
42 goto err_thread;
43
40 comm_str = malloc(32); 44 comm_str = malloc(32);
41 if (!comm_str) 45 if (!comm_str)
42 goto err_thread; 46 goto err_thread;
43 47
44 snprintf(comm_str, 32, ":%d", tid); 48 snprintf(comm_str, 32, ":%d", tid);
45 comm = comm__new(comm_str, 0); 49 comm = comm__new(comm_str, 0, false);
46 free(comm_str); 50 free(comm_str);
47 if (!comm) 51 if (!comm)
48 goto err_thread; 52 goto err_thread;
49 53
50 list_add(&comm->list, &thread->comm_list); 54 list_add(&comm->list, &thread->comm_list);
55
51 } 56 }
52 57
53 return thread; 58 return thread;
@@ -69,6 +74,7 @@ void thread__delete(struct thread *thread)
69 list_del(&comm->list); 74 list_del(&comm->list);
70 comm__free(comm); 75 comm__free(comm);
71 } 76 }
77 unwind__finish_access(thread);
72 78
73 free(thread); 79 free(thread);
74} 80}
@@ -81,22 +87,39 @@ struct comm *thread__comm(const struct thread *thread)
81 return list_first_entry(&thread->comm_list, struct comm, list); 87 return list_first_entry(&thread->comm_list, struct comm, list);
82} 88}
83 89
90struct comm *thread__exec_comm(const struct thread *thread)
91{
92 struct comm *comm, *last = NULL;
93
94 list_for_each_entry(comm, &thread->comm_list, list) {
95 if (comm->exec)
96 return comm;
97 last = comm;
98 }
99
100 return last;
101}
102
84/* CHECKME: time should always be 0 if event aren't ordered */ 103/* CHECKME: time should always be 0 if event aren't ordered */
85int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) 104int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
105 bool exec)
86{ 106{
87 struct comm *new, *curr = thread__comm(thread); 107 struct comm *new, *curr = thread__comm(thread);
88 int err; 108 int err;
89 109
90 /* Override latest entry if it had no specific time coverage */ 110 /* Override latest entry if it had no specific time coverage */
91 if (!curr->start) { 111 if (!curr->start && !curr->exec) {
92 err = comm__override(curr, str, timestamp); 112 err = comm__override(curr, str, timestamp, exec);
93 if (err) 113 if (err)
94 return err; 114 return err;
95 } else { 115 } else {
96 new = comm__new(str, timestamp); 116 new = comm__new(str, timestamp, exec);
97 if (!new) 117 if (!new)
98 return -ENOMEM; 118 return -ENOMEM;
99 list_add(&new->list, &thread->comm_list); 119 list_add(&new->list, &thread->comm_list);
120
121 if (exec)
122 unwind__flush_access(thread);
100 } 123 }
101 124
102 thread->comm_set = true; 125 thread->comm_set = true;
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 716b7723cce2..8c75fa774706 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -38,9 +38,17 @@ static inline void thread__exited(struct thread *thread)
38 thread->dead = true; 38 thread->dead = true;
39} 39}
40 40
41int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp); 41int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
42 bool exec);
43static inline int thread__set_comm(struct thread *thread, const char *comm,
44 u64 timestamp)
45{
46 return __thread__set_comm(thread, comm, timestamp, false);
47}
48
42int thread__comm_len(struct thread *thread); 49int thread__comm_len(struct thread *thread);
43struct comm *thread__comm(const struct thread *thread); 50struct comm *thread__comm(const struct thread *thread);
51struct comm *thread__exec_comm(const struct thread *thread);
44const char *thread__comm_str(const struct thread *thread); 52const char *thread__comm_str(const struct thread *thread);
45void thread__insert_map(struct thread *thread, struct map *map); 53void thread__insert_map(struct thread *thread, struct map *map);
46int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 54int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 5d3215912105..f93b9734735b 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -214,6 +214,17 @@ out_free_threads:
214 goto out; 214 goto out;
215} 215}
216 216
217struct thread_map *thread_map__new_dummy(void)
218{
219 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
220
221 if (threads != NULL) {
222 threads->map[0] = -1;
223 threads->nr = 1;
224 }
225 return threads;
226}
227
217static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) 228static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
218{ 229{
219 struct thread_map *threads = NULL, *nt; 230 struct thread_map *threads = NULL, *nt;
@@ -224,14 +235,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
224 struct strlist *slist; 235 struct strlist *slist;
225 236
226 /* perf-stat expects threads to be generated even if tid not given */ 237 /* perf-stat expects threads to be generated even if tid not given */
227 if (!tid_str) { 238 if (!tid_str)
228 threads = malloc(sizeof(*threads) + sizeof(pid_t)); 239 return thread_map__new_dummy();
229 if (threads != NULL) {
230 threads->map[0] = -1;
231 threads->nr = 1;
232 }
233 return threads;
234 }
235 240
236 slist = strlist__new(false, tid_str); 241 slist = strlist__new(false, tid_str);
237 if (!slist) 242 if (!slist)
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 0cd8b3108084..95313f43cc0f 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -9,6 +9,7 @@ struct thread_map {
9 pid_t map[]; 9 pid_t map[];
10}; 10};
11 11
12struct thread_map *thread_map__new_dummy(void);
12struct thread_map *thread_map__new_by_pid(pid_t pid); 13struct thread_map *thread_map__new_by_pid(pid_t pid);
13struct thread_map *thread_map__new_by_tid(pid_t tid); 14struct thread_map *thread_map__new_by_tid(pid_t tid);
14struct thread_map *thread_map__new_by_uid(uid_t uid); 15struct thread_map *thread_map__new_by_uid(uid_t uid);
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 4385816d3d49..f11636966a0f 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -40,7 +40,7 @@ struct perf_tool {
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 bool ordered_samples; 43 bool ordered_events;
44 bool ordering_requires_timestamps; 44 bool ordering_requires_timestamps;
45}; 45};
46 46
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 57aaccc1692e..5c9bdd1591a9 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -30,6 +30,11 @@
30 30
31struct scripting_context *scripting_context; 31struct scripting_context *scripting_context;
32 32
33static int flush_script_unsupported(void)
34{
35 return 0;
36}
37
33static int stop_script_unsupported(void) 38static int stop_script_unsupported(void)
34{ 39{
35 return 0; 40 return 0;
@@ -74,6 +79,7 @@ static int python_generate_script_unsupported(struct pevent *pevent
74struct scripting_ops python_scripting_unsupported_ops = { 79struct scripting_ops python_scripting_unsupported_ops = {
75 .name = "Python", 80 .name = "Python",
76 .start_script = python_start_script_unsupported, 81 .start_script = python_start_script_unsupported,
82 .flush_script = flush_script_unsupported,
77 .stop_script = stop_script_unsupported, 83 .stop_script = stop_script_unsupported,
78 .process_event = process_event_unsupported, 84 .process_event = process_event_unsupported,
79 .generate_script = python_generate_script_unsupported, 85 .generate_script = python_generate_script_unsupported,
@@ -137,6 +143,7 @@ static int perl_generate_script_unsupported(struct pevent *pevent
137struct scripting_ops perl_scripting_unsupported_ops = { 143struct scripting_ops perl_scripting_unsupported_ops = {
138 .name = "Perl", 144 .name = "Perl",
139 .start_script = perl_start_script_unsupported, 145 .start_script = perl_start_script_unsupported,
146 .flush_script = flush_script_unsupported,
140 .stop_script = stop_script_unsupported, 147 .stop_script = stop_script_unsupported,
141 .process_event = process_event_unsupported, 148 .process_event = process_event_unsupported,
142 .generate_script = perl_generate_script_unsupported, 149 .generate_script = perl_generate_script_unsupported,
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 7b6d68688327..52aaa19e1eb1 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -64,6 +64,7 @@ struct perf_session;
64struct scripting_ops { 64struct scripting_ops {
65 const char *name; 65 const char *name;
66 int (*start_script) (const char *script, int argc, const char **argv); 66 int (*start_script) (const char *script, int argc, const char **argv);
67 int (*flush_script) (void);
67 int (*stop_script) (void); 68 int (*stop_script) (void);
68 void (*process_event) (union perf_event *event, 69 void (*process_event) (union perf_event *event,
69 struct perf_sample *sample, 70 struct perf_sample *sample,
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 92b56db52471..4d45c0dfe343 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -24,6 +24,7 @@
24#include <linux/list.h> 24#include <linux/list.h>
25#include <libunwind.h> 25#include <libunwind.h>
26#include <libunwind-ptrace.h> 26#include <libunwind-ptrace.h>
27#include "callchain.h"
27#include "thread.h" 28#include "thread.h"
28#include "session.h" 29#include "session.h"
29#include "perf_regs.h" 30#include "perf_regs.h"
@@ -525,12 +526,12 @@ static unw_accessors_t accessors = {
525 .get_proc_name = get_proc_name, 526 .get_proc_name = get_proc_name,
526}; 527};
527 528
528static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, 529int unwind__prepare_access(struct thread *thread)
529 void *arg, int max_stack)
530{ 530{
531 unw_addr_space_t addr_space; 531 unw_addr_space_t addr_space;
532 unw_cursor_t c; 532
533 int ret; 533 if (callchain_param.record_mode != CALLCHAIN_DWARF)
534 return 0;
534 535
535 addr_space = unw_create_addr_space(&accessors, 0); 536 addr_space = unw_create_addr_space(&accessors, 0);
536 if (!addr_space) { 537 if (!addr_space) {
@@ -538,6 +539,45 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
538 return -ENOMEM; 539 return -ENOMEM;
539 } 540 }
540 541
542 unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);
543 thread__set_priv(thread, addr_space);
544
545 return 0;
546}
547
548void unwind__flush_access(struct thread *thread)
549{
550 unw_addr_space_t addr_space;
551
552 if (callchain_param.record_mode != CALLCHAIN_DWARF)
553 return;
554
555 addr_space = thread__priv(thread);
556 unw_flush_cache(addr_space, 0, 0);
557}
558
559void unwind__finish_access(struct thread *thread)
560{
561 unw_addr_space_t addr_space;
562
563 if (callchain_param.record_mode != CALLCHAIN_DWARF)
564 return;
565
566 addr_space = thread__priv(thread);
567 unw_destroy_addr_space(addr_space);
568}
569
570static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
571 void *arg, int max_stack)
572{
573 unw_addr_space_t addr_space;
574 unw_cursor_t c;
575 int ret;
576
577 addr_space = thread__priv(ui->thread);
578 if (addr_space == NULL)
579 return -1;
580
541 ret = unw_init_remote(&c, addr_space, ui); 581 ret = unw_init_remote(&c, addr_space, ui);
542 if (ret) 582 if (ret)
543 display_error(ret); 583 display_error(ret);
@@ -549,7 +589,6 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
549 ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; 589 ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0;
550 } 590 }
551 591
552 unw_destroy_addr_space(addr_space);
553 return ret; 592 return ret;
554} 593}
555 594
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index f03061260b4e..f50b737235eb 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -4,6 +4,7 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include "event.h" 5#include "event.h"
6#include "symbol.h" 6#include "symbol.h"
7#include "thread.h"
7 8
8struct unwind_entry { 9struct unwind_entry {
9 struct map *map; 10 struct map *map;
@@ -21,6 +22,17 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
21/* libunwind specific */ 22/* libunwind specific */
22#ifdef HAVE_LIBUNWIND_SUPPORT 23#ifdef HAVE_LIBUNWIND_SUPPORT
23int libunwind__arch_reg_id(int regnum); 24int libunwind__arch_reg_id(int regnum);
25int unwind__prepare_access(struct thread *thread);
26void unwind__flush_access(struct thread *thread);
27void unwind__finish_access(struct thread *thread);
28#else
29static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
30{
31 return 0;
32}
33
34static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
35static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
24#endif 36#endif
25#else 37#else
26static inline int 38static inline int
@@ -33,5 +45,13 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
33{ 45{
34 return 0; 46 return 0;
35} 47}
48
49static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
50{
51 return 0;
52}
53
54static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
55static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
36#endif /* HAVE_DWARF_UNWIND_SUPPORT */ 56#endif /* HAVE_DWARF_UNWIND_SUPPORT */
37#endif /* __UNWIND_H */ 57#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index e52e7461911b..d5eab3f3323f 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -13,6 +13,15 @@
13#include <limits.h> 13#include <limits.h>
14#include <byteswap.h> 14#include <byteswap.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <unistd.h>
17#include "callchain.h"
18
19struct callchain_param callchain_param = {
20 .mode = CHAIN_GRAPH_REL,
21 .min_percent = 0.5,
22 .order = ORDER_CALLEE,
23 .key = CCKEY_FUNCTION
24};
16 25
17/* 26/*
18 * XXX We need to find a better place for these things... 27 * XXX We need to find a better place for these things...
@@ -282,6 +291,18 @@ void get_term_dimensions(struct winsize *ws)
282 ws->ws_col = 80; 291 ws->ws_col = 80;
283} 292}
284 293
294void set_term_quiet_input(struct termios *old)
295{
296 struct termios tc;
297
298 tcgetattr(0, old);
299 tc = *old;
300 tc.c_lflag &= ~(ICANON | ECHO);
301 tc.c_cc[VMIN] = 0;
302 tc.c_cc[VTIME] = 0;
303 tcsetattr(0, TCSANOW, &tc);
304}
305
285static void set_tracing_events_path(const char *mountpoint) 306static void set_tracing_events_path(const char *mountpoint)
286{ 307{
287 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 308 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
@@ -443,6 +464,7 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
443 size_t size = 0, alloc_size = 0; 464 size_t size = 0, alloc_size = 0;
444 void *bf = NULL, *nbf; 465 void *bf = NULL, *nbf;
445 int fd, n, err = 0; 466 int fd, n, err = 0;
467 char sbuf[STRERR_BUFSIZE];
446 468
447 fd = open(filename, O_RDONLY); 469 fd = open(filename, O_RDONLY);
448 if (fd < 0) 470 if (fd < 0)
@@ -463,8 +485,8 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
463 n = read(fd, bf + size, alloc_size - size); 485 n = read(fd, bf + size, alloc_size - size);
464 if (n < 0) { 486 if (n < 0) {
465 if (size) { 487 if (size) {
466 pr_warning("read failed %d: %s\n", 488 pr_warning("read failed %d: %s\n", errno,
467 errno, strerror(errno)); 489 strerror_r(errno, sbuf, sizeof(sbuf)));
468 err = 0; 490 err = 0;
469 } else 491 } else
470 err = -errno; 492 err = -errno;
@@ -536,3 +558,39 @@ void mem_bswap_64(void *src, int byte_size)
536 ++m; 558 ++m;
537 } 559 }
538} 560}
561
562bool find_process(const char *name)
563{
564 size_t len = strlen(name);
565 DIR *dir;
566 struct dirent *d;
567 int ret = -1;
568
569 dir = opendir(procfs__mountpoint());
570 if (!dir)
571 return -1;
572
573 /* Walk through the directory. */
574 while (ret && (d = readdir(dir)) != NULL) {
575 char path[PATH_MAX];
576 char *data;
577 size_t size;
578
579 if ((d->d_type != DT_DIR) ||
580 !strcmp(".", d->d_name) ||
581 !strcmp("..", d->d_name))
582 continue;
583
584 scnprintf(path, sizeof(path), "%s/%s/comm",
585 procfs__mountpoint(), d->d_name);
586
587 if (filename__read_str(path, &data, &size))
588 continue;
589
590 ret = strncmp(name, data, len);
591 free(data);
592 }
593
594 closedir(dir);
595 return ret ? false : true;
596}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 66864364ccb4..80bfdaa0e2a4 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -39,6 +39,8 @@
39 39
40#define _ALL_SOURCE 1 40#define _ALL_SOURCE 1
41#define _BSD_SOURCE 1 41#define _BSD_SOURCE 1
42/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
43#define _DEFAULT_SOURCE 1
42#define HAS_BOOL 44#define HAS_BOOL
43 45
44#include <unistd.h> 46#include <unistd.h>
@@ -64,16 +66,18 @@
64#include <regex.h> 66#include <regex.h>
65#include <utime.h> 67#include <utime.h>
66#include <sys/wait.h> 68#include <sys/wait.h>
67#include <sys/poll.h> 69#include <poll.h>
68#include <sys/socket.h> 70#include <sys/socket.h>
69#include <sys/ioctl.h> 71#include <sys/ioctl.h>
70#include <inttypes.h> 72#include <inttypes.h>
73#include <linux/kernel.h>
71#include <linux/magic.h> 74#include <linux/magic.h>
72#include <linux/types.h> 75#include <linux/types.h>
73#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
74#include <api/fs/debugfs.h> 77#include <api/fs/debugfs.h>
75#include <termios.h> 78#include <termios.h>
76#include <linux/bitops.h> 79#include <linux/bitops.h>
80#include <termios.h>
77 81
78extern const char *graph_line; 82extern const char *graph_line;
79extern const char *graph_dotted_line; 83extern const char *graph_dotted_line;
@@ -307,6 +311,7 @@ extern unsigned int page_size;
307extern int cacheline_size; 311extern int cacheline_size;
308 312
309void get_term_dimensions(struct winsize *ws); 313void get_term_dimensions(struct winsize *ws);
314void set_term_quiet_input(struct termios *old);
310 315
311struct parse_tag { 316struct parse_tag {
312 char tag; 317 char tag;
@@ -317,6 +322,21 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
317 322
318#define SRCLINE_UNKNOWN ((char *) "??:0") 323#define SRCLINE_UNKNOWN ((char *) "??:0")
319 324
325static inline int path__join(char *bf, size_t size,
326 const char *path1, const char *path2)
327{
328 return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
329}
330
331static inline int path__join3(char *bf, size_t size,
332 const char *path1, const char *path2,
333 const char *path3)
334{
335 return scnprintf(bf, size, "%s%s%s%s%s",
336 path1, path1[0] ? "/" : "",
337 path2, path2[0] ? "/" : "", path3);
338}
339
320struct dso; 340struct dso;
321 341
322char *get_srcline(struct dso *dso, unsigned long addr); 342char *get_srcline(struct dso *dso, unsigned long addr);
@@ -330,4 +350,5 @@ void mem_bswap_64(void *src, int byte_size);
330void mem_bswap_32(void *src, int byte_size); 350void mem_bswap_32(void *src, int byte_size);
331 351
332const char *get_filename_for_perf_kvm(void); 352const char *get_filename_for_perf_kvm(void);
353bool find_process(const char *name);
333#endif /* GIT_COMPAT_UTIL_H */ 354#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 60b58cd18410..7ccb073f8316 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -122,6 +122,14 @@ static void os_enter_line_edit_mode(void)
122{ 122{
123 struct termios local_term_attributes; 123 struct termios local_term_attributes;
124 124
125 term_attributes_were_set = 0;
126
127 /* STDIN must be a terminal */
128
129 if (!isatty(STDIN_FILENO)) {
130 return;
131 }
132
125 /* Get and keep the original attributes */ 133 /* Get and keep the original attributes */
126 134
127 if (tcgetattr(STDIN_FILENO, &original_term_attributes)) { 135 if (tcgetattr(STDIN_FILENO, &original_term_attributes)) {
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index 53cee781e24e..24d32968802d 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -146,7 +146,7 @@ u32 ap_get_table_length(struct acpi_table_header *table)
146 146
147 if (ACPI_VALIDATE_RSDP_SIG(table->signature)) { 147 if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
148 rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table); 148 rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
149 return (rsdp->length); 149 return (acpi_tb_get_rsdp_length(rsdp));
150 } 150 }
151 151
152 /* Normal ACPI table */ 152 /* Normal ACPI table */
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index d0396af99fa0..5b1b807265a1 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -267,90 +267,90 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
267/* 267/*
268 * Example Format w/ field column widths: 268 * Example Format w/ field column widths:
269 * 269 *
270 * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt 270 * Package Core CPU Avg_MHz Bzy_MHz TSC_MHz SMI %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
271 * 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567 271 * 123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678
272 */ 272 */
273 273
274void print_header(void) 274void print_header(void)
275{ 275{
276 if (show_pkg) 276 if (show_pkg)
277 outp += sprintf(outp, "Package "); 277 outp += sprintf(outp, " Package");
278 if (show_core) 278 if (show_core)
279 outp += sprintf(outp, " Core "); 279 outp += sprintf(outp, " Core");
280 if (show_cpu) 280 if (show_cpu)
281 outp += sprintf(outp, " CPU "); 281 outp += sprintf(outp, " CPU");
282 if (has_aperf) 282 if (has_aperf)
283 outp += sprintf(outp, "Avg_MHz "); 283 outp += sprintf(outp, " Avg_MHz");
284 if (do_nhm_cstates) 284 if (do_nhm_cstates)
285 outp += sprintf(outp, " %%Busy "); 285 outp += sprintf(outp, " %%Busy");
286 if (has_aperf) 286 if (has_aperf)
287 outp += sprintf(outp, "Bzy_MHz "); 287 outp += sprintf(outp, " Bzy_MHz");
288 outp += sprintf(outp, "TSC_MHz "); 288 outp += sprintf(outp, " TSC_MHz");
289 if (do_smi) 289 if (do_smi)
290 outp += sprintf(outp, " SMI "); 290 outp += sprintf(outp, " SMI");
291 if (extra_delta_offset32) 291 if (extra_delta_offset32)
292 outp += sprintf(outp, " count 0x%03X ", extra_delta_offset32); 292 outp += sprintf(outp, " count 0x%03X", extra_delta_offset32);
293 if (extra_delta_offset64) 293 if (extra_delta_offset64)
294 outp += sprintf(outp, " COUNT 0x%03X ", extra_delta_offset64); 294 outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64);
295 if (extra_msr_offset32) 295 if (extra_msr_offset32)
296 outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset32); 296 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32);
297 if (extra_msr_offset64) 297 if (extra_msr_offset64)
298 outp += sprintf(outp, " MSR 0x%03X ", extra_msr_offset64); 298 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
299 if (do_nhm_cstates) 299 if (do_nhm_cstates)
300 outp += sprintf(outp, " CPU%%c1 "); 300 outp += sprintf(outp, " CPU%%c1");
301 if (do_nhm_cstates && !do_slm_cstates) 301 if (do_nhm_cstates && !do_slm_cstates)
302 outp += sprintf(outp, " CPU%%c3 "); 302 outp += sprintf(outp, " CPU%%c3");
303 if (do_nhm_cstates) 303 if (do_nhm_cstates)
304 outp += sprintf(outp, " CPU%%c6 "); 304 outp += sprintf(outp, " CPU%%c6");
305 if (do_snb_cstates) 305 if (do_snb_cstates)
306 outp += sprintf(outp, " CPU%%c7 "); 306 outp += sprintf(outp, " CPU%%c7");
307 307
308 if (do_dts) 308 if (do_dts)
309 outp += sprintf(outp, "CoreTmp "); 309 outp += sprintf(outp, " CoreTmp");
310 if (do_ptm) 310 if (do_ptm)
311 outp += sprintf(outp, " PkgTmp "); 311 outp += sprintf(outp, " PkgTmp");
312 312
313 if (do_snb_cstates) 313 if (do_snb_cstates)
314 outp += sprintf(outp, "Pkg%%pc2 "); 314 outp += sprintf(outp, " Pkg%%pc2");
315 if (do_nhm_cstates && !do_slm_cstates) 315 if (do_nhm_cstates && !do_slm_cstates)
316 outp += sprintf(outp, "Pkg%%pc3 "); 316 outp += sprintf(outp, " Pkg%%pc3");
317 if (do_nhm_cstates && !do_slm_cstates) 317 if (do_nhm_cstates && !do_slm_cstates)
318 outp += sprintf(outp, "Pkg%%pc6 "); 318 outp += sprintf(outp, " Pkg%%pc6");
319 if (do_snb_cstates) 319 if (do_snb_cstates)
320 outp += sprintf(outp, "Pkg%%pc7 "); 320 outp += sprintf(outp, " Pkg%%pc7");
321 if (do_c8_c9_c10) { 321 if (do_c8_c9_c10) {
322 outp += sprintf(outp, "Pkg%%pc8 "); 322 outp += sprintf(outp, " Pkg%%pc8");
323 outp += sprintf(outp, "Pkg%%pc9 "); 323 outp += sprintf(outp, " Pkg%%pc9");
324 outp += sprintf(outp, "Pk%%pc10 "); 324 outp += sprintf(outp, " Pk%%pc10");
325 } 325 }
326 326
327 if (do_rapl && !rapl_joules) { 327 if (do_rapl && !rapl_joules) {
328 if (do_rapl & RAPL_PKG) 328 if (do_rapl & RAPL_PKG)
329 outp += sprintf(outp, "PkgWatt "); 329 outp += sprintf(outp, " PkgWatt");
330 if (do_rapl & RAPL_CORES) 330 if (do_rapl & RAPL_CORES)
331 outp += sprintf(outp, "CorWatt "); 331 outp += sprintf(outp, " CorWatt");
332 if (do_rapl & RAPL_GFX) 332 if (do_rapl & RAPL_GFX)
333 outp += sprintf(outp, "GFXWatt "); 333 outp += sprintf(outp, " GFXWatt");
334 if (do_rapl & RAPL_DRAM) 334 if (do_rapl & RAPL_DRAM)
335 outp += sprintf(outp, "RAMWatt "); 335 outp += sprintf(outp, " RAMWatt");
336 if (do_rapl & RAPL_PKG_PERF_STATUS) 336 if (do_rapl & RAPL_PKG_PERF_STATUS)
337 outp += sprintf(outp, " PKG_%% "); 337 outp += sprintf(outp, " PKG_%%");
338 if (do_rapl & RAPL_DRAM_PERF_STATUS) 338 if (do_rapl & RAPL_DRAM_PERF_STATUS)
339 outp += sprintf(outp, " RAM_%% "); 339 outp += sprintf(outp, " RAM_%%");
340 } else { 340 } else {
341 if (do_rapl & RAPL_PKG) 341 if (do_rapl & RAPL_PKG)
342 outp += sprintf(outp, " Pkg_J "); 342 outp += sprintf(outp, " Pkg_J");
343 if (do_rapl & RAPL_CORES) 343 if (do_rapl & RAPL_CORES)
344 outp += sprintf(outp, " Cor_J "); 344 outp += sprintf(outp, " Cor_J");
345 if (do_rapl & RAPL_GFX) 345 if (do_rapl & RAPL_GFX)
346 outp += sprintf(outp, " GFX_J "); 346 outp += sprintf(outp, " GFX_J");
347 if (do_rapl & RAPL_DRAM) 347 if (do_rapl & RAPL_DRAM)
348 outp += sprintf(outp, " RAM_W "); 348 outp += sprintf(outp, " RAM_W");
349 if (do_rapl & RAPL_PKG_PERF_STATUS) 349 if (do_rapl & RAPL_PKG_PERF_STATUS)
350 outp += sprintf(outp, " PKG_%% "); 350 outp += sprintf(outp, " PKG_%%");
351 if (do_rapl & RAPL_DRAM_PERF_STATUS) 351 if (do_rapl & RAPL_DRAM_PERF_STATUS)
352 outp += sprintf(outp, " RAM_%% "); 352 outp += sprintf(outp, " RAM_%%");
353 outp += sprintf(outp, " time "); 353 outp += sprintf(outp, " time");
354 354
355 } 355 }
356 outp += sprintf(outp, "\n"); 356 outp += sprintf(outp, "\n");
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index 55ab700f6ba5..bf1398180785 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -194,6 +194,7 @@ my $config_bisect_check;
194 194
195my $patchcheck_type; 195my $patchcheck_type;
196my $patchcheck_start; 196my $patchcheck_start;
197my $patchcheck_cherry;
197my $patchcheck_end; 198my $patchcheck_end;
198 199
199# set when a test is something other that just building or install 200# set when a test is something other that just building or install
@@ -320,6 +321,7 @@ my %option_map = (
320 321
321 "PATCHCHECK_TYPE" => \$patchcheck_type, 322 "PATCHCHECK_TYPE" => \$patchcheck_type,
322 "PATCHCHECK_START" => \$patchcheck_start, 323 "PATCHCHECK_START" => \$patchcheck_start,
324 "PATCHCHECK_CHERRY" => \$patchcheck_cherry,
323 "PATCHCHECK_END" => \$patchcheck_end, 325 "PATCHCHECK_END" => \$patchcheck_end,
324); 326);
325 327
@@ -1448,6 +1450,12 @@ sub wait_for_monitor {
1448 } 1450 }
1449 } 1451 }
1450 print "** Monitor flushed **\n"; 1452 print "** Monitor flushed **\n";
1453
1454 # if stop is defined but wasn't hit, return error
1455 # used by reboot (which wants to see a reboot)
1456 if (defined($stop) && !$booted) {
1457 $bug = 1;
1458 }
1451 return $bug; 1459 return $bug;
1452} 1460}
1453 1461
@@ -2336,15 +2344,17 @@ sub success {
2336 2344
2337sub answer_bisect { 2345sub answer_bisect {
2338 for (;;) { 2346 for (;;) {
2339 doprint "Pass or fail? [p/f]"; 2347 doprint "Pass, fail, or skip? [p/f/s]";
2340 my $ans = <STDIN>; 2348 my $ans = <STDIN>;
2341 chomp $ans; 2349 chomp $ans;
2342 if ($ans eq "p" || $ans eq "P") { 2350 if ($ans eq "p" || $ans eq "P") {
2343 return 1; 2351 return 1;
2344 } elsif ($ans eq "f" || $ans eq "F") { 2352 } elsif ($ans eq "f" || $ans eq "F") {
2345 return 0; 2353 return 0;
2354 } elsif ($ans eq "s" || $ans eq "S") {
2355 return -1;
2346 } else { 2356 } else {
2347 print "Please answer 'P' or 'F'\n"; 2357 print "Please answer 'p', 'f', or 's'\n";
2348 } 2358 }
2349 } 2359 }
2350} 2360}
@@ -2726,15 +2736,17 @@ sub bisect {
2726 run_command "git bisect start$start_files" or 2736 run_command "git bisect start$start_files" or
2727 dodie "could not start bisect"; 2737 dodie "could not start bisect";
2728 2738
2729 run_command "git bisect good $good" or
2730 dodie "could not set bisect good to $good";
2731
2732 run_git_bisect "git bisect bad $bad" or
2733 dodie "could not set bisect bad to $bad";
2734
2735 if (defined($replay)) { 2739 if (defined($replay)) {
2736 run_command "git bisect replay $replay" or 2740 run_command "git bisect replay $replay" or
2737 dodie "failed to run replay"; 2741 dodie "failed to run replay";
2742 } else {
2743
2744 run_command "git bisect good $good" or
2745 dodie "could not set bisect good to $good";
2746
2747 run_git_bisect "git bisect bad $bad" or
2748 dodie "could not set bisect bad to $bad";
2749
2738 } 2750 }
2739 2751
2740 if (defined($start)) { 2752 if (defined($start)) {
@@ -3181,9 +3193,16 @@ sub patchcheck {
3181 3193
3182 my $start = $patchcheck_start; 3194 my $start = $patchcheck_start;
3183 3195
3196 my $cherry = $patchcheck_cherry;
3197 if (!defined($cherry)) {
3198 $cherry = 0;
3199 }
3200
3184 my $end = "HEAD"; 3201 my $end = "HEAD";
3185 if (defined($patchcheck_end)) { 3202 if (defined($patchcheck_end)) {
3186 $end = $patchcheck_end; 3203 $end = $patchcheck_end;
3204 } elsif ($cherry) {
3205 die "PATCHCHECK_END must be defined with PATCHCHECK_CHERRY\n";
3187 } 3206 }
3188 3207
3189 # Get the true sha1's since we can use things like HEAD~3 3208 # Get the true sha1's since we can use things like HEAD~3
@@ -3197,24 +3216,38 @@ sub patchcheck {
3197 $type = "boot"; 3216 $type = "boot";
3198 } 3217 }
3199 3218
3200 open (IN, "git log --pretty=oneline $end|") or 3219 if ($cherry) {
3201 dodie "could not get git list"; 3220 open (IN, "git cherry -v $start $end|") or
3221 dodie "could not get git list";
3222 } else {
3223 open (IN, "git log --pretty=oneline $end|") or
3224 dodie "could not get git list";
3225 }
3202 3226
3203 my @list; 3227 my @list;
3204 3228
3205 while (<IN>) { 3229 while (<IN>) {
3206 chomp; 3230 chomp;
3231 # git cherry adds a '+' we want to remove
3232 s/^\+ //;
3207 $list[$#list+1] = $_; 3233 $list[$#list+1] = $_;
3208 last if (/^$start/); 3234 last if (/^$start/);
3209 } 3235 }
3210 close(IN); 3236 close(IN);
3211 3237
3212 if ($list[$#list] !~ /^$start/) { 3238 if (!$cherry) {
3213 fail "SHA1 $start not found"; 3239 if ($list[$#list] !~ /^$start/) {
3240 fail "SHA1 $start not found";
3241 }
3242
3243 # go backwards in the list
3244 @list = reverse @list;
3214 } 3245 }
3215 3246
3216 # go backwards in the list 3247 doprint("Going to test the following commits:\n");
3217 @list = reverse @list; 3248 foreach my $l (@list) {
3249 doprint "$l\n";
3250 }
3218 3251
3219 my $save_clean = $noclean; 3252 my $save_clean = $noclean;
3220 my %ignored_warnings; 3253 my %ignored_warnings;
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index 911e45ad657a..6c58cd8bbbae 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -906,6 +906,16 @@
906# 906#
907# PATCHCHECK_END is the last patch to check (default HEAD) 907# PATCHCHECK_END is the last patch to check (default HEAD)
908# 908#
909# PATCHCHECK_CHERRY if set to non zero, then git cherry will be
910# performed against PATCHCHECK_START and PATCHCHECK_END. That is
911#
912# git cherry ${PATCHCHECK_START} ${PATCHCHECK_END}
913#
914# Then the changes found will be tested.
915#
916# Note, PATCHCHECK_CHERRY requires PATCHCHECK_END to be defined.
917# (default 0)
918#
909# PATCHCHECK_TYPE is required and is the type of test to run: 919# PATCHCHECK_TYPE is required and is the type of test to run:
910# build, boot, test. 920# build, boot, test.
911# 921#
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index d10f95ce2ea4..45f145c6f843 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -2,8 +2,10 @@ TARGETS = breakpoints
2TARGETS += cpu-hotplug 2TARGETS += cpu-hotplug
3TARGETS += efivarfs 3TARGETS += efivarfs
4TARGETS += kcmp 4TARGETS += kcmp
5TARGETS += memfd
5TARGETS += memory-hotplug 6TARGETS += memory-hotplug
6TARGETS += mqueue 7TARGETS += mqueue
8TARGETS += mount
7TARGETS += net 9TARGETS += net
8TARGETS += ptrace 10TARGETS += ptrace
9TARGETS += timers 11TARGETS += timers
@@ -12,6 +14,7 @@ TARGETS += powerpc
12TARGETS += user 14TARGETS += user
13TARGETS += sysctl 15TARGETS += sysctl
14TARGETS += firmware 16TARGETS += firmware
17TARGETS += ftrace
15 18
16TARGETS_HOTPLUG = cpu-hotplug 19TARGETS_HOTPLUG = cpu-hotplug
17TARGETS_HOTPLUG += memory-hotplug 20TARGETS_HOTPLUG += memory-hotplug
diff --git a/tools/testing/selftests/ftrace/Makefile b/tools/testing/selftests/ftrace/Makefile
new file mode 100644
index 000000000000..76cc9f156267
--- /dev/null
+++ b/tools/testing/selftests/ftrace/Makefile
@@ -0,0 +1,7 @@
1all:
2
3run_tests:
4 @/bin/sh ./ftracetest || echo "ftrace selftests: [FAIL]"
5
6clean:
7 rm -rf logs/*
diff --git a/tools/testing/selftests/ftrace/README b/tools/testing/selftests/ftrace/README
new file mode 100644
index 000000000000..182e76fa4b82
--- /dev/null
+++ b/tools/testing/selftests/ftrace/README
@@ -0,0 +1,82 @@
1Linux Ftrace Testcases
2
3This is a collection of testcases for ftrace tracing feature in the Linux
4kernel. Since ftrace exports interfaces via the debugfs, we just need
5shell scripts for testing. Feel free to add new test cases.
6
7Running the ftrace testcases
8============================
9
10At first, you need to be the root user to run this script.
11To run all testcases:
12
13 $ sudo ./ftracetest
14
15To run specific testcases:
16
17 # ./ftracetest test.d/basic3.tc
18
19Or you can also run testcases under given directory:
20
21 # ./ftracetest test.d/kprobe/
22
23Contributing new testcases
24==========================
25
26Copy test.d/template to your testcase (whose filename must have *.tc
27extension) and rewrite the test description line.
28
29 * The working directory of the script is <debugfs>/tracing/.
30
31 * Take care with side effects as the tests are run with root privilege.
32
33 * The tests should not run for a long period of time (more than 1 min.)
34 These are to be unit tests.
35
36 * You can add a directory for your testcases under test.d/ if needed.
37
38 * The test cases should run on dash (busybox shell) for testing on
39 minimal cross-build environments.
40
41 * Note that the tests are run with "set -e" (errexit) option. If any
42 command fails, the test will be terminated immediately.
43
44 * The tests can return some result codes instead of pass or fail by
45 using exit_unresolved, exit_untested, exit_unsupported and exit_xfail.
46
47Result code
48===========
49
50Ftracetest supports following result codes.
51
52 * PASS: The test succeeded as expected. The test which exits with 0 is
53 counted as passed test.
54
55 * FAIL: The test failed, but was expected to succeed. The test which exits
56 with !0 is counted as failed test.
57
58 * UNRESOLVED: The test produced unclear or intermidiate results.
59 for example, the test was interrupted
60 or the test depends on a previous test, which failed.
61 or the test was set up incorrectly
62 The test which is in above situation, must call exit_unresolved.
63
64 * UNTESTED: The test was not run, currently just a placeholder.
65 In this case, the test must call exit_untested.
66
67 * UNSUPPORTED: The test failed because of lack of feature.
68 In this case, the test must call exit_unsupported.
69
70 * XFAIL: The test failed, and was expected to fail.
71 To return XFAIL, call exit_xfail from the test.
72
73There are some sample test scripts for result code under samples/.
74You can also run samples as below:
75
76 # ./ftracetest samples/
77
78TODO
79====
80
81 * Fancy colored output :)
82
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
new file mode 100755
index 000000000000..515247601df4
--- /dev/null
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -0,0 +1,253 @@
1#!/bin/sh
2
3# ftracetest - Ftrace test shell scripts
4#
5# Copyright (C) Hitachi Ltd., 2014
6# Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
7#
8# Released under the terms of the GPL v2.
9
10usage() { # errno [message]
11[ "$2" ] && echo $2
12echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]"
13echo " Options:"
14echo " -h|--help Show help message"
15echo " -k|--keep Keep passed test logs"
16echo " -d|--debug Debug mode (trace all shell commands)"
17exit $1
18}
19
20errexit() { # message
21 echo "Error: $1" 1>&2
22 exit 1
23}
24
25# Ensuring user privilege
26if [ `id -u` -ne 0 ]; then
27 errexit "this must be run by root user"
28fi
29
30# Utilities
31absdir() { # file_path
32 (cd `dirname $1`; pwd)
33}
34
35abspath() {
36 echo `absdir $1`/`basename $1`
37}
38
39find_testcases() { #directory
40 echo `find $1 -name \*.tc`
41}
42
43parse_opts() { # opts
44 local OPT_TEST_CASES=
45 local OPT_TEST_DIR=
46
47 while [ "$1" ]; do
48 case "$1" in
49 --help|-h)
50 usage 0
51 ;;
52 --keep|-k)
53 KEEP_LOG=1
54 shift 1
55 ;;
56 --debug|-d)
57 DEBUG=1
58 shift 1
59 ;;
60 *.tc)
61 if [ -f "$1" ]; then
62 OPT_TEST_CASES="$OPT_TEST_CASES `abspath $1`"
63 shift 1
64 else
65 usage 1 "$1 is not a testcase"
66 fi
67 ;;
68 *)
69 if [ -d "$1" ]; then
70 OPT_TEST_DIR=`abspath $1`
71 OPT_TEST_CASES="$OPT_TEST_CASES `find_testcases $OPT_TEST_DIR`"
72 shift 1
73 else
74 usage 1 "Invalid option ($1)"
75 fi
76 ;;
77 esac
78 done
79 if [ "$OPT_TEST_CASES" ]; then
80 TEST_CASES=$OPT_TEST_CASES
81 fi
82}
83
84# Parameters
85DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
86TRACING_DIR=$DEBUGFS_DIR/tracing
87TOP_DIR=`absdir $0`
88TEST_DIR=$TOP_DIR/test.d
89TEST_CASES=`find_testcases $TEST_DIR`
90LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/
91KEEP_LOG=0
92DEBUG=0
93# Parse command-line options
94parse_opts $*
95
96[ $DEBUG -ne 0 ] && set -x
97
98# Verify parameters
99if [ -z "$DEBUGFS_DIR" -o ! -d "$TRACING_DIR" ]; then
100 errexit "No ftrace directory found"
101fi
102
103# Preparing logs
104LOG_FILE=$LOG_DIR/ftracetest.log
105mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR"
106date > $LOG_FILE
107prlog() { # messages
108 echo "$@" | tee -a $LOG_FILE
109}
110catlog() { #file
111 cat $1 | tee -a $LOG_FILE
112}
113prlog "=== Ftrace unit tests ==="
114
115
116# Testcase management
117# Test result codes - Dejagnu extended code
118PASS=0 # The test succeeded.
119FAIL=1 # The test failed, but was expected to succeed.
120UNRESOLVED=2 # The test produced indeterminate results. (e.g. interrupted)
121UNTESTED=3 # The test was not run, currently just a placeholder.
122UNSUPPORTED=4 # The test failed because of lack of feature.
123XFAIL=5 # The test failed, and was expected to fail.
124
125# Accumulations
126PASSED_CASES=
127FAILED_CASES=
128UNRESOLVED_CASES=
129UNTESTED_CASES=
130UNSUPPORTED_CASES=
131XFAILED_CASES=
132UNDEFINED_CASES=
133TOTAL_RESULT=0
134
135CASENO=0
136testcase() { # testfile
137 CASENO=$((CASENO+1))
138 prlog -n "[$CASENO]"`grep "^#[ \t]*description:" $1 | cut -f2 -d:`
139}
140
141eval_result() { # retval sigval
142 local retval=$2
143 if [ $2 -eq 0 ]; then
144 test $1 -ne 0 && retval=$FAIL
145 fi
146 case $retval in
147 $PASS)
148 prlog " [PASS]"
149 PASSED_CASES="$PASSED_CASES $CASENO"
150 return 0
151 ;;
152 $FAIL)
153 prlog " [FAIL]"
154 FAILED_CASES="$FAILED_CASES $CASENO"
155 return 1 # this is a bug.
156 ;;
157 $UNRESOLVED)
158 prlog " [UNRESOLVED]"
159 UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO"
160 return 1 # this is a kind of bug.. something happened.
161 ;;
162 $UNTESTED)
163 prlog " [UNTESTED]"
164 UNTESTED_CASES="$UNTESTED_CASES $CASENO"
165 return 0
166 ;;
167 $UNSUPPORTED)
168 prlog " [UNSUPPORTED]"
169 UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO"
170 return 1 # this is not a bug, but the result should be reported.
171 ;;
172 $XFAIL)
173 prlog " [XFAIL]"
174 XFAILED_CASES="$XFAILED_CASES $CASENO"
175 return 0
176 ;;
177 *)
178 prlog " [UNDEFINED]"
179 UNDEFINED_CASES="$UNDEFINED_CASES $CASENO"
180 return 1 # this must be a test bug
181 ;;
182 esac
183}
184
185# Signal handling for result codes
186SIG_RESULT=
187SIG_BASE=36 # Use realtime signals
188SIG_PID=$$
189
190SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED))
191exit_unresolved () {
192 kill -s $SIG_UNRESOLVED $SIG_PID
193 exit 0
194}
195trap 'SIG_RESULT=$UNRESOLVED' $SIG_UNRESOLVED
196
197SIG_UNTESTED=$((SIG_BASE + UNTESTED))
198exit_untested () {
199 kill -s $SIG_UNTESTED $SIG_PID
200 exit 0
201}
202trap 'SIG_RESULT=$UNTESTED' $SIG_UNTESTED
203
204SIG_UNSUPPORTED=$((SIG_BASE + UNSUPPORTED))
205exit_unsupported () {
206 kill -s $SIG_UNSUPPORTED $SIG_PID
207 exit 0
208}
209trap 'SIG_RESULT=$UNSUPPORTED' $SIG_UNSUPPORTED
210
211SIG_XFAIL=$((SIG_BASE + XFAIL))
212exit_xfail () {
213 kill -s $SIG_XFAIL $SIG_PID
214 exit 0
215}
216trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL
217
218# Run one test case
219run_test() { # testfile
220 local testname=`basename $1`
221 local testlog=`mktemp --tmpdir=$LOG_DIR ${testname}-XXXXXX.log`
222 testcase $1
223 echo "execute: "$1 > $testlog
224 SIG_RESULT=0
225 # setup PID and PPID, $$ is not updated.
226 (cd $TRACING_DIR; read PID _ < /proc/self/stat ;
227 set -e; set -x; . $1) >> $testlog 2>&1
228 eval_result $? $SIG_RESULT
229 if [ $? -eq 0 ]; then
230 # Remove test log if the test was done as it was expected.
231 [ $KEEP_LOG -eq 0 ] && rm $testlog
232 else
233 catlog $testlog
234 TOTAL_RESULT=1
235 fi
236}
237
238# Main loop
239for t in $TEST_CASES; do
240 run_test $t
241done
242
243prlog ""
244prlog "# of passed: " `echo $PASSED_CASES | wc -w`
245prlog "# of failed: " `echo $FAILED_CASES | wc -w`
246prlog "# of unresolved: " `echo $UNRESOLVED_CASES | wc -w`
247prlog "# of untested: " `echo $UNTESTED_CASES | wc -w`
248prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w`
249prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w`
250prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w`
251
252# if no error, return 0
253exit $TOTAL_RESULT
diff --git a/tools/testing/selftests/ftrace/samples/fail.tc b/tools/testing/selftests/ftrace/samples/fail.tc
new file mode 100644
index 000000000000..15e35b956e05
--- /dev/null
+++ b/tools/testing/selftests/ftrace/samples/fail.tc
@@ -0,0 +1,4 @@
1#!/bin/sh
2# description: failure-case example
3cat non-exist-file
4echo "this is not executed"
diff --git a/tools/testing/selftests/ftrace/samples/pass.tc b/tools/testing/selftests/ftrace/samples/pass.tc
new file mode 100644
index 000000000000..d01549370041
--- /dev/null
+++ b/tools/testing/selftests/ftrace/samples/pass.tc
@@ -0,0 +1,3 @@
1#!/bin/sh
2# description: pass-case example
3return 0
diff --git a/tools/testing/selftests/ftrace/samples/unresolved.tc b/tools/testing/selftests/ftrace/samples/unresolved.tc
new file mode 100644
index 000000000000..41e99d3358d1
--- /dev/null
+++ b/tools/testing/selftests/ftrace/samples/unresolved.tc
@@ -0,0 +1,4 @@
1#!/bin/sh
2# description: unresolved-case example
3trap exit_unresolved INT
4kill -INT $PID
diff --git a/tools/testing/selftests/ftrace/samples/unsupported.tc b/tools/testing/selftests/ftrace/samples/unsupported.tc
new file mode 100644
index 000000000000..45910ff13328
--- /dev/null
+++ b/tools/testing/selftests/ftrace/samples/unsupported.tc
@@ -0,0 +1,3 @@
1#!/bin/sh
2# description: unsupported-case example
3exit_unsupported
diff --git a/tools/testing/selftests/ftrace/samples/untested.tc b/tools/testing/selftests/ftrace/samples/untested.tc
new file mode 100644
index 000000000000..35a45946ec60
--- /dev/null
+++ b/tools/testing/selftests/ftrace/samples/untested.tc
@@ -0,0 +1,3 @@
1#!/bin/sh
2# description: untested-case example
3exit_untested
diff --git a/tools/testing/selftests/ftrace/samples/xfail.tc b/tools/testing/selftests/ftrace/samples/xfail.tc
new file mode 100644
index 000000000000..9dd395323259
--- /dev/null
+++ b/tools/testing/selftests/ftrace/samples/xfail.tc
@@ -0,0 +1,3 @@
1#!/bin/sh
2# description: xfail-case example
3cat non-exist-file || exit_xfail
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc
new file mode 100644
index 000000000000..9980ff14ae44
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc
@@ -0,0 +1,3 @@
1#!/bin/sh
2# description: Basic trace file check
3test -f README -a -f trace -a -f tracing_on -a -f trace_pipe
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc
new file mode 100644
index 000000000000..bf9a7b037924
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc
@@ -0,0 +1,7 @@
1#!/bin/sh
2# description: Basic test for tracers
3test -f available_tracers
4for t in `cat available_tracers`; do
5 echo $t > current_tracer
6done
7echo nop > current_tracer
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc
new file mode 100644
index 000000000000..bde6625d9785
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc
@@ -0,0 +1,8 @@
1#!/bin/sh
2# description: Basic trace clock test
3test -f trace_clock
4for c in `cat trace_clock | tr -d \[\]`; do
5 echo $c > trace_clock
6 grep '\['$c'\]' trace_clock
7done
8echo local > trace_clock
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
new file mode 100644
index 000000000000..1b8b665ab2b3
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc
@@ -0,0 +1,11 @@
1#!/bin/sh
2# description: Kprobe dynamic event - adding and removing
3
4[ -f kprobe_events ] || exit_unsupported # this is configurable
5
6echo 0 > events/enable
7echo > kprobe_events
8echo p:myevent do_fork > kprobe_events
9grep myevent kprobe_events
10test -d events/kprobes/myevent
11echo > kprobe_events
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
new file mode 100644
index 000000000000..b55c84003587
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
@@ -0,0 +1,13 @@
1#!/bin/sh
2# description: Kprobe dynamic event - busy event check
3
4[ -f kprobe_events ] || exit_unsupported
5
6echo 0 > events/enable
7echo > kprobe_events
8echo p:myevent do_fork > kprobe_events
9test -d events/kprobes/myevent
10echo 1 > events/kprobes/myevent/enable
11echo > kprobe_events && exit 1 # this must fail
12echo 0 > events/kprobes/myevent/enable
13echo > kprobe_events # this must succeed
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
new file mode 100644
index 000000000000..a603d3f8db7b
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
@@ -0,0 +1,16 @@
1#!/bin/sh
2# description: Kprobe dynamic event with arguments
3
4[ -f kprobe_events ] || exit_unsupported # this is configurable
5
6echo 0 > events/enable
7echo > kprobe_events
8echo 'p:testprobe do_fork $stack $stack0 +0($stack)' > kprobe_events
9grep testprobe kprobe_events
10test -d events/kprobes/testprobe
11echo 1 > events/kprobes/testprobe/enable
12( echo "forked")
13echo 0 > events/kprobes/testprobe/enable
14echo "-:testprobe" >> kprobe_events
15test -d events/kprobes/testprobe && exit 1 || exit 0
16
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
new file mode 100644
index 000000000000..283c29e7f7c4
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
@@ -0,0 +1,15 @@
1#!/bin/sh
2# description: Kretprobe dynamic event with arguments
3
4[ -f kprobe_events ] || exit_unsupported # this is configurable
5
6echo 0 > events/enable
7echo > kprobe_events
8echo 'r:testprobe2 do_fork $retval' > kprobe_events
9grep testprobe2 kprobe_events
10test -d events/kprobes/testprobe2
11echo 1 > events/kprobes/testprobe2/enable
12( echo "forked")
13echo 0 > events/kprobes/testprobe2/enable
14echo '-:testprobe2' >> kprobe_events
15test -d events/kprobes/testprobe2 && exit 1 || exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/template b/tools/testing/selftests/ftrace/test.d/template
new file mode 100644
index 000000000000..5448f7abad5f
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/template
@@ -0,0 +1,9 @@
1#!/bin/sh
2# description: %HERE DESCRIBE WHAT THIS DOES%
3# you have to add ".tc" extention for your testcase file
4# Note that all tests are run with "errexit" option.
5
6exit 0 # Return 0 if the test is passed, otherwise return !0
7# If the test could not run because of lack of feature, call exit_unsupported
8# If the test returned unclear results, call exit_unresolved
9# If the test is a dummy, or a placeholder, call exit_untested
diff --git a/tools/testing/selftests/ipc/Makefile b/tools/testing/selftests/ipc/Makefile
index 5386fd7c43ae..74bbefdeaf4c 100644
--- a/tools/testing/selftests/ipc/Makefile
+++ b/tools/testing/selftests/ipc/Makefile
@@ -1,18 +1,18 @@
1uname_M := $(shell uname -m 2>/dev/null || echo not) 1uname_M := $(shell uname -m 2>/dev/null || echo not)
2ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/) 2ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
3ifeq ($(ARCH),i386) 3ifeq ($(ARCH),i386)
4 ARCH := X86 4 ARCH := x86
5 CFLAGS := -DCONFIG_X86_32 -D__i386__ 5 CFLAGS := -DCONFIG_X86_32 -D__i386__
6endif 6endif
7ifeq ($(ARCH),x86_64) 7ifeq ($(ARCH),x86_64)
8 ARCH := X86 8 ARCH := x86
9 CFLAGS := -DCONFIG_X86_64 -D__x86_64__ 9 CFLAGS := -DCONFIG_X86_64 -D__x86_64__
10endif 10endif
11 11
12CFLAGS += -I../../../../usr/include/ 12CFLAGS += -I../../../../usr/include/
13 13
14all: 14all:
15ifeq ($(ARCH),X86) 15ifeq ($(ARCH),x86)
16 gcc $(CFLAGS) msgque.c -o msgque_test 16 gcc $(CFLAGS) msgque.c -o msgque_test
17else 17else
18 echo "Not an x86 target, can't build msgque selftest" 18 echo "Not an x86 target, can't build msgque selftest"
diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile
index d7d6bbeeff2f..8aabd82db9e4 100644
--- a/tools/testing/selftests/kcmp/Makefile
+++ b/tools/testing/selftests/kcmp/Makefile
@@ -1,11 +1,11 @@
1uname_M := $(shell uname -m 2>/dev/null || echo not) 1uname_M := $(shell uname -m 2>/dev/null || echo not)
2ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/) 2ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
3ifeq ($(ARCH),i386) 3ifeq ($(ARCH),i386)
4 ARCH := X86 4 ARCH := x86
5 CFLAGS := -DCONFIG_X86_32 -D__i386__ 5 CFLAGS := -DCONFIG_X86_32 -D__i386__
6endif 6endif
7ifeq ($(ARCH),x86_64) 7ifeq ($(ARCH),x86_64)
8 ARCH := X86 8 ARCH := x86
9 CFLAGS := -DCONFIG_X86_64 -D__x86_64__ 9 CFLAGS := -DCONFIG_X86_64 -D__x86_64__
10endif 10endif
11 11
@@ -15,7 +15,7 @@ CFLAGS += -I../../../../usr/include/
15CFLAGS += -I../../../../arch/x86/include/ 15CFLAGS += -I../../../../arch/x86/include/
16 16
17all: 17all:
18ifeq ($(ARCH),X86) 18ifeq ($(ARCH),x86)
19 gcc $(CFLAGS) kcmp_test.c -o kcmp_test 19 gcc $(CFLAGS) kcmp_test.c -o kcmp_test
20else 20else
21 echo "Not an x86 target, can't build kcmp selftest" 21 echo "Not an x86 target, can't build kcmp selftest"
diff --git a/tools/testing/selftests/memfd/.gitignore b/tools/testing/selftests/memfd/.gitignore
new file mode 100644
index 000000000000..afe87c40ac80
--- /dev/null
+++ b/tools/testing/selftests/memfd/.gitignore
@@ -0,0 +1,4 @@
1fuse_mnt
2fuse_test
3memfd_test
4memfd-test-file
diff --git a/tools/testing/selftests/memfd/Makefile b/tools/testing/selftests/memfd/Makefile
new file mode 100644
index 000000000000..b80cd10d53ba
--- /dev/null
+++ b/tools/testing/selftests/memfd/Makefile
@@ -0,0 +1,20 @@
1CFLAGS += -D_FILE_OFFSET_BITS=64
2CFLAGS += -I../../../../include/uapi/
3CFLAGS += -I../../../../include/
4
5all:
6 gcc $(CFLAGS) memfd_test.c -o memfd_test
7
8run_tests: all
9 gcc $(CFLAGS) memfd_test.c -o memfd_test
10 @./memfd_test || echo "memfd_test: [FAIL]"
11
12build_fuse:
13 gcc $(CFLAGS) fuse_mnt.c `pkg-config fuse --cflags --libs` -o fuse_mnt
14 gcc $(CFLAGS) fuse_test.c -o fuse_test
15
16run_fuse: build_fuse
17 @./run_fuse_test.sh || echo "fuse_test: [FAIL]"
18
19clean:
20 $(RM) memfd_test fuse_test
diff --git a/tools/testing/selftests/memfd/fuse_mnt.c b/tools/testing/selftests/memfd/fuse_mnt.c
new file mode 100644
index 000000000000..feacf1280fcd
--- /dev/null
+++ b/tools/testing/selftests/memfd/fuse_mnt.c
@@ -0,0 +1,110 @@
1/*
2 * memfd test file-system
3 * This file uses FUSE to create a dummy file-system with only one file /memfd.
4 * This file is read-only and takes 1s per read.
5 *
6 * This file-system is used by the memfd test-cases to force the kernel to pin
7 * pages during reads(). Due to the 1s delay of this file-system, this is a
8 * nice way to test race-conditions against get_user_pages() in the kernel.
9 *
10 * We use direct_io==1 to force the kernel to use direct-IO for this
11 * file-system.
12 */
13
14#define FUSE_USE_VERSION 26
15
16#include <fuse.h>
17#include <stdio.h>
18#include <string.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <unistd.h>
22
23static const char memfd_content[] = "memfd-example-content";
24static const char memfd_path[] = "/memfd";
25
26static int memfd_getattr(const char *path, struct stat *st)
27{
28 memset(st, 0, sizeof(*st));
29
30 if (!strcmp(path, "/")) {
31 st->st_mode = S_IFDIR | 0755;
32 st->st_nlink = 2;
33 } else if (!strcmp(path, memfd_path)) {
34 st->st_mode = S_IFREG | 0444;
35 st->st_nlink = 1;
36 st->st_size = strlen(memfd_content);
37 } else {
38 return -ENOENT;
39 }
40
41 return 0;
42}
43
44static int memfd_readdir(const char *path,
45 void *buf,
46 fuse_fill_dir_t filler,
47 off_t offset,
48 struct fuse_file_info *fi)
49{
50 if (strcmp(path, "/"))
51 return -ENOENT;
52
53 filler(buf, ".", NULL, 0);
54 filler(buf, "..", NULL, 0);
55 filler(buf, memfd_path + 1, NULL, 0);
56
57 return 0;
58}
59
60static int memfd_open(const char *path, struct fuse_file_info *fi)
61{
62 if (strcmp(path, memfd_path))
63 return -ENOENT;
64
65 if ((fi->flags & 3) != O_RDONLY)
66 return -EACCES;
67
68 /* force direct-IO */
69 fi->direct_io = 1;
70
71 return 0;
72}
73
74static int memfd_read(const char *path,
75 char *buf,
76 size_t size,
77 off_t offset,
78 struct fuse_file_info *fi)
79{
80 size_t len;
81
82 if (strcmp(path, memfd_path) != 0)
83 return -ENOENT;
84
85 sleep(1);
86
87 len = strlen(memfd_content);
88 if (offset < len) {
89 if (offset + size > len)
90 size = len - offset;
91
92 memcpy(buf, memfd_content + offset, size);
93 } else {
94 size = 0;
95 }
96
97 return size;
98}
99
100static struct fuse_operations memfd_ops = {
101 .getattr = memfd_getattr,
102 .readdir = memfd_readdir,
103 .open = memfd_open,
104 .read = memfd_read,
105};
106
107int main(int argc, char *argv[])
108{
109 return fuse_main(argc, argv, &memfd_ops, NULL);
110}
diff --git a/tools/testing/selftests/memfd/fuse_test.c b/tools/testing/selftests/memfd/fuse_test.c
new file mode 100644
index 000000000000..67908b18f035
--- /dev/null
+++ b/tools/testing/selftests/memfd/fuse_test.c
@@ -0,0 +1,311 @@
1/*
2 * memfd GUP test-case
3 * This tests memfd interactions with get_user_pages(). We require the
4 * fuse_mnt.c program to provide a fake direct-IO FUSE mount-point for us. This
5 * file-system delays _all_ reads by 1s and forces direct-IO. This means, any
6 * read() on files in that file-system will pin the receive-buffer pages for at
7 * least 1s via get_user_pages().
8 *
9 * We use this trick to race ADD_SEALS against a write on a memfd object. The
10 * ADD_SEALS must fail if the memfd pages are still pinned. Note that we use
11 * the read() syscall with our memory-mapped memfd object as receive buffer to
12 * force the kernel to write into our memfd object.
13 */
14
15#define _GNU_SOURCE
16#define __EXPORTED_HEADERS__
17
18#include <errno.h>
19#include <inttypes.h>
20#include <limits.h>
21#include <linux/falloc.h>
22#include <linux/fcntl.h>
23#include <linux/memfd.h>
24#include <sched.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <signal.h>
28#include <string.h>
29#include <sys/mman.h>
30#include <sys/stat.h>
31#include <sys/syscall.h>
32#include <sys/wait.h>
33#include <unistd.h>
34
35#define MFD_DEF_SIZE 8192
36#define STACK_SIZE 65535
37
38static int sys_memfd_create(const char *name,
39 unsigned int flags)
40{
41 return syscall(__NR_memfd_create, name, flags);
42}
43
44static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
45{
46 int r, fd;
47
48 fd = sys_memfd_create(name, flags);
49 if (fd < 0) {
50 printf("memfd_create(\"%s\", %u) failed: %m\n",
51 name, flags);
52 abort();
53 }
54
55 r = ftruncate(fd, sz);
56 if (r < 0) {
57 printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz);
58 abort();
59 }
60
61 return fd;
62}
63
64static __u64 mfd_assert_get_seals(int fd)
65{
66 long r;
67
68 r = fcntl(fd, F_GET_SEALS);
69 if (r < 0) {
70 printf("GET_SEALS(%d) failed: %m\n", fd);
71 abort();
72 }
73
74 return r;
75}
76
77static void mfd_assert_has_seals(int fd, __u64 seals)
78{
79 __u64 s;
80
81 s = mfd_assert_get_seals(fd);
82 if (s != seals) {
83 printf("%llu != %llu = GET_SEALS(%d)\n",
84 (unsigned long long)seals, (unsigned long long)s, fd);
85 abort();
86 }
87}
88
89static void mfd_assert_add_seals(int fd, __u64 seals)
90{
91 long r;
92 __u64 s;
93
94 s = mfd_assert_get_seals(fd);
95 r = fcntl(fd, F_ADD_SEALS, seals);
96 if (r < 0) {
97 printf("ADD_SEALS(%d, %llu -> %llu) failed: %m\n",
98 fd, (unsigned long long)s, (unsigned long long)seals);
99 abort();
100 }
101}
102
103static int mfd_busy_add_seals(int fd, __u64 seals)
104{
105 long r;
106 __u64 s;
107
108 r = fcntl(fd, F_GET_SEALS);
109 if (r < 0)
110 s = 0;
111 else
112 s = r;
113
114 r = fcntl(fd, F_ADD_SEALS, seals);
115 if (r < 0 && errno != EBUSY) {
116 printf("ADD_SEALS(%d, %llu -> %llu) didn't fail as expected with EBUSY: %m\n",
117 fd, (unsigned long long)s, (unsigned long long)seals);
118 abort();
119 }
120
121 return r;
122}
123
124static void *mfd_assert_mmap_shared(int fd)
125{
126 void *p;
127
128 p = mmap(NULL,
129 MFD_DEF_SIZE,
130 PROT_READ | PROT_WRITE,
131 MAP_SHARED,
132 fd,
133 0);
134 if (p == MAP_FAILED) {
135 printf("mmap() failed: %m\n");
136 abort();
137 }
138
139 return p;
140}
141
142static void *mfd_assert_mmap_private(int fd)
143{
144 void *p;
145
146 p = mmap(NULL,
147 MFD_DEF_SIZE,
148 PROT_READ | PROT_WRITE,
149 MAP_PRIVATE,
150 fd,
151 0);
152 if (p == MAP_FAILED) {
153 printf("mmap() failed: %m\n");
154 abort();
155 }
156
157 return p;
158}
159
160static int global_mfd = -1;
161static void *global_p = NULL;
162
163static int sealing_thread_fn(void *arg)
164{
165 int sig, r;
166
167 /*
168 * This thread first waits 200ms so any pending operation in the parent
169 * is correctly started. After that, it tries to seal @global_mfd as
170 * SEAL_WRITE. This _must_ fail as the parent thread has a read() into
171 * that memory mapped object still ongoing.
172 * We then wait one more second and try sealing again. This time it
173 * must succeed as there shouldn't be anyone else pinning the pages.
174 */
175
176 /* wait 200ms for FUSE-request to be active */
177 usleep(200000);
178
179 /* unmount mapping before sealing to avoid i_mmap_writable failures */
180 munmap(global_p, MFD_DEF_SIZE);
181
182 /* Try sealing the global file; expect EBUSY or success. Current
183 * kernels will never succeed, but in the future, kernels might
184 * implement page-replacements or other fancy ways to avoid racing
185 * writes. */
186 r = mfd_busy_add_seals(global_mfd, F_SEAL_WRITE);
187 if (r >= 0) {
188 printf("HURRAY! This kernel fixed GUP races!\n");
189 } else {
190 /* wait 1s more so the FUSE-request is done */
191 sleep(1);
192
193 /* try sealing the global file again */
194 mfd_assert_add_seals(global_mfd, F_SEAL_WRITE);
195 }
196
197 return 0;
198}
199
200static pid_t spawn_sealing_thread(void)
201{
202 uint8_t *stack;
203 pid_t pid;
204
205 stack = malloc(STACK_SIZE);
206 if (!stack) {
207 printf("malloc(STACK_SIZE) failed: %m\n");
208 abort();
209 }
210
211 pid = clone(sealing_thread_fn,
212 stack + STACK_SIZE,
213 SIGCHLD | CLONE_FILES | CLONE_FS | CLONE_VM,
214 NULL);
215 if (pid < 0) {
216 printf("clone() failed: %m\n");
217 abort();
218 }
219
220 return pid;
221}
222
223static void join_sealing_thread(pid_t pid)
224{
225 waitpid(pid, NULL, 0);
226}
227
228int main(int argc, char **argv)
229{
230 static const char zero[MFD_DEF_SIZE];
231 int fd, mfd, r;
232 void *p;
233 int was_sealed;
234 pid_t pid;
235
236 if (argc < 2) {
237 printf("error: please pass path to file in fuse_mnt mount-point\n");
238 abort();
239 }
240
241 /* open FUSE memfd file for GUP testing */
242 printf("opening: %s\n", argv[1]);
243 fd = open(argv[1], O_RDONLY | O_CLOEXEC);
244 if (fd < 0) {
245 printf("cannot open(\"%s\"): %m\n", argv[1]);
246 abort();
247 }
248
249 /* create new memfd-object */
250 mfd = mfd_assert_new("kern_memfd_fuse",
251 MFD_DEF_SIZE,
252 MFD_CLOEXEC | MFD_ALLOW_SEALING);
253
254 /* mmap memfd-object for writing */
255 p = mfd_assert_mmap_shared(mfd);
256
257 /* pass mfd+mapping to a separate sealing-thread which tries to seal
258 * the memfd objects with SEAL_WRITE while we write into it */
259 global_mfd = mfd;
260 global_p = p;
261 pid = spawn_sealing_thread();
262
263 /* Use read() on the FUSE file to read into our memory-mapped memfd
264 * object. This races the other thread which tries to seal the
265 * memfd-object.
266 * If @fd is on the memfd-fake-FUSE-FS, the read() is delayed by 1s.
267 * This guarantees that the receive-buffer is pinned for 1s until the
268 * data is written into it. The racing ADD_SEALS should thus fail as
269 * the pages are still pinned. */
270 r = read(fd, p, MFD_DEF_SIZE);
271 if (r < 0) {
272 printf("read() failed: %m\n");
273 abort();
274 } else if (!r) {
275 printf("unexpected EOF on read()\n");
276 abort();
277 }
278
279 was_sealed = mfd_assert_get_seals(mfd) & F_SEAL_WRITE;
280
281 /* Wait for sealing-thread to finish and verify that it
282 * successfully sealed the file after the second try. */
283 join_sealing_thread(pid);
284 mfd_assert_has_seals(mfd, F_SEAL_WRITE);
285
286 /* *IF* the memfd-object was sealed at the time our read() returned,
287 * then the kernel did a page-replacement or canceled the read() (or
288 * whatever magic it did..). In that case, the memfd object is still
289 * all zero.
290 * In case the memfd-object was *not* sealed, the read() was successfull
291 * and the memfd object must *not* be all zero.
292 * Note that in real scenarios, there might be a mixture of both, but
293 * in this test-cases, we have explicit 200ms delays which should be
294 * enough to avoid any in-flight writes. */
295
296 p = mfd_assert_mmap_private(mfd);
297 if (was_sealed && memcmp(p, zero, MFD_DEF_SIZE)) {
298 printf("memfd sealed during read() but data not discarded\n");
299 abort();
300 } else if (!was_sealed && !memcmp(p, zero, MFD_DEF_SIZE)) {
301 printf("memfd sealed after read() but data discarded\n");
302 abort();
303 }
304
305 close(mfd);
306 close(fd);
307
308 printf("fuse: DONE\n");
309
310 return 0;
311}
diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c
new file mode 100644
index 000000000000..0b9eafb7ab7b
--- /dev/null
+++ b/tools/testing/selftests/memfd/memfd_test.c
@@ -0,0 +1,911 @@
1#define _GNU_SOURCE
2#define __EXPORTED_HEADERS__
3
4#include <errno.h>
5#include <inttypes.h>
6#include <limits.h>
7#include <linux/falloc.h>
8#include <linux/fcntl.h>
9#include <linux/memfd.h>
10#include <sched.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <signal.h>
14#include <string.h>
15#include <sys/mman.h>
16#include <sys/stat.h>
17#include <sys/syscall.h>
18#include <unistd.h>
19
20#define MFD_DEF_SIZE 8192
21#define STACK_SIZE 65535
22
23static int sys_memfd_create(const char *name,
24 unsigned int flags)
25{
26 return syscall(__NR_memfd_create, name, flags);
27}
28
29static int mfd_assert_new(const char *name, loff_t sz, unsigned int flags)
30{
31 int r, fd;
32
33 fd = sys_memfd_create(name, flags);
34 if (fd < 0) {
35 printf("memfd_create(\"%s\", %u) failed: %m\n",
36 name, flags);
37 abort();
38 }
39
40 r = ftruncate(fd, sz);
41 if (r < 0) {
42 printf("ftruncate(%llu) failed: %m\n", (unsigned long long)sz);
43 abort();
44 }
45
46 return fd;
47}
48
49static void mfd_fail_new(const char *name, unsigned int flags)
50{
51 int r;
52
53 r = sys_memfd_create(name, flags);
54 if (r >= 0) {
55 printf("memfd_create(\"%s\", %u) succeeded, but failure expected\n",
56 name, flags);
57 close(r);
58 abort();
59 }
60}
61
62static unsigned int mfd_assert_get_seals(int fd)
63{
64 int r;
65
66 r = fcntl(fd, F_GET_SEALS);
67 if (r < 0) {
68 printf("GET_SEALS(%d) failed: %m\n", fd);
69 abort();
70 }
71
72 return (unsigned int)r;
73}
74
75static void mfd_assert_has_seals(int fd, unsigned int seals)
76{
77 unsigned int s;
78
79 s = mfd_assert_get_seals(fd);
80 if (s != seals) {
81 printf("%u != %u = GET_SEALS(%d)\n", seals, s, fd);
82 abort();
83 }
84}
85
86static void mfd_assert_add_seals(int fd, unsigned int seals)
87{
88 int r;
89 unsigned int s;
90
91 s = mfd_assert_get_seals(fd);
92 r = fcntl(fd, F_ADD_SEALS, seals);
93 if (r < 0) {
94 printf("ADD_SEALS(%d, %u -> %u) failed: %m\n", fd, s, seals);
95 abort();
96 }
97}
98
99static void mfd_fail_add_seals(int fd, unsigned int seals)
100{
101 int r;
102 unsigned int s;
103
104 r = fcntl(fd, F_GET_SEALS);
105 if (r < 0)
106 s = 0;
107 else
108 s = (unsigned int)r;
109
110 r = fcntl(fd, F_ADD_SEALS, seals);
111 if (r >= 0) {
112 printf("ADD_SEALS(%d, %u -> %u) didn't fail as expected\n",
113 fd, s, seals);
114 abort();
115 }
116}
117
118static void mfd_assert_size(int fd, size_t size)
119{
120 struct stat st;
121 int r;
122
123 r = fstat(fd, &st);
124 if (r < 0) {
125 printf("fstat(%d) failed: %m\n", fd);
126 abort();
127 } else if (st.st_size != size) {
128 printf("wrong file size %lld, but expected %lld\n",
129 (long long)st.st_size, (long long)size);
130 abort();
131 }
132}
133
134static int mfd_assert_dup(int fd)
135{
136 int r;
137
138 r = dup(fd);
139 if (r < 0) {
140 printf("dup(%d) failed: %m\n", fd);
141 abort();
142 }
143
144 return r;
145}
146
147static void *mfd_assert_mmap_shared(int fd)
148{
149 void *p;
150
151 p = mmap(NULL,
152 MFD_DEF_SIZE,
153 PROT_READ | PROT_WRITE,
154 MAP_SHARED,
155 fd,
156 0);
157 if (p == MAP_FAILED) {
158 printf("mmap() failed: %m\n");
159 abort();
160 }
161
162 return p;
163}
164
165static void *mfd_assert_mmap_private(int fd)
166{
167 void *p;
168
169 p = mmap(NULL,
170 MFD_DEF_SIZE,
171 PROT_READ,
172 MAP_PRIVATE,
173 fd,
174 0);
175 if (p == MAP_FAILED) {
176 printf("mmap() failed: %m\n");
177 abort();
178 }
179
180 return p;
181}
182
183static int mfd_assert_open(int fd, int flags, mode_t mode)
184{
185 char buf[512];
186 int r;
187
188 sprintf(buf, "/proc/self/fd/%d", fd);
189 r = open(buf, flags, mode);
190 if (r < 0) {
191 printf("open(%s) failed: %m\n", buf);
192 abort();
193 }
194
195 return r;
196}
197
198static void mfd_fail_open(int fd, int flags, mode_t mode)
199{
200 char buf[512];
201 int r;
202
203 sprintf(buf, "/proc/self/fd/%d", fd);
204 r = open(buf, flags, mode);
205 if (r >= 0) {
206 printf("open(%s) didn't fail as expected\n", buf);
207 abort();
208 }
209}
210
211static void mfd_assert_read(int fd)
212{
213 char buf[16];
214 void *p;
215 ssize_t l;
216
217 l = read(fd, buf, sizeof(buf));
218 if (l != sizeof(buf)) {
219 printf("read() failed: %m\n");
220 abort();
221 }
222
223 /* verify PROT_READ *is* allowed */
224 p = mmap(NULL,
225 MFD_DEF_SIZE,
226 PROT_READ,
227 MAP_PRIVATE,
228 fd,
229 0);
230 if (p == MAP_FAILED) {
231 printf("mmap() failed: %m\n");
232 abort();
233 }
234 munmap(p, MFD_DEF_SIZE);
235
236 /* verify MAP_PRIVATE is *always* allowed (even writable) */
237 p = mmap(NULL,
238 MFD_DEF_SIZE,
239 PROT_READ | PROT_WRITE,
240 MAP_PRIVATE,
241 fd,
242 0);
243 if (p == MAP_FAILED) {
244 printf("mmap() failed: %m\n");
245 abort();
246 }
247 munmap(p, MFD_DEF_SIZE);
248}
249
250static void mfd_assert_write(int fd)
251{
252 ssize_t l;
253 void *p;
254 int r;
255
256 /* verify write() succeeds */
257 l = write(fd, "\0\0\0\0", 4);
258 if (l != 4) {
259 printf("write() failed: %m\n");
260 abort();
261 }
262
263 /* verify PROT_READ | PROT_WRITE is allowed */
264 p = mmap(NULL,
265 MFD_DEF_SIZE,
266 PROT_READ | PROT_WRITE,
267 MAP_SHARED,
268 fd,
269 0);
270 if (p == MAP_FAILED) {
271 printf("mmap() failed: %m\n");
272 abort();
273 }
274 *(char *)p = 0;
275 munmap(p, MFD_DEF_SIZE);
276
277 /* verify PROT_WRITE is allowed */
278 p = mmap(NULL,
279 MFD_DEF_SIZE,
280 PROT_WRITE,
281 MAP_SHARED,
282 fd,
283 0);
284 if (p == MAP_FAILED) {
285 printf("mmap() failed: %m\n");
286 abort();
287 }
288 *(char *)p = 0;
289 munmap(p, MFD_DEF_SIZE);
290
291 /* verify PROT_READ with MAP_SHARED is allowed and a following
292 * mprotect(PROT_WRITE) allows writing */
293 p = mmap(NULL,
294 MFD_DEF_SIZE,
295 PROT_READ,
296 MAP_SHARED,
297 fd,
298 0);
299 if (p == MAP_FAILED) {
300 printf("mmap() failed: %m\n");
301 abort();
302 }
303
304 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
305 if (r < 0) {
306 printf("mprotect() failed: %m\n");
307 abort();
308 }
309
310 *(char *)p = 0;
311 munmap(p, MFD_DEF_SIZE);
312
313 /* verify PUNCH_HOLE works */
314 r = fallocate(fd,
315 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
316 0,
317 MFD_DEF_SIZE);
318 if (r < 0) {
319 printf("fallocate(PUNCH_HOLE) failed: %m\n");
320 abort();
321 }
322}
323
324static void mfd_fail_write(int fd)
325{
326 ssize_t l;
327 void *p;
328 int r;
329
330 /* verify write() fails */
331 l = write(fd, "data", 4);
332 if (l != -EPERM) {
333 printf("expected EPERM on write(), but got %d: %m\n", (int)l);
334 abort();
335 }
336
337 /* verify PROT_READ | PROT_WRITE is not allowed */
338 p = mmap(NULL,
339 MFD_DEF_SIZE,
340 PROT_READ | PROT_WRITE,
341 MAP_SHARED,
342 fd,
343 0);
344 if (p != MAP_FAILED) {
345 printf("mmap() didn't fail as expected\n");
346 abort();
347 }
348
349 /* verify PROT_WRITE is not allowed */
350 p = mmap(NULL,
351 MFD_DEF_SIZE,
352 PROT_WRITE,
353 MAP_SHARED,
354 fd,
355 0);
356 if (p != MAP_FAILED) {
357 printf("mmap() didn't fail as expected\n");
358 abort();
359 }
360
361 /* Verify PROT_READ with MAP_SHARED with a following mprotect is not
362 * allowed. Note that for r/w the kernel already prevents the mmap. */
363 p = mmap(NULL,
364 MFD_DEF_SIZE,
365 PROT_READ,
366 MAP_SHARED,
367 fd,
368 0);
369 if (p != MAP_FAILED) {
370 r = mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE);
371 if (r >= 0) {
372 printf("mmap()+mprotect() didn't fail as expected\n");
373 abort();
374 }
375 }
376
377 /* verify PUNCH_HOLE fails */
378 r = fallocate(fd,
379 FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
380 0,
381 MFD_DEF_SIZE);
382 if (r >= 0) {
383 printf("fallocate(PUNCH_HOLE) didn't fail as expected\n");
384 abort();
385 }
386}
387
388static void mfd_assert_shrink(int fd)
389{
390 int r, fd2;
391
392 r = ftruncate(fd, MFD_DEF_SIZE / 2);
393 if (r < 0) {
394 printf("ftruncate(SHRINK) failed: %m\n");
395 abort();
396 }
397
398 mfd_assert_size(fd, MFD_DEF_SIZE / 2);
399
400 fd2 = mfd_assert_open(fd,
401 O_RDWR | O_CREAT | O_TRUNC,
402 S_IRUSR | S_IWUSR);
403 close(fd2);
404
405 mfd_assert_size(fd, 0);
406}
407
408static void mfd_fail_shrink(int fd)
409{
410 int r;
411
412 r = ftruncate(fd, MFD_DEF_SIZE / 2);
413 if (r >= 0) {
414 printf("ftruncate(SHRINK) didn't fail as expected\n");
415 abort();
416 }
417
418 mfd_fail_open(fd,
419 O_RDWR | O_CREAT | O_TRUNC,
420 S_IRUSR | S_IWUSR);
421}
422
423static void mfd_assert_grow(int fd)
424{
425 int r;
426
427 r = ftruncate(fd, MFD_DEF_SIZE * 2);
428 if (r < 0) {
429 printf("ftruncate(GROW) failed: %m\n");
430 abort();
431 }
432
433 mfd_assert_size(fd, MFD_DEF_SIZE * 2);
434
435 r = fallocate(fd,
436 0,
437 0,
438 MFD_DEF_SIZE * 4);
439 if (r < 0) {
440 printf("fallocate(ALLOC) failed: %m\n");
441 abort();
442 }
443
444 mfd_assert_size(fd, MFD_DEF_SIZE * 4);
445}
446
447static void mfd_fail_grow(int fd)
448{
449 int r;
450
451 r = ftruncate(fd, MFD_DEF_SIZE * 2);
452 if (r >= 0) {
453 printf("ftruncate(GROW) didn't fail as expected\n");
454 abort();
455 }
456
457 r = fallocate(fd,
458 0,
459 0,
460 MFD_DEF_SIZE * 4);
461 if (r >= 0) {
462 printf("fallocate(ALLOC) didn't fail as expected\n");
463 abort();
464 }
465}
466
467static void mfd_assert_grow_write(int fd)
468{
469 static char buf[MFD_DEF_SIZE * 8];
470 ssize_t l;
471
472 l = pwrite(fd, buf, sizeof(buf), 0);
473 if (l != sizeof(buf)) {
474 printf("pwrite() failed: %m\n");
475 abort();
476 }
477
478 mfd_assert_size(fd, MFD_DEF_SIZE * 8);
479}
480
481static void mfd_fail_grow_write(int fd)
482{
483 static char buf[MFD_DEF_SIZE * 8];
484 ssize_t l;
485
486 l = pwrite(fd, buf, sizeof(buf), 0);
487 if (l == sizeof(buf)) {
488 printf("pwrite() didn't fail as expected\n");
489 abort();
490 }
491}
492
493static int idle_thread_fn(void *arg)
494{
495 sigset_t set;
496 int sig;
497
498 /* dummy waiter; SIGTERM terminates us anyway */
499 sigemptyset(&set);
500 sigaddset(&set, SIGTERM);
501 sigwait(&set, &sig);
502
503 return 0;
504}
505
506static pid_t spawn_idle_thread(unsigned int flags)
507{
508 uint8_t *stack;
509 pid_t pid;
510
511 stack = malloc(STACK_SIZE);
512 if (!stack) {
513 printf("malloc(STACK_SIZE) failed: %m\n");
514 abort();
515 }
516
517 pid = clone(idle_thread_fn,
518 stack + STACK_SIZE,
519 SIGCHLD | flags,
520 NULL);
521 if (pid < 0) {
522 printf("clone() failed: %m\n");
523 abort();
524 }
525
526 return pid;
527}
528
529static void join_idle_thread(pid_t pid)
530{
531 kill(pid, SIGTERM);
532 waitpid(pid, NULL, 0);
533}
534
535/*
536 * Test memfd_create() syscall
537 * Verify syscall-argument validation, including name checks, flag validation
538 * and more.
539 */
540static void test_create(void)
541{
542 char buf[2048];
543 int fd;
544
545 /* test NULL name */
546 mfd_fail_new(NULL, 0);
547
548 /* test over-long name (not zero-terminated) */
549 memset(buf, 0xff, sizeof(buf));
550 mfd_fail_new(buf, 0);
551
552 /* test over-long zero-terminated name */
553 memset(buf, 0xff, sizeof(buf));
554 buf[sizeof(buf) - 1] = 0;
555 mfd_fail_new(buf, 0);
556
557 /* verify "" is a valid name */
558 fd = mfd_assert_new("", 0, 0);
559 close(fd);
560
561 /* verify invalid O_* open flags */
562 mfd_fail_new("", 0x0100);
563 mfd_fail_new("", ~MFD_CLOEXEC);
564 mfd_fail_new("", ~MFD_ALLOW_SEALING);
565 mfd_fail_new("", ~0);
566 mfd_fail_new("", 0x80000000U);
567
568 /* verify MFD_CLOEXEC is allowed */
569 fd = mfd_assert_new("", 0, MFD_CLOEXEC);
570 close(fd);
571
572 /* verify MFD_ALLOW_SEALING is allowed */
573 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING);
574 close(fd);
575
576 /* verify MFD_ALLOW_SEALING | MFD_CLOEXEC is allowed */
577 fd = mfd_assert_new("", 0, MFD_ALLOW_SEALING | MFD_CLOEXEC);
578 close(fd);
579}
580
581/*
582 * Test basic sealing
583 * A very basic sealing test to see whether setting/retrieving seals works.
584 */
585static void test_basic(void)
586{
587 int fd;
588
589 fd = mfd_assert_new("kern_memfd_basic",
590 MFD_DEF_SIZE,
591 MFD_CLOEXEC | MFD_ALLOW_SEALING);
592
593 /* add basic seals */
594 mfd_assert_has_seals(fd, 0);
595 mfd_assert_add_seals(fd, F_SEAL_SHRINK |
596 F_SEAL_WRITE);
597 mfd_assert_has_seals(fd, F_SEAL_SHRINK |
598 F_SEAL_WRITE);
599
600 /* add them again */
601 mfd_assert_add_seals(fd, F_SEAL_SHRINK |
602 F_SEAL_WRITE);
603 mfd_assert_has_seals(fd, F_SEAL_SHRINK |
604 F_SEAL_WRITE);
605
606 /* add more seals and seal against sealing */
607 mfd_assert_add_seals(fd, F_SEAL_GROW | F_SEAL_SEAL);
608 mfd_assert_has_seals(fd, F_SEAL_SHRINK |
609 F_SEAL_GROW |
610 F_SEAL_WRITE |
611 F_SEAL_SEAL);
612
613 /* verify that sealing no longer works */
614 mfd_fail_add_seals(fd, F_SEAL_GROW);
615 mfd_fail_add_seals(fd, 0);
616
617 close(fd);
618
619 /* verify sealing does not work without MFD_ALLOW_SEALING */
620 fd = mfd_assert_new("kern_memfd_basic",
621 MFD_DEF_SIZE,
622 MFD_CLOEXEC);
623 mfd_assert_has_seals(fd, F_SEAL_SEAL);
624 mfd_fail_add_seals(fd, F_SEAL_SHRINK |
625 F_SEAL_GROW |
626 F_SEAL_WRITE);
627 mfd_assert_has_seals(fd, F_SEAL_SEAL);
628 close(fd);
629}
630
631/*
632 * Test SEAL_WRITE
633 * Test whether SEAL_WRITE actually prevents modifications.
634 */
635static void test_seal_write(void)
636{
637 int fd;
638
639 fd = mfd_assert_new("kern_memfd_seal_write",
640 MFD_DEF_SIZE,
641 MFD_CLOEXEC | MFD_ALLOW_SEALING);
642 mfd_assert_has_seals(fd, 0);
643 mfd_assert_add_seals(fd, F_SEAL_WRITE);
644 mfd_assert_has_seals(fd, F_SEAL_WRITE);
645
646 mfd_assert_read(fd);
647 mfd_fail_write(fd);
648 mfd_assert_shrink(fd);
649 mfd_assert_grow(fd);
650 mfd_fail_grow_write(fd);
651
652 close(fd);
653}
654
655/*
656 * Test SEAL_SHRINK
657 * Test whether SEAL_SHRINK actually prevents shrinking
658 */
659static void test_seal_shrink(void)
660{
661 int fd;
662
663 fd = mfd_assert_new("kern_memfd_seal_shrink",
664 MFD_DEF_SIZE,
665 MFD_CLOEXEC | MFD_ALLOW_SEALING);
666 mfd_assert_has_seals(fd, 0);
667 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
668 mfd_assert_has_seals(fd, F_SEAL_SHRINK);
669
670 mfd_assert_read(fd);
671 mfd_assert_write(fd);
672 mfd_fail_shrink(fd);
673 mfd_assert_grow(fd);
674 mfd_assert_grow_write(fd);
675
676 close(fd);
677}
678
679/*
680 * Test SEAL_GROW
681 * Test whether SEAL_GROW actually prevents growing
682 */
683static void test_seal_grow(void)
684{
685 int fd;
686
687 fd = mfd_assert_new("kern_memfd_seal_grow",
688 MFD_DEF_SIZE,
689 MFD_CLOEXEC | MFD_ALLOW_SEALING);
690 mfd_assert_has_seals(fd, 0);
691 mfd_assert_add_seals(fd, F_SEAL_GROW);
692 mfd_assert_has_seals(fd, F_SEAL_GROW);
693
694 mfd_assert_read(fd);
695 mfd_assert_write(fd);
696 mfd_assert_shrink(fd);
697 mfd_fail_grow(fd);
698 mfd_fail_grow_write(fd);
699
700 close(fd);
701}
702
703/*
704 * Test SEAL_SHRINK | SEAL_GROW
705 * Test whether SEAL_SHRINK | SEAL_GROW actually prevents resizing
706 */
707static void test_seal_resize(void)
708{
709 int fd;
710
711 fd = mfd_assert_new("kern_memfd_seal_resize",
712 MFD_DEF_SIZE,
713 MFD_CLOEXEC | MFD_ALLOW_SEALING);
714 mfd_assert_has_seals(fd, 0);
715 mfd_assert_add_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
716 mfd_assert_has_seals(fd, F_SEAL_SHRINK | F_SEAL_GROW);
717
718 mfd_assert_read(fd);
719 mfd_assert_write(fd);
720 mfd_fail_shrink(fd);
721 mfd_fail_grow(fd);
722 mfd_fail_grow_write(fd);
723
724 close(fd);
725}
726
727/*
728 * Test sharing via dup()
729 * Test that seals are shared between dupped FDs and they're all equal.
730 */
731static void test_share_dup(void)
732{
733 int fd, fd2;
734
735 fd = mfd_assert_new("kern_memfd_share_dup",
736 MFD_DEF_SIZE,
737 MFD_CLOEXEC | MFD_ALLOW_SEALING);
738 mfd_assert_has_seals(fd, 0);
739
740 fd2 = mfd_assert_dup(fd);
741 mfd_assert_has_seals(fd2, 0);
742
743 mfd_assert_add_seals(fd, F_SEAL_WRITE);
744 mfd_assert_has_seals(fd, F_SEAL_WRITE);
745 mfd_assert_has_seals(fd2, F_SEAL_WRITE);
746
747 mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
748 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
749 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
750
751 mfd_assert_add_seals(fd, F_SEAL_SEAL);
752 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
753 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
754
755 mfd_fail_add_seals(fd, F_SEAL_GROW);
756 mfd_fail_add_seals(fd2, F_SEAL_GROW);
757 mfd_fail_add_seals(fd, F_SEAL_SEAL);
758 mfd_fail_add_seals(fd2, F_SEAL_SEAL);
759
760 close(fd2);
761
762 mfd_fail_add_seals(fd, F_SEAL_GROW);
763 close(fd);
764}
765
766/*
767 * Test sealing with active mmap()s
768 * Modifying seals is only allowed if no other mmap() refs exist.
769 */
770static void test_share_mmap(void)
771{
772 int fd;
773 void *p;
774
775 fd = mfd_assert_new("kern_memfd_share_mmap",
776 MFD_DEF_SIZE,
777 MFD_CLOEXEC | MFD_ALLOW_SEALING);
778 mfd_assert_has_seals(fd, 0);
779
780 /* shared/writable ref prevents sealing WRITE, but allows others */
781 p = mfd_assert_mmap_shared(fd);
782 mfd_fail_add_seals(fd, F_SEAL_WRITE);
783 mfd_assert_has_seals(fd, 0);
784 mfd_assert_add_seals(fd, F_SEAL_SHRINK);
785 mfd_assert_has_seals(fd, F_SEAL_SHRINK);
786 munmap(p, MFD_DEF_SIZE);
787
788 /* readable ref allows sealing */
789 p = mfd_assert_mmap_private(fd);
790 mfd_assert_add_seals(fd, F_SEAL_WRITE);
791 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
792 munmap(p, MFD_DEF_SIZE);
793
794 close(fd);
795}
796
797/*
798 * Test sealing with open(/proc/self/fd/%d)
799 * Via /proc we can get access to a separate file-context for the same memfd.
800 * This is *not* like dup(), but like a real separate open(). Make sure the
801 * semantics are as expected and we correctly check for RDONLY / WRONLY / RDWR.
802 */
803static void test_share_open(void)
804{
805 int fd, fd2;
806
807 fd = mfd_assert_new("kern_memfd_share_open",
808 MFD_DEF_SIZE,
809 MFD_CLOEXEC | MFD_ALLOW_SEALING);
810 mfd_assert_has_seals(fd, 0);
811
812 fd2 = mfd_assert_open(fd, O_RDWR, 0);
813 mfd_assert_add_seals(fd, F_SEAL_WRITE);
814 mfd_assert_has_seals(fd, F_SEAL_WRITE);
815 mfd_assert_has_seals(fd2, F_SEAL_WRITE);
816
817 mfd_assert_add_seals(fd2, F_SEAL_SHRINK);
818 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
819 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
820
821 close(fd);
822 fd = mfd_assert_open(fd2, O_RDONLY, 0);
823
824 mfd_fail_add_seals(fd, F_SEAL_SEAL);
825 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK);
826 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK);
827
828 close(fd2);
829 fd2 = mfd_assert_open(fd, O_RDWR, 0);
830
831 mfd_assert_add_seals(fd2, F_SEAL_SEAL);
832 mfd_assert_has_seals(fd, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
833 mfd_assert_has_seals(fd2, F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_SEAL);
834
835 close(fd2);
836 close(fd);
837}
838
839/*
840 * Test sharing via fork()
841 * Test whether seal-modifications work as expected with forked childs.
842 */
843static void test_share_fork(void)
844{
845 int fd;
846 pid_t pid;
847
848 fd = mfd_assert_new("kern_memfd_share_fork",
849 MFD_DEF_SIZE,
850 MFD_CLOEXEC | MFD_ALLOW_SEALING);
851 mfd_assert_has_seals(fd, 0);
852
853 pid = spawn_idle_thread(0);
854 mfd_assert_add_seals(fd, F_SEAL_SEAL);
855 mfd_assert_has_seals(fd, F_SEAL_SEAL);
856
857 mfd_fail_add_seals(fd, F_SEAL_WRITE);
858 mfd_assert_has_seals(fd, F_SEAL_SEAL);
859
860 join_idle_thread(pid);
861
862 mfd_fail_add_seals(fd, F_SEAL_WRITE);
863 mfd_assert_has_seals(fd, F_SEAL_SEAL);
864
865 close(fd);
866}
867
868int main(int argc, char **argv)
869{
870 pid_t pid;
871
872 printf("memfd: CREATE\n");
873 test_create();
874 printf("memfd: BASIC\n");
875 test_basic();
876
877 printf("memfd: SEAL-WRITE\n");
878 test_seal_write();
879 printf("memfd: SEAL-SHRINK\n");
880 test_seal_shrink();
881 printf("memfd: SEAL-GROW\n");
882 test_seal_grow();
883 printf("memfd: SEAL-RESIZE\n");
884 test_seal_resize();
885
886 printf("memfd: SHARE-DUP\n");
887 test_share_dup();
888 printf("memfd: SHARE-MMAP\n");
889 test_share_mmap();
890 printf("memfd: SHARE-OPEN\n");
891 test_share_open();
892 printf("memfd: SHARE-FORK\n");
893 test_share_fork();
894
895 /* Run test-suite in a multi-threaded environment with a shared
896 * file-table. */
897 pid = spawn_idle_thread(CLONE_FILES | CLONE_FS | CLONE_VM);
898 printf("memfd: SHARE-DUP (shared file-table)\n");
899 test_share_dup();
900 printf("memfd: SHARE-MMAP (shared file-table)\n");
901 test_share_mmap();
902 printf("memfd: SHARE-OPEN (shared file-table)\n");
903 test_share_open();
904 printf("memfd: SHARE-FORK (shared file-table)\n");
905 test_share_fork();
906 join_idle_thread(pid);
907
908 printf("memfd: DONE\n");
909
910 return 0;
911}
diff --git a/tools/testing/selftests/memfd/run_fuse_test.sh b/tools/testing/selftests/memfd/run_fuse_test.sh
new file mode 100644
index 000000000000..69b930e1e041
--- /dev/null
+++ b/tools/testing/selftests/memfd/run_fuse_test.sh
@@ -0,0 +1,14 @@
1#!/bin/sh
2
3if test -d "./mnt" ; then
4 fusermount -u ./mnt
5 rmdir ./mnt
6fi
7
8set -e
9
10mkdir mnt
11./fuse_mnt ./mnt
12./fuse_test ./mnt/memfd
13fusermount -u ./mnt
14rmdir ./mnt
diff --git a/tools/testing/selftests/mount/Makefile b/tools/testing/selftests/mount/Makefile
new file mode 100644
index 000000000000..337d853c2b72
--- /dev/null
+++ b/tools/testing/selftests/mount/Makefile
@@ -0,0 +1,17 @@
1# Makefile for mount selftests.
2
3all: unprivileged-remount-test
4
5unprivileged-remount-test: unprivileged-remount-test.c
6 gcc -Wall -O2 unprivileged-remount-test.c -o unprivileged-remount-test
7
8# Allow specific tests to be selected.
9test_unprivileged_remount: unprivileged-remount-test
10 @if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi
11
12run_tests: all test_unprivileged_remount
13
14clean:
15 rm -f unprivileged-remount-test
16
17.PHONY: all test_unprivileged_remount
diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c
new file mode 100644
index 000000000000..1b3ff2fda4d0
--- /dev/null
+++ b/tools/testing/selftests/mount/unprivileged-remount-test.c
@@ -0,0 +1,242 @@
1#define _GNU_SOURCE
2#include <sched.h>
3#include <stdio.h>
4#include <errno.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/mount.h>
8#include <sys/wait.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <fcntl.h>
12#include <grp.h>
13#include <stdbool.h>
14#include <stdarg.h>
15
16#ifndef CLONE_NEWNS
17# define CLONE_NEWNS 0x00020000
18#endif
19#ifndef CLONE_NEWUTS
20# define CLONE_NEWUTS 0x04000000
21#endif
22#ifndef CLONE_NEWIPC
23# define CLONE_NEWIPC 0x08000000
24#endif
25#ifndef CLONE_NEWNET
26# define CLONE_NEWNET 0x40000000
27#endif
28#ifndef CLONE_NEWUSER
29# define CLONE_NEWUSER 0x10000000
30#endif
31#ifndef CLONE_NEWPID
32# define CLONE_NEWPID 0x20000000
33#endif
34
35#ifndef MS_RELATIME
36#define MS_RELATIME (1 << 21)
37#endif
38#ifndef MS_STRICTATIME
39#define MS_STRICTATIME (1 << 24)
40#endif
41
42static void die(char *fmt, ...)
43{
44 va_list ap;
45 va_start(ap, fmt);
46 vfprintf(stderr, fmt, ap);
47 va_end(ap);
48 exit(EXIT_FAILURE);
49}
50
51static void write_file(char *filename, char *fmt, ...)
52{
53 char buf[4096];
54 int fd;
55 ssize_t written;
56 int buf_len;
57 va_list ap;
58
59 va_start(ap, fmt);
60 buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
61 va_end(ap);
62 if (buf_len < 0) {
63 die("vsnprintf failed: %s\n",
64 strerror(errno));
65 }
66 if (buf_len >= sizeof(buf)) {
67 die("vsnprintf output truncated\n");
68 }
69
70 fd = open(filename, O_WRONLY);
71 if (fd < 0) {
72 die("open of %s failed: %s\n",
73 filename, strerror(errno));
74 }
75 written = write(fd, buf, buf_len);
76 if (written != buf_len) {
77 if (written >= 0) {
78 die("short write to %s\n", filename);
79 } else {
80 die("write to %s failed: %s\n",
81 filename, strerror(errno));
82 }
83 }
84 if (close(fd) != 0) {
85 die("close of %s failed: %s\n",
86 filename, strerror(errno));
87 }
88}
89
90static void create_and_enter_userns(void)
91{
92 uid_t uid;
93 gid_t gid;
94
95 uid = getuid();
96 gid = getgid();
97
98 if (unshare(CLONE_NEWUSER) !=0) {
99 die("unshare(CLONE_NEWUSER) failed: %s\n",
100 strerror(errno));
101 }
102
103 write_file("/proc/self/uid_map", "0 %d 1", uid);
104 write_file("/proc/self/gid_map", "0 %d 1", gid);
105
106 if (setgroups(0, NULL) != 0) {
107 die("setgroups failed: %s\n",
108 strerror(errno));
109 }
110 if (setgid(0) != 0) {
111 die ("setgid(0) failed %s\n",
112 strerror(errno));
113 }
114 if (setuid(0) != 0) {
115 die("setuid(0) failed %s\n",
116 strerror(errno));
117 }
118}
119
120static
121bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags)
122{
123 pid_t child;
124
125 child = fork();
126 if (child == -1) {
127 die("fork failed: %s\n",
128 strerror(errno));
129 }
130 if (child != 0) { /* parent */
131 pid_t pid;
132 int status;
133 pid = waitpid(child, &status, 0);
134 if (pid == -1) {
135 die("waitpid failed: %s\n",
136 strerror(errno));
137 }
138 if (pid != child) {
139 die("waited for %d got %d\n",
140 child, pid);
141 }
142 if (!WIFEXITED(status)) {
143 die("child did not terminate cleanly\n");
144 }
145 return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false;
146 }
147
148 create_and_enter_userns();
149 if (unshare(CLONE_NEWNS) != 0) {
150 die("unshare(CLONE_NEWNS) failed: %s\n",
151 strerror(errno));
152 }
153
154 if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) {
155 die("mount of /tmp failed: %s\n",
156 strerror(errno));
157 }
158
159 create_and_enter_userns();
160
161 if (unshare(CLONE_NEWNS) != 0) {
162 die("unshare(CLONE_NEWNS) failed: %s\n",
163 strerror(errno));
164 }
165
166 if (mount("/tmp", "/tmp", "none",
167 MS_REMOUNT | MS_BIND | remount_flags, NULL) != 0) {
168 /* system("cat /proc/self/mounts"); */
169 die("remount of /tmp failed: %s\n",
170 strerror(errno));
171 }
172
173 if (mount("/tmp", "/tmp", "none",
174 MS_REMOUNT | MS_BIND | invalid_flags, NULL) == 0) {
175 /* system("cat /proc/self/mounts"); */
176 die("remount of /tmp with invalid flags "
177 "succeeded unexpectedly\n");
178 }
179 exit(EXIT_SUCCESS);
180}
181
182static bool test_unpriv_remount_simple(int mount_flags)
183{
184 return test_unpriv_remount(mount_flags, mount_flags, 0);
185}
186
187static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags)
188{
189 return test_unpriv_remount(mount_flags, mount_flags, invalid_flags);
190}
191
192int main(int argc, char **argv)
193{
194 if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) {
195 die("MS_RDONLY malfunctions\n");
196 }
197 if (!test_unpriv_remount_simple(MS_NODEV)) {
198 die("MS_NODEV malfunctions\n");
199 }
200 if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) {
201 die("MS_NOSUID malfunctions\n");
202 }
203 if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) {
204 die("MS_NOEXEC malfunctions\n");
205 }
206 if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV,
207 MS_NOATIME|MS_NODEV))
208 {
209 die("MS_RELATIME malfunctions\n");
210 }
211 if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV,
212 MS_NOATIME|MS_NODEV))
213 {
214 die("MS_STRICTATIME malfunctions\n");
215 }
216 if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV,
217 MS_STRICTATIME|MS_NODEV))
218 {
219 die("MS_RELATIME malfunctions\n");
220 }
221 if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV,
222 MS_NOATIME|MS_NODEV))
223 {
224 die("MS_RELATIME malfunctions\n");
225 }
226 if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV,
227 MS_NOATIME|MS_NODEV))
228 {
229 die("MS_RELATIME malfunctions\n");
230 }
231 if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV,
232 MS_STRICTATIME|MS_NODEV))
233 {
234 die("MS_RELATIME malfunctions\n");
235 }
236 if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV,
237 MS_NOATIME|MS_NODEV))
238 {
239 die("Default atime malfunctions\n");
240 }
241 return EXIT_SUCCESS;
242}
diff --git a/tools/testing/selftests/net/psock_fanout.c b/tools/testing/selftests/net/psock_fanout.c
index 57b9c2b7c4ff..6f6733331d95 100644
--- a/tools/testing/selftests/net/psock_fanout.c
+++ b/tools/testing/selftests/net/psock_fanout.c
@@ -128,7 +128,7 @@ static int sock_fanout_read_ring(int fd, void *ring)
128 struct tpacket2_hdr *header = ring; 128 struct tpacket2_hdr *header = ring;
129 int count = 0; 129 int count = 0;
130 130
131 while (header->tp_status & TP_STATUS_USER && count < RING_NUM_FRAMES) { 131 while (count < RING_NUM_FRAMES && header->tp_status & TP_STATUS_USER) {
132 count++; 132 count++;
133 header = ring + (count * getpagesize()); 133 header = ring + (count * getpagesize());
134 } 134 }
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 54833a791a44..f6ff90a76bd7 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -13,14 +13,14 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR
13 13
14export CC CFLAGS 14export CC CFLAGS
15 15
16TARGETS = pmu copyloops mm tm 16TARGETS = pmu copyloops mm tm primitives
17 17
18endif 18endif
19 19
20all: 20all: $(TARGETS)
21 @for TARGET in $(TARGETS); do \ 21
22 $(MAKE) -C $$TARGET all; \ 22$(TARGETS):
23 done; 23 $(MAKE) -k -C $@ all
24 24
25run_tests: all 25run_tests: all
26 @for TARGET in $(TARGETS); do \ 26 @for TARGET in $(TARGETS); do \
@@ -36,4 +36,4 @@ clean:
36tags: 36tags:
37 find . -name '*.c' -o -name '*.h' | xargs ctags 37 find . -name '*.c' -o -name '*.h' | xargs ctags
38 38
39.PHONY: all run_tests clean tags 39.PHONY: all run_tests clean tags $(TARGETS)
diff --git a/tools/testing/selftests/powerpc/pmu/Makefile b/tools/testing/selftests/powerpc/pmu/Makefile
index b9ff0db42c79..c9f4263906a5 100644
--- a/tools/testing/selftests/powerpc/pmu/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/Makefile
@@ -1,10 +1,12 @@
1noarg: 1noarg:
2 $(MAKE) -C ../ 2 $(MAKE) -C ../
3 3
4PROGS := count_instructions 4PROGS := count_instructions l3_bank_test per_event_excludes
5EXTRA_SOURCES := ../harness.c event.c 5EXTRA_SOURCES := ../harness.c event.c lib.c
6 6
7all: $(PROGS) sub_all 7SUB_TARGETS = ebb
8
9all: $(PROGS) $(SUB_TARGETS)
8 10
9$(PROGS): $(EXTRA_SOURCES) 11$(PROGS): $(EXTRA_SOURCES)
10 12
@@ -20,13 +22,8 @@ run_tests: all sub_run_tests
20clean: sub_clean 22clean: sub_clean
21 rm -f $(PROGS) loop.o 23 rm -f $(PROGS) loop.o
22 24
23 25$(SUB_TARGETS):
24SUB_TARGETS = ebb 26 $(MAKE) -k -C $@ all
25
26sub_all:
27 @for TARGET in $(SUB_TARGETS); do \
28 $(MAKE) -C $$TARGET all; \
29 done;
30 27
31sub_run_tests: all 28sub_run_tests: all
32 @for TARGET in $(SUB_TARGETS); do \ 29 @for TARGET in $(SUB_TARGETS); do \
@@ -38,4 +35,4 @@ sub_clean:
38 $(MAKE) -C $$TARGET clean; \ 35 $(MAKE) -C $$TARGET clean; \
39 done; 36 done;
40 37
41.PHONY: all run_tests clean sub_all sub_run_tests sub_clean 38.PHONY: all run_tests clean sub_run_tests sub_clean $(SUB_TARGETS)
diff --git a/tools/testing/selftests/powerpc/pmu/count_instructions.c b/tools/testing/selftests/powerpc/pmu/count_instructions.c
index 312b4f0fd27c..4622117b24c0 100644
--- a/tools/testing/selftests/powerpc/pmu/count_instructions.c
+++ b/tools/testing/selftests/powerpc/pmu/count_instructions.c
@@ -12,6 +12,7 @@
12 12
13#include "event.h" 13#include "event.h"
14#include "utils.h" 14#include "utils.h"
15#include "lib.h"
15 16
16extern void thirty_two_instruction_loop(u64 loops); 17extern void thirty_two_instruction_loop(u64 loops);
17 18
@@ -90,7 +91,7 @@ static u64 determine_overhead(struct event *events)
90 return overhead; 91 return overhead;
91} 92}
92 93
93static int count_instructions(void) 94static int test_body(void)
94{ 95{
95 struct event events[2]; 96 struct event events[2];
96 u64 overhead; 97 u64 overhead;
@@ -111,17 +112,23 @@ static int count_instructions(void)
111 overhead = determine_overhead(events); 112 overhead = determine_overhead(events);
112 printf("Overhead of null loop: %llu instructions\n", overhead); 113 printf("Overhead of null loop: %llu instructions\n", overhead);
113 114
114 /* Run for 1M instructions */ 115 /* Run for 1Mi instructions */
115 FAIL_IF(do_count_loop(events, 0x100000, overhead, true)); 116 FAIL_IF(do_count_loop(events, 1000000, overhead, true));
117
118 /* Run for 10Mi instructions */
119 FAIL_IF(do_count_loop(events, 10000000, overhead, true));
120
121 /* Run for 100Mi instructions */
122 FAIL_IF(do_count_loop(events, 100000000, overhead, true));
116 123
117 /* Run for 10M instructions */ 124 /* Run for 1Bi instructions */
118 FAIL_IF(do_count_loop(events, 0xa00000, overhead, true)); 125 FAIL_IF(do_count_loop(events, 1000000000, overhead, true));
119 126
120 /* Run for 100M instructions */ 127 /* Run for 16Bi instructions */
121 FAIL_IF(do_count_loop(events, 0x6400000, overhead, true)); 128 FAIL_IF(do_count_loop(events, 16000000000, overhead, true));
122 129
123 /* Run for 1G instructions */ 130 /* Run for 64Bi instructions */
124 FAIL_IF(do_count_loop(events, 0x40000000, overhead, true)); 131 FAIL_IF(do_count_loop(events, 64000000000, overhead, true));
125 132
126 event_close(&events[0]); 133 event_close(&events[0]);
127 event_close(&events[1]); 134 event_close(&events[1]);
@@ -129,6 +136,11 @@ static int count_instructions(void)
129 return 0; 136 return 0;
130} 137}
131 138
139static int count_instructions(void)
140{
141 return eat_cpu(test_body);
142}
143
132int main(void) 144int main(void)
133{ 145{
134 return test_harness(count_instructions, "count_instructions"); 146 return test_harness(count_instructions, "count_instructions");
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
index edbba2affc2c..3dc4332698cb 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
@@ -13,11 +13,12 @@ PROGS := reg_access_test event_attributes_test cycles_test \
13 close_clears_pmcc_test instruction_count_test \ 13 close_clears_pmcc_test instruction_count_test \
14 fork_cleanup_test ebb_on_child_test \ 14 fork_cleanup_test ebb_on_child_test \
15 ebb_on_willing_child_test back_to_back_ebbs_test \ 15 ebb_on_willing_child_test back_to_back_ebbs_test \
16 lost_exception_test no_handler_test 16 lost_exception_test no_handler_test \
17 cycles_with_mmcr2_test
17 18
18all: $(PROGS) 19all: $(PROGS)
19 20
20$(PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c 21$(PROGS): ../../harness.c ../event.c ../lib.c ebb.c ebb_handler.S trace.c busy_loop.S
21 22
22instruction_count_test: ../loop.S 23instruction_count_test: ../loop.S
23 24
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/busy_loop.S b/tools/testing/selftests/powerpc/pmu/ebb/busy_loop.S
new file mode 100644
index 000000000000..c7e4093f1cd3
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/ebb/busy_loop.S
@@ -0,0 +1,271 @@
1/*
2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <ppc-asm.h>
7
8 .text
9
10FUNC_START(core_busy_loop)
11 stdu %r1, -168(%r1)
12 std r14, 160(%r1)
13 std r15, 152(%r1)
14 std r16, 144(%r1)
15 std r17, 136(%r1)
16 std r18, 128(%r1)
17 std r19, 120(%r1)
18 std r20, 112(%r1)
19 std r21, 104(%r1)
20 std r22, 96(%r1)
21 std r23, 88(%r1)
22 std r24, 80(%r1)
23 std r25, 72(%r1)
24 std r26, 64(%r1)
25 std r27, 56(%r1)
26 std r28, 48(%r1)
27 std r29, 40(%r1)
28 std r30, 32(%r1)
29 std r31, 24(%r1)
30
31 li r3, 0x3030
32 std r3, -96(%r1)
33 li r4, 0x4040
34 std r4, -104(%r1)
35 li r5, 0x5050
36 std r5, -112(%r1)
37 li r6, 0x6060
38 std r6, -120(%r1)
39 li r7, 0x7070
40 std r7, -128(%r1)
41 li r8, 0x0808
42 std r8, -136(%r1)
43 li r9, 0x0909
44 std r9, -144(%r1)
45 li r10, 0x1010
46 std r10, -152(%r1)
47 li r11, 0x1111
48 std r11, -160(%r1)
49 li r14, 0x1414
50 std r14, -168(%r1)
51 li r15, 0x1515
52 std r15, -176(%r1)
53 li r16, 0x1616
54 std r16, -184(%r1)
55 li r17, 0x1717
56 std r17, -192(%r1)
57 li r18, 0x1818
58 std r18, -200(%r1)
59 li r19, 0x1919
60 std r19, -208(%r1)
61 li r20, 0x2020
62 std r20, -216(%r1)
63 li r21, 0x2121
64 std r21, -224(%r1)
65 li r22, 0x2222
66 std r22, -232(%r1)
67 li r23, 0x2323
68 std r23, -240(%r1)
69 li r24, 0x2424
70 std r24, -248(%r1)
71 li r25, 0x2525
72 std r25, -256(%r1)
73 li r26, 0x2626
74 std r26, -264(%r1)
75 li r27, 0x2727
76 std r27, -272(%r1)
77 li r28, 0x2828
78 std r28, -280(%r1)
79 li r29, 0x2929
80 std r29, -288(%r1)
81 li r30, 0x3030
82 li r31, 0x3131
83
84 li r3, 0
850: addi r3, r3, 1
86 cmpwi r3, 100
87 blt 0b
88
89 /* Return 1 (fail) unless we get through all the checks */
90 li r3, 1
91
92 /* Check none of our registers have been corrupted */
93 cmpwi r4, 0x4040
94 bne 1f
95 cmpwi r5, 0x5050
96 bne 1f
97 cmpwi r6, 0x6060
98 bne 1f
99 cmpwi r7, 0x7070
100 bne 1f
101 cmpwi r8, 0x0808
102 bne 1f
103 cmpwi r9, 0x0909
104 bne 1f
105 cmpwi r10, 0x1010
106 bne 1f
107 cmpwi r11, 0x1111
108 bne 1f
109 cmpwi r14, 0x1414
110 bne 1f
111 cmpwi r15, 0x1515
112 bne 1f
113 cmpwi r16, 0x1616
114 bne 1f
115 cmpwi r17, 0x1717
116 bne 1f
117 cmpwi r18, 0x1818
118 bne 1f
119 cmpwi r19, 0x1919
120 bne 1f
121 cmpwi r20, 0x2020
122 bne 1f
123 cmpwi r21, 0x2121
124 bne 1f
125 cmpwi r22, 0x2222
126 bne 1f
127 cmpwi r23, 0x2323
128 bne 1f
129 cmpwi r24, 0x2424
130 bne 1f
131 cmpwi r25, 0x2525
132 bne 1f
133 cmpwi r26, 0x2626
134 bne 1f
135 cmpwi r27, 0x2727
136 bne 1f
137 cmpwi r28, 0x2828
138 bne 1f
139 cmpwi r29, 0x2929
140 bne 1f
141 cmpwi r30, 0x3030
142 bne 1f
143 cmpwi r31, 0x3131
144 bne 1f
145
146 /* Load junk into all our registers before we reload them from the stack. */
147 li r3, 0xde
148 li r4, 0xad
149 li r5, 0xbe
150 li r6, 0xef
151 li r7, 0xde
152 li r8, 0xad
153 li r9, 0xbe
154 li r10, 0xef
155 li r11, 0xde
156 li r14, 0xad
157 li r15, 0xbe
158 li r16, 0xef
159 li r17, 0xde
160 li r18, 0xad
161 li r19, 0xbe
162 li r20, 0xef
163 li r21, 0xde
164 li r22, 0xad
165 li r23, 0xbe
166 li r24, 0xef
167 li r25, 0xde
168 li r26, 0xad
169 li r27, 0xbe
170 li r28, 0xef
171 li r29, 0xdd
172
173 ld r3, -96(%r1)
174 cmpwi r3, 0x3030
175 bne 1f
176 ld r4, -104(%r1)
177 cmpwi r4, 0x4040
178 bne 1f
179 ld r5, -112(%r1)
180 cmpwi r5, 0x5050
181 bne 1f
182 ld r6, -120(%r1)
183 cmpwi r6, 0x6060
184 bne 1f
185 ld r7, -128(%r1)
186 cmpwi r7, 0x7070
187 bne 1f
188 ld r8, -136(%r1)
189 cmpwi r8, 0x0808
190 bne 1f
191 ld r9, -144(%r1)
192 cmpwi r9, 0x0909
193 bne 1f
194 ld r10, -152(%r1)
195 cmpwi r10, 0x1010
196 bne 1f
197 ld r11, -160(%r1)
198 cmpwi r11, 0x1111
199 bne 1f
200 ld r14, -168(%r1)
201 cmpwi r14, 0x1414
202 bne 1f
203 ld r15, -176(%r1)
204 cmpwi r15, 0x1515
205 bne 1f
206 ld r16, -184(%r1)
207 cmpwi r16, 0x1616
208 bne 1f
209 ld r17, -192(%r1)
210 cmpwi r17, 0x1717
211 bne 1f
212 ld r18, -200(%r1)
213 cmpwi r18, 0x1818
214 bne 1f
215 ld r19, -208(%r1)
216 cmpwi r19, 0x1919
217 bne 1f
218 ld r20, -216(%r1)
219 cmpwi r20, 0x2020
220 bne 1f
221 ld r21, -224(%r1)
222 cmpwi r21, 0x2121
223 bne 1f
224 ld r22, -232(%r1)
225 cmpwi r22, 0x2222
226 bne 1f
227 ld r23, -240(%r1)
228 cmpwi r23, 0x2323
229 bne 1f
230 ld r24, -248(%r1)
231 cmpwi r24, 0x2424
232 bne 1f
233 ld r25, -256(%r1)
234 cmpwi r25, 0x2525
235 bne 1f
236 ld r26, -264(%r1)
237 cmpwi r26, 0x2626
238 bne 1f
239 ld r27, -272(%r1)
240 cmpwi r27, 0x2727
241 bne 1f
242 ld r28, -280(%r1)
243 cmpwi r28, 0x2828
244 bne 1f
245 ld r29, -288(%r1)
246 cmpwi r29, 0x2929
247 bne 1f
248
249 /* Load 0 (success) to return */
250 li r3, 0
251
2521: ld r14, 160(%r1)
253 ld r15, 152(%r1)
254 ld r16, 144(%r1)
255 ld r17, 136(%r1)
256 ld r18, 128(%r1)
257 ld r19, 120(%r1)
258 ld r20, 112(%r1)
259 ld r21, 104(%r1)
260 ld r22, 96(%r1)
261 ld r23, 88(%r1)
262 ld r24, 80(%r1)
263 ld r25, 72(%r1)
264 ld r26, 64(%r1)
265 ld r27, 56(%r1)
266 ld r28, 48(%r1)
267 ld r29, 40(%r1)
268 ld r30, 32(%r1)
269 ld r31, 24(%r1)
270 addi %r1, %r1, 168
271 blr
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c b/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c
new file mode 100644
index 000000000000..d43029b0800c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/ebb/cycles_with_mmcr2_test.c
@@ -0,0 +1,91 @@
1/*
2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <stdbool.h>
9
10#include "ebb.h"
11
12
13/*
14 * Test of counting cycles while manipulating the user accessible bits in MMCR2.
15 */
16
17/* We use two values because the first freezes PMC1 and so we would get no EBBs */
18#define MMCR2_EXPECTED_1 0x4020100804020000UL /* (FC1P|FC2P|FC3P|FC4P|FC5P|FC6P) */
19#define MMCR2_EXPECTED_2 0x0020100804020000UL /* ( FC2P|FC3P|FC4P|FC5P|FC6P) */
20
21
22int cycles_with_mmcr2(void)
23{
24 struct event event;
25 uint64_t val, expected[2], actual;
26 int i;
27 bool bad_mmcr2;
28
29 event_init_named(&event, 0x1001e, "cycles");
30 event_leader_ebb_init(&event);
31
32 event.attr.exclude_kernel = 1;
33 event.attr.exclude_hv = 1;
34 event.attr.exclude_idle = 1;
35
36 FAIL_IF(event_open(&event));
37
38 ebb_enable_pmc_counting(1);
39 setup_ebb_handler(standard_ebb_callee);
40 ebb_global_enable();
41
42 FAIL_IF(ebb_event_enable(&event));
43
44 mtspr(SPRN_PMC1, pmc_sample_period(sample_period));
45
46 /* XXX Set of MMCR2 must be after enable */
47 expected[0] = MMCR2_EXPECTED_1;
48 expected[1] = MMCR2_EXPECTED_2;
49 i = 0;
50 bad_mmcr2 = false;
51
52 /* Make sure we loop until we take at least one EBB */
53 while ((ebb_state.stats.ebb_count < 20 && !bad_mmcr2) ||
54 ebb_state.stats.ebb_count < 1)
55 {
56 mtspr(SPRN_MMCR2, expected[i % 2]);
57
58 FAIL_IF(core_busy_loop());
59
60 val = mfspr(SPRN_MMCR2);
61 if (val != expected[i % 2]) {
62 bad_mmcr2 = true;
63 actual = val;
64 }
65
66 i++;
67 }
68
69 ebb_global_disable();
70 ebb_freeze_pmcs();
71
72 count_pmc(1, sample_period);
73
74 dump_ebb_state();
75
76 event_close(&event);
77
78 FAIL_IF(ebb_state.stats.ebb_count == 0);
79
80 if (bad_mmcr2)
81 printf("Bad MMCR2 value seen is 0x%lx\n", actual);
82
83 FAIL_IF(bad_mmcr2);
84
85 return 0;
86}
87
88int main(void)
89{
90 return test_harness(cycles_with_mmcr2, "cycles_with_mmcr2");
91}
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
index 1b46be94b64c..d7a72ce696b5 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
@@ -224,6 +224,7 @@ void dump_ebb_hw_state(void)
224 224
225 printf("HW state:\n" \ 225 printf("HW state:\n" \
226 "MMCR0 0x%016x %s\n" \ 226 "MMCR0 0x%016x %s\n" \
227 "MMCR2 0x%016lx\n" \
227 "EBBHR 0x%016lx\n" \ 228 "EBBHR 0x%016lx\n" \
228 "BESCR 0x%016llx %s\n" \ 229 "BESCR 0x%016llx %s\n" \
229 "PMC1 0x%016lx\n" \ 230 "PMC1 0x%016lx\n" \
@@ -233,10 +234,11 @@ void dump_ebb_hw_state(void)
233 "PMC5 0x%016lx\n" \ 234 "PMC5 0x%016lx\n" \
234 "PMC6 0x%016lx\n" \ 235 "PMC6 0x%016lx\n" \
235 "SIAR 0x%016lx\n", 236 "SIAR 0x%016lx\n",
236 mmcr0, decode_mmcr0(mmcr0), mfspr(SPRN_EBBHR), bescr, 237 mmcr0, decode_mmcr0(mmcr0), mfspr(SPRN_MMCR2),
237 decode_bescr(bescr), mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), 238 mfspr(SPRN_EBBHR), bescr, decode_bescr(bescr),
238 mfspr(SPRN_PMC3), mfspr(SPRN_PMC4), mfspr(SPRN_PMC5), 239 mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), mfspr(SPRN_PMC3),
239 mfspr(SPRN_PMC6), mfspr(SPRN_SIAR)); 240 mfspr(SPRN_PMC4), mfspr(SPRN_PMC5), mfspr(SPRN_PMC6),
241 mfspr(SPRN_SIAR));
240} 242}
241 243
242void dump_ebb_state(void) 244void dump_ebb_state(void)
@@ -335,257 +337,6 @@ void event_leader_ebb_init(struct event *e)
335 e->attr.pinned = 1; 337 e->attr.pinned = 1;
336} 338}
337 339
338int core_busy_loop(void)
339{
340 int rc;
341
342 asm volatile (
343 "li 3, 0x3030\n"
344 "std 3, -96(1)\n"
345 "li 4, 0x4040\n"
346 "std 4, -104(1)\n"
347 "li 5, 0x5050\n"
348 "std 5, -112(1)\n"
349 "li 6, 0x6060\n"
350 "std 6, -120(1)\n"
351 "li 7, 0x7070\n"
352 "std 7, -128(1)\n"
353 "li 8, 0x0808\n"
354 "std 8, -136(1)\n"
355 "li 9, 0x0909\n"
356 "std 9, -144(1)\n"
357 "li 10, 0x1010\n"
358 "std 10, -152(1)\n"
359 "li 11, 0x1111\n"
360 "std 11, -160(1)\n"
361 "li 14, 0x1414\n"
362 "std 14, -168(1)\n"
363 "li 15, 0x1515\n"
364 "std 15, -176(1)\n"
365 "li 16, 0x1616\n"
366 "std 16, -184(1)\n"
367 "li 17, 0x1717\n"
368 "std 17, -192(1)\n"
369 "li 18, 0x1818\n"
370 "std 18, -200(1)\n"
371 "li 19, 0x1919\n"
372 "std 19, -208(1)\n"
373 "li 20, 0x2020\n"
374 "std 20, -216(1)\n"
375 "li 21, 0x2121\n"
376 "std 21, -224(1)\n"
377 "li 22, 0x2222\n"
378 "std 22, -232(1)\n"
379 "li 23, 0x2323\n"
380 "std 23, -240(1)\n"
381 "li 24, 0x2424\n"
382 "std 24, -248(1)\n"
383 "li 25, 0x2525\n"
384 "std 25, -256(1)\n"
385 "li 26, 0x2626\n"
386 "std 26, -264(1)\n"
387 "li 27, 0x2727\n"
388 "std 27, -272(1)\n"
389 "li 28, 0x2828\n"
390 "std 28, -280(1)\n"
391 "li 29, 0x2929\n"
392 "std 29, -288(1)\n"
393 "li 30, 0x3030\n"
394 "li 31, 0x3131\n"
395
396 "li 3, 0\n"
397 "0: "
398 "addi 3, 3, 1\n"
399 "cmpwi 3, 100\n"
400 "blt 0b\n"
401
402 /* Return 1 (fail) unless we get through all the checks */
403 "li 0, 1\n"
404
405 /* Check none of our registers have been corrupted */
406 "cmpwi 4, 0x4040\n"
407 "bne 1f\n"
408 "cmpwi 5, 0x5050\n"
409 "bne 1f\n"
410 "cmpwi 6, 0x6060\n"
411 "bne 1f\n"
412 "cmpwi 7, 0x7070\n"
413 "bne 1f\n"
414 "cmpwi 8, 0x0808\n"
415 "bne 1f\n"
416 "cmpwi 9, 0x0909\n"
417 "bne 1f\n"
418 "cmpwi 10, 0x1010\n"
419 "bne 1f\n"
420 "cmpwi 11, 0x1111\n"
421 "bne 1f\n"
422 "cmpwi 14, 0x1414\n"
423 "bne 1f\n"
424 "cmpwi 15, 0x1515\n"
425 "bne 1f\n"
426 "cmpwi 16, 0x1616\n"
427 "bne 1f\n"
428 "cmpwi 17, 0x1717\n"
429 "bne 1f\n"
430 "cmpwi 18, 0x1818\n"
431 "bne 1f\n"
432 "cmpwi 19, 0x1919\n"
433 "bne 1f\n"
434 "cmpwi 20, 0x2020\n"
435 "bne 1f\n"
436 "cmpwi 21, 0x2121\n"
437 "bne 1f\n"
438 "cmpwi 22, 0x2222\n"
439 "bne 1f\n"
440 "cmpwi 23, 0x2323\n"
441 "bne 1f\n"
442 "cmpwi 24, 0x2424\n"
443 "bne 1f\n"
444 "cmpwi 25, 0x2525\n"
445 "bne 1f\n"
446 "cmpwi 26, 0x2626\n"
447 "bne 1f\n"
448 "cmpwi 27, 0x2727\n"
449 "bne 1f\n"
450 "cmpwi 28, 0x2828\n"
451 "bne 1f\n"
452 "cmpwi 29, 0x2929\n"
453 "bne 1f\n"
454 "cmpwi 30, 0x3030\n"
455 "bne 1f\n"
456 "cmpwi 31, 0x3131\n"
457 "bne 1f\n"
458
459 /* Load junk into all our registers before we reload them from the stack. */
460 "li 3, 0xde\n"
461 "li 4, 0xad\n"
462 "li 5, 0xbe\n"
463 "li 6, 0xef\n"
464 "li 7, 0xde\n"
465 "li 8, 0xad\n"
466 "li 9, 0xbe\n"
467 "li 10, 0xef\n"
468 "li 11, 0xde\n"
469 "li 14, 0xad\n"
470 "li 15, 0xbe\n"
471 "li 16, 0xef\n"
472 "li 17, 0xde\n"
473 "li 18, 0xad\n"
474 "li 19, 0xbe\n"
475 "li 20, 0xef\n"
476 "li 21, 0xde\n"
477 "li 22, 0xad\n"
478 "li 23, 0xbe\n"
479 "li 24, 0xef\n"
480 "li 25, 0xde\n"
481 "li 26, 0xad\n"
482 "li 27, 0xbe\n"
483 "li 28, 0xef\n"
484 "li 29, 0xdd\n"
485
486 "ld 3, -96(1)\n"
487 "cmpwi 3, 0x3030\n"
488 "bne 1f\n"
489 "ld 4, -104(1)\n"
490 "cmpwi 4, 0x4040\n"
491 "bne 1f\n"
492 "ld 5, -112(1)\n"
493 "cmpwi 5, 0x5050\n"
494 "bne 1f\n"
495 "ld 6, -120(1)\n"
496 "cmpwi 6, 0x6060\n"
497 "bne 1f\n"
498 "ld 7, -128(1)\n"
499 "cmpwi 7, 0x7070\n"
500 "bne 1f\n"
501 "ld 8, -136(1)\n"
502 "cmpwi 8, 0x0808\n"
503 "bne 1f\n"
504 "ld 9, -144(1)\n"
505 "cmpwi 9, 0x0909\n"
506 "bne 1f\n"
507 "ld 10, -152(1)\n"
508 "cmpwi 10, 0x1010\n"
509 "bne 1f\n"
510 "ld 11, -160(1)\n"
511 "cmpwi 11, 0x1111\n"
512 "bne 1f\n"
513 "ld 14, -168(1)\n"
514 "cmpwi 14, 0x1414\n"
515 "bne 1f\n"
516 "ld 15, -176(1)\n"
517 "cmpwi 15, 0x1515\n"
518 "bne 1f\n"
519 "ld 16, -184(1)\n"
520 "cmpwi 16, 0x1616\n"
521 "bne 1f\n"
522 "ld 17, -192(1)\n"
523 "cmpwi 17, 0x1717\n"
524 "bne 1f\n"
525 "ld 18, -200(1)\n"
526 "cmpwi 18, 0x1818\n"
527 "bne 1f\n"
528 "ld 19, -208(1)\n"
529 "cmpwi 19, 0x1919\n"
530 "bne 1f\n"
531 "ld 20, -216(1)\n"
532 "cmpwi 20, 0x2020\n"
533 "bne 1f\n"
534 "ld 21, -224(1)\n"
535 "cmpwi 21, 0x2121\n"
536 "bne 1f\n"
537 "ld 22, -232(1)\n"
538 "cmpwi 22, 0x2222\n"
539 "bne 1f\n"
540 "ld 23, -240(1)\n"
541 "cmpwi 23, 0x2323\n"
542 "bne 1f\n"
543 "ld 24, -248(1)\n"
544 "cmpwi 24, 0x2424\n"
545 "bne 1f\n"
546 "ld 25, -256(1)\n"
547 "cmpwi 25, 0x2525\n"
548 "bne 1f\n"
549 "ld 26, -264(1)\n"
550 "cmpwi 26, 0x2626\n"
551 "bne 1f\n"
552 "ld 27, -272(1)\n"
553 "cmpwi 27, 0x2727\n"
554 "bne 1f\n"
555 "ld 28, -280(1)\n"
556 "cmpwi 28, 0x2828\n"
557 "bne 1f\n"
558 "ld 29, -288(1)\n"
559 "cmpwi 29, 0x2929\n"
560 "bne 1f\n"
561
562 /* Load 0 (success) to return */
563 "li 0, 0\n"
564
565 "1: mr %0, 0\n"
566
567 : "=r" (rc)
568 : /* no inputs */
569 : "3", "4", "5", "6", "7", "8", "9", "10", "11", "14",
570 "15", "16", "17", "18", "19", "20", "21", "22", "23",
571 "24", "25", "26", "27", "28", "29", "30", "31",
572 "memory"
573 );
574
575 return rc;
576}
577
578int core_busy_loop_with_freeze(void)
579{
580 int rc;
581
582 mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC);
583 rc = core_busy_loop();
584 mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) | MMCR0_FC);
585
586 return rc;
587}
588
589int ebb_child(union pipe read_pipe, union pipe write_pipe) 340int ebb_child(union pipe read_pipe, union pipe write_pipe)
590{ 341{
591 struct event event; 342 struct event event;
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.h b/tools/testing/selftests/powerpc/pmu/ebb/ebb.h
index e62bde05bf78..e44eee5d97ca 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb.h
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.h
@@ -70,7 +70,6 @@ int ebb_check_mmcr0(void);
70extern u64 sample_period; 70extern u64 sample_period;
71 71
72int core_busy_loop(void); 72int core_busy_loop(void);
73int core_busy_loop_with_freeze(void);
74int ebb_child(union pipe read_pipe, union pipe write_pipe); 73int ebb_child(union pipe read_pipe, union pipe write_pipe);
75int catch_sigill(void (*func)(void)); 74int catch_sigill(void (*func)(void));
76void write_pmc1(void); 75void write_pmc1(void);
diff --git a/tools/testing/selftests/powerpc/pmu/l3_bank_test.c b/tools/testing/selftests/powerpc/pmu/l3_bank_test.c
new file mode 100644
index 000000000000..77472f31441e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/l3_bank_test.c
@@ -0,0 +1,48 @@
1/*
2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8
9#include "event.h"
10#include "utils.h"
11
12#define MALLOC_SIZE (0x10000 * 10) /* Ought to be enough .. */
13
14/*
15 * Tests that the L3 bank handling is correct. We fixed it in commit e9aaac1.
16 */
17static int l3_bank_test(void)
18{
19 struct event event;
20 char *p;
21 int i;
22
23 p = malloc(MALLOC_SIZE);
24 FAIL_IF(!p);
25
26 event_init(&event, 0x84918F);
27
28 FAIL_IF(event_open(&event));
29
30 for (i = 0; i < MALLOC_SIZE; i += 0x10000)
31 p[i] = i;
32
33 event_read(&event);
34 event_report(&event);
35
36 FAIL_IF(event.result.running == 0);
37 FAIL_IF(event.result.enabled == 0);
38
39 event_close(&event);
40 free(p);
41
42 return 0;
43}
44
45int main(void)
46{
47 return test_harness(l3_bank_test, "l3_bank_test");
48}
diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c
index 0f6a4731d546..9768dea37bf3 100644
--- a/tools/testing/selftests/powerpc/pmu/lib.c
+++ b/tools/testing/selftests/powerpc/pmu/lib.c
@@ -5,10 +5,15 @@
5 5
6#define _GNU_SOURCE /* For CPU_ZERO etc. */ 6#define _GNU_SOURCE /* For CPU_ZERO etc. */
7 7
8#include <elf.h>
8#include <errno.h> 9#include <errno.h>
10#include <fcntl.h>
11#include <link.h>
9#include <sched.h> 12#include <sched.h>
10#include <setjmp.h> 13#include <setjmp.h>
11#include <stdlib.h> 14#include <stdlib.h>
15#include <sys/stat.h>
16#include <sys/types.h>
12#include <sys/wait.h> 17#include <sys/wait.h>
13 18
14#include "utils.h" 19#include "utils.h"
@@ -177,8 +182,8 @@ struct addr_range libc, vdso;
177 182
178int parse_proc_maps(void) 183int parse_proc_maps(void)
179{ 184{
185 unsigned long start, end;
180 char execute, name[128]; 186 char execute, name[128];
181 uint64_t start, end;
182 FILE *f; 187 FILE *f;
183 int rc; 188 int rc;
184 189
@@ -250,3 +255,46 @@ out_close:
250out: 255out:
251 return rc; 256 return rc;
252} 257}
258
259static char auxv[4096];
260
261void *get_auxv_entry(int type)
262{
263 ElfW(auxv_t) *p;
264 void *result;
265 ssize_t num;
266 int fd;
267
268 fd = open("/proc/self/auxv", O_RDONLY);
269 if (fd == -1) {
270 perror("open");
271 return NULL;
272 }
273
274 result = NULL;
275
276 num = read(fd, auxv, sizeof(auxv));
277 if (num < 0) {
278 perror("read");
279 goto out;
280 }
281
282 if (num > sizeof(auxv)) {
283 printf("Overflowed auxv buffer\n");
284 goto out;
285 }
286
287 p = (ElfW(auxv_t) *)auxv;
288
289 while (p->a_type != AT_NULL) {
290 if (p->a_type == type) {
291 result = (void *)p->a_un.a_val;
292 break;
293 }
294
295 p++;
296 }
297out:
298 close(fd);
299 return result;
300}
diff --git a/tools/testing/selftests/powerpc/pmu/lib.h b/tools/testing/selftests/powerpc/pmu/lib.h
index ca5d72ae3be6..0f0339c8a6f6 100644
--- a/tools/testing/selftests/powerpc/pmu/lib.h
+++ b/tools/testing/selftests/powerpc/pmu/lib.h
@@ -29,6 +29,7 @@ extern int notify_parent(union pipe write_pipe);
29extern int notify_parent_of_error(union pipe write_pipe); 29extern int notify_parent_of_error(union pipe write_pipe);
30extern pid_t eat_cpu(int (test_function)(void)); 30extern pid_t eat_cpu(int (test_function)(void));
31extern bool require_paranoia_below(int level); 31extern bool require_paranoia_below(int level);
32extern void *get_auxv_entry(int type);
32 33
33struct addr_range { 34struct addr_range {
34 uint64_t first, last; 35 uint64_t first, last;
diff --git a/tools/testing/selftests/powerpc/pmu/per_event_excludes.c b/tools/testing/selftests/powerpc/pmu/per_event_excludes.c
new file mode 100644
index 000000000000..fddbbc9cae2f
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/per_event_excludes.c
@@ -0,0 +1,114 @@
1/*
2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#define _GNU_SOURCE
7
8#include <elf.h>
9#include <limits.h>
10#include <stdio.h>
11#include <stdbool.h>
12#include <string.h>
13#include <sys/prctl.h>
14
15#include "event.h"
16#include "lib.h"
17#include "utils.h"
18
19/*
20 * Test that per-event excludes work.
21 */
22
23static int per_event_excludes(void)
24{
25 struct event *e, events[4];
26 char *platform;
27 int i;
28
29 platform = (char *)get_auxv_entry(AT_BASE_PLATFORM);
30 FAIL_IF(!platform);
31 SKIP_IF(strcmp(platform, "power8") != 0);
32
33 /*
34 * We need to create the events disabled, otherwise the running/enabled
35 * counts don't match up.
36 */
37 e = &events[0];
38 event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS,
39 PERF_TYPE_HARDWARE, "instructions");
40 e->attr.disabled = 1;
41
42 e = &events[1];
43 event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS,
44 PERF_TYPE_HARDWARE, "instructions(k)");
45 e->attr.disabled = 1;
46 e->attr.exclude_user = 1;
47 e->attr.exclude_hv = 1;
48
49 e = &events[2];
50 event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS,
51 PERF_TYPE_HARDWARE, "instructions(h)");
52 e->attr.disabled = 1;
53 e->attr.exclude_user = 1;
54 e->attr.exclude_kernel = 1;
55
56 e = &events[3];
57 event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS,
58 PERF_TYPE_HARDWARE, "instructions(u)");
59 e->attr.disabled = 1;
60 e->attr.exclude_hv = 1;
61 e->attr.exclude_kernel = 1;
62
63 FAIL_IF(event_open(&events[0]));
64
65 /*
66 * The open here will fail if we don't have per event exclude support,
67 * because the second event has an incompatible set of exclude settings
68 * and we're asking for the events to be in a group.
69 */
70 for (i = 1; i < 4; i++)
71 FAIL_IF(event_open_with_group(&events[i], events[0].fd));
72
73 /*
74 * Even though the above will fail without per-event excludes we keep
75 * testing in order to be thorough.
76 */
77 prctl(PR_TASK_PERF_EVENTS_ENABLE);
78
79 /* Spin for a while */
80 for (i = 0; i < INT_MAX; i++)
81 asm volatile("" : : : "memory");
82
83 prctl(PR_TASK_PERF_EVENTS_DISABLE);
84
85 for (i = 0; i < 4; i++) {
86 FAIL_IF(event_read(&events[i]));
87 event_report(&events[i]);
88 }
89
90 /*
91 * We should see that all events have enabled == running. That
92 * shows that they were all on the PMU at once.
93 */
94 for (i = 0; i < 4; i++)
95 FAIL_IF(events[i].result.running != events[i].result.enabled);
96
97 /*
98 * We can also check that the result for instructions is >= all the
99 * other counts. That's because it is counting all instructions while
100 * the others are counting a subset.
101 */
102 for (i = 1; i < 4; i++)
103 FAIL_IF(events[0].result.value < events[i].result.value);
104
105 for (i = 0; i < 4; i++)
106 event_close(&events[i]);
107
108 return 0;
109}
110
111int main(void)
112{
113 return test_harness(per_event_excludes, "per_event_excludes");
114}
diff --git a/tools/testing/selftests/powerpc/primitives/Makefile b/tools/testing/selftests/powerpc/primitives/Makefile
new file mode 100644
index 000000000000..ea737ca01732
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/Makefile
@@ -0,0 +1,17 @@
1CFLAGS += -I$(CURDIR)
2
3PROGS := load_unaligned_zeropad
4
5all: $(PROGS)
6
7$(PROGS): ../harness.c
8
9run_tests: all
10 @-for PROG in $(PROGS); do \
11 ./$$PROG; \
12 done;
13
14clean:
15 rm -f $(PROGS) *.o
16
17.PHONY: all run_tests clean
diff --git a/tools/testing/selftests/powerpc/primitives/asm/asm-compat.h b/tools/testing/selftests/powerpc/primitives/asm/asm-compat.h
new file mode 120000
index 000000000000..b14255e15a25
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/asm/asm-compat.h
@@ -0,0 +1 @@
../.././../../../../arch/powerpc/include/asm/asm-compat.h \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/primitives/asm/ppc-opcode.h b/tools/testing/selftests/powerpc/primitives/asm/ppc-opcode.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/asm/ppc-opcode.h
diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
new file mode 100644
index 000000000000..d1b647509596
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
@@ -0,0 +1,147 @@
1/*
2 * Userspace test harness for load_unaligned_zeropad. Creates two
3 * pages and uses mprotect to prevent access to the second page and
4 * a SEGV handler that walks the exception tables and runs the fixup
5 * routine.
6 *
7 * The results are compared against a normal load that is that is
8 * performed while access to the second page is enabled via mprotect.
9 *
10 * Copyright (C) 2014 Anton Blanchard <anton@au.ibm.com>, IBM
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <stdlib.h>
19#include <string.h>
20#include <stdio.h>
21#include <stdbool.h>
22#include <signal.h>
23#include <unistd.h>
24#include <sys/mman.h>
25
26#define FIXUP_SECTION ".ex_fixup"
27
28#include "word-at-a-time.h"
29
30#include "utils.h"
31
32
33static int page_size;
34static char *mem_region;
35
36static int protect_region(void)
37{
38 if (mprotect(mem_region + page_size, page_size, PROT_NONE)) {
39 perror("mprotect");
40 return 1;
41 }
42
43 return 0;
44}
45
46static int unprotect_region(void)
47{
48 if (mprotect(mem_region + page_size, page_size, PROT_READ|PROT_WRITE)) {
49 perror("mprotect");
50 return 1;
51 }
52
53 return 0;
54}
55
56extern char __start___ex_table[];
57extern char __stop___ex_table[];
58
59#if defined(__powerpc64__)
60#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP]
61#elif defined(__powerpc__)
62#define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP]
63#else
64#error implement UCONTEXT_NIA
65#endif
66
67static int segv_error;
68
69static void segv_handler(int signr, siginfo_t *info, void *ptr)
70{
71 ucontext_t *uc = (ucontext_t *)ptr;
72 unsigned long addr = (unsigned long)info->si_addr;
73 unsigned long *ip = &UCONTEXT_NIA(uc);
74 unsigned long *ex_p = (unsigned long *)__start___ex_table;
75
76 while (ex_p < (unsigned long *)__stop___ex_table) {
77 unsigned long insn, fixup;
78
79 insn = *ex_p++;
80 fixup = *ex_p++;
81
82 if (insn == *ip) {
83 *ip = fixup;
84 return;
85 }
86 }
87
88 printf("No exception table match for NIA %lx ADDR %lx\n", *ip, addr);
89 segv_error++;
90}
91
92static void setup_segv_handler(void)
93{
94 struct sigaction action;
95
96 memset(&action, 0, sizeof(action));
97 action.sa_sigaction = segv_handler;
98 action.sa_flags = SA_SIGINFO;
99 sigaction(SIGSEGV, &action, NULL);
100}
101
102static int do_one_test(char *p, int page_offset)
103{
104 unsigned long should;
105 unsigned long got;
106
107 FAIL_IF(unprotect_region());
108 should = *(unsigned long *)p;
109 FAIL_IF(protect_region());
110
111 got = load_unaligned_zeropad(p);
112
113 if (should != got)
114 printf("offset %u load_unaligned_zeropad returned 0x%lx, should be 0x%lx\n", page_offset, got, should);
115
116 return 0;
117}
118
119static int test_body(void)
120{
121 unsigned long i;
122
123 page_size = getpagesize();
124 mem_region = mmap(NULL, page_size * 2, PROT_READ|PROT_WRITE,
125 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
126
127 FAIL_IF(mem_region == MAP_FAILED);
128
129 for (i = 0; i < page_size; i++)
130 mem_region[i] = i;
131
132 memset(mem_region+page_size, 0, page_size);
133
134 setup_segv_handler();
135
136 for (i = 0; i < page_size; i++)
137 FAIL_IF(do_one_test(mem_region+i, i));
138
139 FAIL_IF(segv_error);
140
141 return 0;
142}
143
144int main(void)
145{
146 return test_harness(test_body, "load_unaligned_zeropad");
147}
diff --git a/tools/testing/selftests/powerpc/primitives/word-at-a-time.h b/tools/testing/selftests/powerpc/primitives/word-at-a-time.h
new file mode 120000
index 000000000000..eb74401b591f
--- /dev/null
+++ b/tools/testing/selftests/powerpc/primitives/word-at-a-time.h
@@ -0,0 +1 @@
../../../../../arch/powerpc/include/asm/word-at-a-time.h \ No newline at end of file
diff --git a/tools/testing/selftests/ptrace/peeksiginfo.c b/tools/testing/selftests/ptrace/peeksiginfo.c
index d46558b1f58d..c34cd8ac8aaa 100644
--- a/tools/testing/selftests/ptrace/peeksiginfo.c
+++ b/tools/testing/selftests/ptrace/peeksiginfo.c
@@ -31,6 +31,10 @@ static int sys_ptrace(int request, pid_t pid, void *addr, void *data)
31#define TEST_SICODE_PRIV -1 31#define TEST_SICODE_PRIV -1
32#define TEST_SICODE_SHARE -2 32#define TEST_SICODE_SHARE -2
33 33
34#ifndef PAGE_SIZE
35#define PAGE_SIZE sysconf(_SC_PAGESIZE)
36#endif
37
34#define err(fmt, ...) \ 38#define err(fmt, ...) \
35 fprintf(stderr, \ 39 fprintf(stderr, \
36 "Error (%s:%d): " fmt, \ 40 "Error (%s:%d): " fmt, \
diff --git a/tools/testing/selftests/rcutorture/bin/config2frag.sh b/tools/testing/selftests/rcutorture/bin/config2frag.sh
index 9f9ffcd427d3..56f51ae13d73 100644..100755
--- a/tools/testing/selftests/rcutorture/bin/config2frag.sh
+++ b/tools/testing/selftests/rcutorture/bin/config2frag.sh
@@ -1,5 +1,5 @@
1#!/bin/sh 1#!/bin/bash
2# Usage: sh config2frag.sh < .config > configfrag 2# Usage: config2frag.sh < .config > configfrag
3# 3#
4# Converts the "# CONFIG_XXX is not set" to "CONFIG_XXX=n" so that the 4# Converts the "# CONFIG_XXX is not set" to "CONFIG_XXX=n" so that the
5# resulting file becomes a legitimate Kconfig fragment. 5# resulting file becomes a legitimate Kconfig fragment.
diff --git a/tools/testing/selftests/rcutorture/bin/configcheck.sh b/tools/testing/selftests/rcutorture/bin/configcheck.sh
index d686537dd55c..eee31e261bf7 100755
--- a/tools/testing/selftests/rcutorture/bin/configcheck.sh
+++ b/tools/testing/selftests/rcutorture/bin/configcheck.sh
@@ -1,5 +1,5 @@
1#!/bin/sh 1#!/bin/bash
2# Usage: sh configcheck.sh .config .config-template 2# Usage: configcheck.sh .config .config-template
3# 3#
4# This program is free software; you can redistribute it and/or modify 4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by 5# it under the terms of the GNU General Public License as published by
diff --git a/tools/testing/selftests/rcutorture/bin/configinit.sh b/tools/testing/selftests/rcutorture/bin/configinit.sh
index 9c3f3d39b934..15f1a17ca96e 100755
--- a/tools/testing/selftests/rcutorture/bin/configinit.sh
+++ b/tools/testing/selftests/rcutorture/bin/configinit.sh
@@ -1,6 +1,6 @@
1#!/bin/sh 1#!/bin/bash
2# 2#
3# sh configinit.sh config-spec-file [ build output dir ] 3# Usage: configinit.sh config-spec-file [ build output dir ]
4# 4#
5# Create a .config file from the spec file. Run from the kernel source tree. 5# Create a .config file from the spec file. Run from the kernel source tree.
6# Exits with 0 if all went well, with 1 if all went well but the config 6# Exits with 0 if all went well, with 1 if all went well but the config
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh
index d01b865bb100..b325470c01b3 100644
--- a/tools/testing/selftests/rcutorture/bin/functions.sh
+++ b/tools/testing/selftests/rcutorture/bin/functions.sh
@@ -64,6 +64,26 @@ configfrag_boot_params () {
64 fi 64 fi
65} 65}
66 66
67# configfrag_boot_cpus bootparam-string config-fragment-file config-cpus
68#
69# Decreases number of CPUs based on any maxcpus= boot parameters specified.
70configfrag_boot_cpus () {
71 local bootargs="`configfrag_boot_params "$1" "$2"`"
72 local maxcpus
73 if echo "${bootargs}" | grep -q 'maxcpus=[0-9]'
74 then
75 maxcpus="`echo "${bootargs}" | sed -e 's/^.*maxcpus=\([0-9]*\).*$/\1/'`"
76 if test "$3" -gt "$maxcpus"
77 then
78 echo $maxcpus
79 else
80 echo $3
81 fi
82 else
83 echo $3
84 fi
85}
86
67# configfrag_hotplug_cpu config-fragment-file 87# configfrag_hotplug_cpu config-fragment-file
68# 88#
69# Returns 1 if the config fragment specifies hotplug CPU. 89# Returns 1 if the config fragment specifies hotplug CPU.
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-build.sh b/tools/testing/selftests/rcutorture/bin/kvm-build.sh
index 7c1e56b46de4..00cb0db2643d 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-build.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-build.sh
@@ -2,7 +2,7 @@
2# 2#
3# Build a kvm-ready Linux kernel from the tree in the current directory. 3# Build a kvm-ready Linux kernel from the tree in the current directory.
4# 4#
5# Usage: sh kvm-build.sh config-template build-dir more-configs 5# Usage: kvm-build.sh config-template build-dir more-configs
6# 6#
7# This program is free software; you can redistribute it and/or modify 7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by 8# it under the terms of the GNU General Public License as published by
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
index 7f1ff1a8fc4b..43f764098e50 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-lock.sh
@@ -2,7 +2,7 @@
2# 2#
3# Analyze a given results directory for locktorture progress. 3# Analyze a given results directory for locktorture progress.
4# 4#
5# Usage: sh kvm-recheck-lock.sh resdir 5# Usage: kvm-recheck-lock.sh resdir
6# 6#
7# This program is free software; you can redistribute it and/or modify 7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by 8# it under the terms of the GNU General Public License as published by
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
index 307c4b95f325..d6cc07fc137f 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcu.sh
@@ -2,7 +2,7 @@
2# 2#
3# Analyze a given results directory for rcutorture progress. 3# Analyze a given results directory for rcutorture progress.
4# 4#
5# Usage: sh kvm-recheck-rcu.sh resdir 5# Usage: kvm-recheck-rcu.sh resdir
6# 6#
7# This program is free software; you can redistribute it and/or modify 7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by 8# it under the terms of the GNU General Public License as published by
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
index 3f6c9b78d177..4f5b20f367a9 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
@@ -4,7 +4,7 @@
4# check the build and console output for errors. Given a directory 4# check the build and console output for errors. Given a directory
5# containing results directories, this recursively checks them all. 5# containing results directories, this recursively checks them all.
6# 6#
7# Usage: sh kvm-recheck.sh resdir ... 7# Usage: kvm-recheck.sh resdir ...
8# 8#
9# This program is free software; you can redistribute it and/or modify 9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by 10# it under the terms of the GNU General Public License as published by
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 0f69dcbf9def..f6b2b4771b78 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -6,7 +6,7 @@
6# Execute this in the source tree. Do not run it as a background task 6# Execute this in the source tree. Do not run it as a background task
7# because qemu does not seem to like that much. 7# because qemu does not seem to like that much.
8# 8#
9# Usage: sh kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args 9# Usage: kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args
10# 10#
11# qemu-args defaults to "-nographic", along with arguments specifying the 11# qemu-args defaults to "-nographic", along with arguments specifying the
12# number of CPUs and other options generated from 12# number of CPUs and other options generated from
@@ -140,6 +140,7 @@ fi
140# Generate -smp qemu argument. 140# Generate -smp qemu argument.
141qemu_args="-nographic $qemu_args" 141qemu_args="-nographic $qemu_args"
142cpu_count=`configNR_CPUS.sh $config_template` 142cpu_count=`configNR_CPUS.sh $config_template`
143cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"`
143vcpus=`identify_qemu_vcpus` 144vcpus=`identify_qemu_vcpus`
144if test $cpu_count -gt $vcpus 145if test $cpu_count -gt $vcpus
145then 146then
@@ -214,7 +215,7 @@ then
214 fi 215 fi
215 if test $kruntime -ge $((seconds + grace)) 216 if test $kruntime -ge $((seconds + grace))
216 then 217 then
217 echo "!!! Hang at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1 218 echo "!!! PID $qemu_pid hung at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1
218 kill -KILL $qemu_pid 219 kill -KILL $qemu_pid
219 break 220 break
220 fi 221 fi
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 589e9c38413b..e527dc952eb0 100644..100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -7,7 +7,7 @@
7# Edit the definitions below to set the locations of the various directories, 7# Edit the definitions below to set the locations of the various directories,
8# as well as the test duration. 8# as well as the test duration.
9# 9#
10# Usage: sh kvm.sh [ options ] 10# Usage: kvm.sh [ options ]
11# 11#
12# This program is free software; you can redistribute it and/or modify 12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by 13# it under the terms of the GNU General Public License as published by
@@ -188,7 +188,9 @@ for CF in $configs
188do 188do
189 if test -f "$CONFIGFRAG/$kversion/$CF" 189 if test -f "$CONFIGFRAG/$kversion/$CF"
190 then 190 then
191 echo $CF `configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF` >> $T/cfgcpu 191 cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF`
192 cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$kversion/$CF" "$cpu_count"`
193 echo $CF $cpu_count >> $T/cfgcpu
192 else 194 else
193 echo "The --configs file $CF does not exist, terminating." 195 echo "The --configs file $CF does not exist, terminating."
194 exit 1 196 exit 1
diff --git a/tools/testing/selftests/rcutorture/bin/parse-build.sh b/tools/testing/selftests/rcutorture/bin/parse-build.sh
index 543230951c38..499d1e598e42 100755
--- a/tools/testing/selftests/rcutorture/bin/parse-build.sh
+++ b/tools/testing/selftests/rcutorture/bin/parse-build.sh
@@ -1,4 +1,4 @@
1#!/bin/sh 1#!/bin/bash
2# 2#
3# Check the build output from an rcutorture run for goodness. 3# Check the build output from an rcutorture run for goodness.
4# The "file" is a pathname on the local system, and "title" is 4# The "file" is a pathname on the local system, and "title" is
@@ -6,8 +6,7 @@
6# 6#
7# The file must contain kernel build output. 7# The file must contain kernel build output.
8# 8#
9# Usage: 9# Usage: parse-build.sh file title
10# sh parse-build.sh file title
11# 10#
12# This program is free software; you can redistribute it and/or modify 11# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by 12# it under the terms of the GNU General Public License as published by
diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh
index 4185d4cab32e..f962ba4cf68b 100755
--- a/tools/testing/selftests/rcutorture/bin/parse-console.sh
+++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh
@@ -1,11 +1,10 @@
1#!/bin/sh 1#!/bin/bash
2# 2#
3# Check the console output from an rcutorture run for oopses. 3# Check the console output from an rcutorture run for oopses.
4# The "file" is a pathname on the local system, and "title" is 4# The "file" is a pathname on the local system, and "title" is
5# a text string for error-message purposes. 5# a text string for error-message purposes.
6# 6#
7# Usage: 7# Usage: parse-console.sh file title
8# sh parse-console.sh file title
9# 8#
10# This program is free software; you can redistribute it and/or modify 9# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by 10# it under the terms of the GNU General Public License as published by
@@ -33,6 +32,10 @@ title="$2"
33 32
34. functions.sh 33. functions.sh
35 34
35if grep -Pq '\x00' < $file
36then
37 print_warning Console output contains nul bytes, old qemu still running?
38fi
36egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T 39egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $T
37if test -s $T 40if test -s $T
38then 41then
diff --git a/tools/testing/selftests/rcutorture/bin/parse-torture.sh b/tools/testing/selftests/rcutorture/bin/parse-torture.sh
index 3455560ab4e4..e3c5f0705696 100755
--- a/tools/testing/selftests/rcutorture/bin/parse-torture.sh
+++ b/tools/testing/selftests/rcutorture/bin/parse-torture.sh
@@ -1,4 +1,4 @@
1#!/bin/sh 1#!/bin/bash
2# 2#
3# Check the console output from a torture run for goodness. 3# Check the console output from a torture run for goodness.
4# The "file" is a pathname on the local system, and "title" is 4# The "file" is a pathname on the local system, and "title" is
@@ -7,8 +7,7 @@
7# The file must contain torture output, but can be interspersed 7# The file must contain torture output, but can be interspersed
8# with other dmesg text, as in console-log output. 8# with other dmesg text, as in console-log output.
9# 9#
10# Usage: 10# Usage: parse-torture.sh file title
11# sh parse-torture.sh file title
12# 11#
13# This program is free software; you can redistribute it and/or modify 12# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License as published by 13# it under the terms of the GNU General Public License as published by
diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
index a061b22d1892..6910b7370761 100644
--- a/tools/testing/selftests/rcutorture/configs/lock/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST
@@ -1 +1,4 @@
1LOCK01 1LOCK01
2LOCK02
3LOCK03
4LOCK04 \ No newline at end of file
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK02 b/tools/testing/selftests/rcutorture/configs/lock/LOCK02
new file mode 100644
index 000000000000..1d1da1477fc3
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK02
@@ -0,0 +1,6 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=4
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK02.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK02.boot
new file mode 100644
index 000000000000..5aa44b4f1b51
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK02.boot
@@ -0,0 +1 @@
locktorture.torture_type=mutex_lock
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK03 b/tools/testing/selftests/rcutorture/configs/lock/LOCK03
new file mode 100644
index 000000000000..1d1da1477fc3
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK03
@@ -0,0 +1,6 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=4
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK03.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK03.boot
new file mode 100644
index 000000000000..a67bbe0245c9
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK03.boot
@@ -0,0 +1 @@
locktorture.torture_type=rwsem_lock
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK04 b/tools/testing/selftests/rcutorture/configs/lock/LOCK04
new file mode 100644
index 000000000000..1d1da1477fc3
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK04
@@ -0,0 +1,6 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=4
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK04.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK04.boot
new file mode 100644
index 000000000000..48c04fe47fb4
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK04.boot
@@ -0,0 +1 @@
locktorture.torture_type=rw_lock
diff --git a/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
index 9746ea1cd6c7..252aae618984 100644
--- a/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/lock/ver_functions.sh
@@ -38,6 +38,6 @@ per_version_boot_params () {
38 echo $1 `locktorture_param_onoff "$1" "$2"` \ 38 echo $1 `locktorture_param_onoff "$1" "$2"` \
39 locktorture.stat_interval=15 \ 39 locktorture.stat_interval=15 \
40 locktorture.shutdown_secs=$3 \ 40 locktorture.shutdown_secs=$3 \
41 locktorture.locktorture_runnable=1 \ 41 locktorture.torture_runnable=1 \
42 locktorture.verbose=1 42 locktorture.verbose=1
43} 43}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
index cd3d29cb0a47..a3a1a05a2b5c 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFLIST
@@ -11,3 +11,6 @@ SRCU-N
11SRCU-P 11SRCU-P
12TINY01 12TINY01
13TINY02 13TINY02
14TASKS01
15TASKS02
16TASKS03
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS01 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01
new file mode 100644
index 000000000000..97f0a0b27ef7
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01
@@ -0,0 +1,9 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=2
3CONFIG_HOTPLUG_CPU=y
4CONFIG_PREEMPT_NONE=n
5CONFIG_PREEMPT_VOLUNTARY=n
6CONFIG_PREEMPT=y
7CONFIG_DEBUG_LOCK_ALLOC=y
8CONFIG_PROVE_RCU=y
9CONFIG_TASKS_RCU=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01.boot
new file mode 100644
index 000000000000..cd2a188eeb6d
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS01.boot
@@ -0,0 +1 @@
rcutorture.torture_type=tasks
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS02 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS02
new file mode 100644
index 000000000000..696d2ea74d13
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS02
@@ -0,0 +1,5 @@
1CONFIG_SMP=n
2CONFIG_PREEMPT_NONE=y
3CONFIG_PREEMPT_VOLUNTARY=n
4CONFIG_PREEMPT=n
5CONFIG_TASKS_RCU=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS02.boot b/tools/testing/selftests/rcutorture/configs/rcu/TASKS02.boot
new file mode 100644
index 000000000000..cd2a188eeb6d
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS02.boot
@@ -0,0 +1 @@
rcutorture.torture_type=tasks
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03 b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03
new file mode 100644
index 000000000000..9c60da5b5d1d
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03
@@ -0,0 +1,13 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=2
3CONFIG_HOTPLUG_CPU=n
4CONFIG_SUSPEND=n
5CONFIG_HIBERNATION=n
6CONFIG_PREEMPT_NONE=n
7CONFIG_PREEMPT_VOLUNTARY=n
8CONFIG_PREEMPT=y
9CONFIG_TASKS_RCU=y
10CONFIG_HZ_PERIODIC=n
11CONFIG_NO_HZ_IDLE=n
12CONFIG_NO_HZ_FULL=y
13CONFIG_NO_HZ_FULL_ALL=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot
new file mode 100644
index 000000000000..cd2a188eeb6d
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TASKS03.boot
@@ -0,0 +1 @@
rcutorture.torture_type=tasks
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
index 063b7079c621..38e3895759dd 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
@@ -1,5 +1,4 @@
1CONFIG_SMP=y 1CONFIG_SMP=y
2CONFIG_NR_CPUS=8
3CONFIG_PREEMPT_NONE=n 2CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n 3CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y 4CONFIG_PREEMPT=y
@@ -10,8 +9,7 @@ CONFIG_NO_HZ_FULL=n
10CONFIG_RCU_FAST_NO_HZ=y 9CONFIG_RCU_FAST_NO_HZ=y
11CONFIG_RCU_TRACE=y 10CONFIG_RCU_TRACE=y
12CONFIG_HOTPLUG_CPU=y 11CONFIG_HOTPLUG_CPU=y
13CONFIG_RCU_FANOUT=8 12CONFIG_MAXSMP=y
14CONFIG_RCU_FANOUT_EXACT=n
15CONFIG_RCU_NOCB_CPU=y 13CONFIG_RCU_NOCB_CPU=y
16CONFIG_RCU_NOCB_CPU_ZERO=y 14CONFIG_RCU_NOCB_CPU_ZERO=y
17CONFIG_DEBUG_LOCK_ALLOC=n 15CONFIG_DEBUG_LOCK_ALLOC=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
index 0fc8a3428938..adc3abc82fb8 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01.boot
@@ -1 +1 @@
rcutorture.torture_type=rcu_bh rcutorture.torture_type=rcu_bh maxcpus=8
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index ab6225506909..8f1017666aa7 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -1,5 +1,6 @@
1CONFIG_SMP=y 1CONFIG_SMP=y
2CONFIG_NR_CPUS=16 2CONFIG_NR_CPUS=16
3CONFIG_CPUMASK_OFFSTACK=y
3CONFIG_PREEMPT_NONE=y 4CONFIG_PREEMPT_NONE=y
4CONFIG_PREEMPT_VOLUNTARY=n 5CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=n 6CONFIG_PREEMPT=n
@@ -7,7 +8,7 @@ CONFIG_PREEMPT=n
7CONFIG_HZ_PERIODIC=n 8CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=n 9CONFIG_NO_HZ_IDLE=n
9CONFIG_NO_HZ_FULL=y 10CONFIG_NO_HZ_FULL=y
10CONFIG_NO_HZ_FULL_ALL=y 11CONFIG_NO_HZ_FULL_ALL=n
11CONFIG_NO_HZ_FULL_SYSIDLE=y 12CONFIG_NO_HZ_FULL_SYSIDLE=y
12CONFIG_RCU_FAST_NO_HZ=n 13CONFIG_RCU_FAST_NO_HZ=n
13CONFIG_RCU_TRACE=y 14CONFIG_RCU_TRACE=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE07.boot
new file mode 100644
index 000000000000..d44609937503
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07.boot
@@ -0,0 +1 @@
nohz_full=2-9
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
index 8977d8d31b19..ffb85ed786fa 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
+++ b/tools/testing/selftests/rcutorture/configs/rcu/ver_functions.sh
@@ -51,7 +51,7 @@ per_version_boot_params () {
51 `rcutorture_param_n_barrier_cbs "$1"` \ 51 `rcutorture_param_n_barrier_cbs "$1"` \
52 rcutorture.stat_interval=15 \ 52 rcutorture.stat_interval=15 \
53 rcutorture.shutdown_secs=$3 \ 53 rcutorture.shutdown_secs=$3 \
54 rcutorture.rcutorture_runnable=1 \ 54 rcutorture.torture_runnable=1 \
55 rcutorture.test_no_idle_hz=1 \ 55 rcutorture.test_no_idle_hz=1 \
56 rcutorture.verbose=1 56 rcutorture.verbose=1
57} 57}
diff --git a/tools/testing/selftests/rcutorture/doc/initrd.txt b/tools/testing/selftests/rcutorture/doc/initrd.txt
index 49d134c25c04..4170e714f044 100644
--- a/tools/testing/selftests/rcutorture/doc/initrd.txt
+++ b/tools/testing/selftests/rcutorture/doc/initrd.txt
@@ -6,6 +6,7 @@ this case. There are probably much better ways of doing this.
6That said, here are the commands: 6That said, here are the commands:
7 7
8------------------------------------------------------------------------ 8------------------------------------------------------------------------
9cd tools/testing/selftests/rcutorture
9zcat /initrd.img > /tmp/initrd.img.zcat 10zcat /initrd.img > /tmp/initrd.img.zcat
10mkdir initrd 11mkdir initrd
11cd initrd 12cd initrd
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index 3f94e1afd6cf..4c4b1f631ecf 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -3,6 +3,7 @@
3CC = $(CROSS_COMPILE)gcc 3CC = $(CROSS_COMPILE)gcc
4CFLAGS = -Wall 4CFLAGS = -Wall
5BINARIES = hugepage-mmap hugepage-shm map_hugetlb thuge-gen hugetlbfstest 5BINARIES = hugepage-mmap hugepage-shm map_hugetlb thuge-gen hugetlbfstest
6BINARIES += transhuge-stress
6 7
7all: $(BINARIES) 8all: $(BINARIES)
8%: %.c 9%: %.c
diff --git a/tools/testing/selftests/vm/transhuge-stress.c b/tools/testing/selftests/vm/transhuge-stress.c
new file mode 100644
index 000000000000..fd7f1b4a96f9
--- /dev/null
+++ b/tools/testing/selftests/vm/transhuge-stress.c
@@ -0,0 +1,144 @@
1/*
2 * Stress test for transparent huge pages, memory compaction and migration.
3 *
4 * Authors: Konstantin Khlebnikov <koct9i@gmail.com>
5 *
6 * This is free and unencumbered software released into the public domain.
7 */
8
9#include <stdlib.h>
10#include <stdio.h>
11#include <stdint.h>
12#include <err.h>
13#include <time.h>
14#include <unistd.h>
15#include <fcntl.h>
16#include <string.h>
17#include <sys/mman.h>
18
19#define PAGE_SHIFT 12
20#define HPAGE_SHIFT 21
21
22#define PAGE_SIZE (1 << PAGE_SHIFT)
23#define HPAGE_SIZE (1 << HPAGE_SHIFT)
24
25#define PAGEMAP_PRESENT(ent) (((ent) & (1ull << 63)) != 0)
26#define PAGEMAP_PFN(ent) ((ent) & ((1ull << 55) - 1))
27
28int pagemap_fd;
29
30int64_t allocate_transhuge(void *ptr)
31{
32 uint64_t ent[2];
33
34 /* drop pmd */
35 if (mmap(ptr, HPAGE_SIZE, PROT_READ | PROT_WRITE,
36 MAP_FIXED | MAP_ANONYMOUS |
37 MAP_NORESERVE | MAP_PRIVATE, -1, 0) != ptr)
38 errx(2, "mmap transhuge");
39
40 if (madvise(ptr, HPAGE_SIZE, MADV_HUGEPAGE))
41 err(2, "MADV_HUGEPAGE");
42
43 /* allocate transparent huge page */
44 *(volatile void **)ptr = ptr;
45
46 if (pread(pagemap_fd, ent, sizeof(ent),
47 (uintptr_t)ptr >> (PAGE_SHIFT - 3)) != sizeof(ent))
48 err(2, "read pagemap");
49
50 if (PAGEMAP_PRESENT(ent[0]) && PAGEMAP_PRESENT(ent[1]) &&
51 PAGEMAP_PFN(ent[0]) + 1 == PAGEMAP_PFN(ent[1]) &&
52 !(PAGEMAP_PFN(ent[0]) & ((1 << (HPAGE_SHIFT - PAGE_SHIFT)) - 1)))
53 return PAGEMAP_PFN(ent[0]);
54
55 return -1;
56}
57
58int main(int argc, char **argv)
59{
60 size_t ram, len;
61 void *ptr, *p;
62 struct timespec a, b;
63 double s;
64 uint8_t *map;
65 size_t map_len;
66
67 ram = sysconf(_SC_PHYS_PAGES);
68 if (ram > SIZE_MAX / sysconf(_SC_PAGESIZE) / 4)
69 ram = SIZE_MAX / 4;
70 else
71 ram *= sysconf(_SC_PAGESIZE);
72
73 if (argc == 1)
74 len = ram;
75 else if (!strcmp(argv[1], "-h"))
76 errx(1, "usage: %s [size in MiB]", argv[0]);
77 else
78 len = atoll(argv[1]) << 20;
79
80 warnx("allocate %zd transhuge pages, using %zd MiB virtual memory"
81 " and %zd MiB of ram", len >> HPAGE_SHIFT, len >> 20,
82 len >> (20 + HPAGE_SHIFT - PAGE_SHIFT - 1));
83
84 pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
85 if (pagemap_fd < 0)
86 err(2, "open pagemap");
87
88 len -= len % HPAGE_SIZE;
89 ptr = mmap(NULL, len + HPAGE_SIZE, PROT_READ | PROT_WRITE,
90 MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0);
91 if (ptr == MAP_FAILED)
92 err(2, "initial mmap");
93 ptr += HPAGE_SIZE - (uintptr_t)ptr % HPAGE_SIZE;
94
95 if (madvise(ptr, len, MADV_HUGEPAGE))
96 err(2, "MADV_HUGEPAGE");
97
98 map_len = ram >> (HPAGE_SHIFT - 1);
99 map = malloc(map_len);
100 if (!map)
101 errx(2, "map malloc");
102
103 while (1) {
104 int nr_succeed = 0, nr_failed = 0, nr_pages = 0;
105
106 memset(map, 0, map_len);
107
108 clock_gettime(CLOCK_MONOTONIC, &a);
109 for (p = ptr; p < ptr + len; p += HPAGE_SIZE) {
110 int64_t pfn;
111
112 pfn = allocate_transhuge(p);
113
114 if (pfn < 0) {
115 nr_failed++;
116 } else {
117 size_t idx = pfn >> (HPAGE_SHIFT - PAGE_SHIFT);
118
119 nr_succeed++;
120 if (idx >= map_len) {
121 map = realloc(map, idx + 1);
122 if (!map)
123 errx(2, "map realloc");
124 memset(map + map_len, 0, idx + 1 - map_len);
125 map_len = idx + 1;
126 }
127 if (!map[idx])
128 nr_pages++;
129 map[idx] = 1;
130 }
131
132 /* split transhuge page, keep last page */
133 if (madvise(p, HPAGE_SIZE - PAGE_SIZE, MADV_DONTNEED))
134 err(2, "MADV_DONTNEED");
135 }
136 clock_gettime(CLOCK_MONOTONIC, &b);
137 s = b.tv_sec - a.tv_sec + (b.tv_nsec - a.tv_nsec) / 1000000000.;
138
139 warnx("%.3f s/loop, %.3f ms/page, %10.3f MiB/s\t"
140 "%4d succeed, %4d failed, %4d different pages",
141 s, s * 1000 / (len >> HPAGE_SHIFT), len / s / (1 << 20),
142 nr_succeed, nr_failed, nr_pages);
143 }
144}
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index a87e99f37c52..88d5e71be044 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * ffs-test.c.c -- user mode filesystem api for usb composite function 2 * ffs-test.c -- user mode filesystem api for usb composite function
3 * 3 *
4 * Copyright (C) 2010 Samsung Electronics 4 * Copyright (C) 2010 Samsung Electronics
5 * Author: Michal Nazarewicz <mina86@mina86.com> 5 * Author: Michal Nazarewicz <mina86@mina86.com>
@@ -29,6 +29,7 @@
29#include <fcntl.h> 29#include <fcntl.h>
30#include <pthread.h> 30#include <pthread.h>
31#include <stdarg.h> 31#include <stdarg.h>
32#include <stdbool.h>
32#include <stdio.h> 33#include <stdio.h>
33#include <stdlib.h> 34#include <stdlib.h>
34#include <string.h> 35#include <string.h>
@@ -106,7 +107,9 @@ static void _msg(unsigned level, const char *fmt, ...)
106/******************** Descriptors and Strings *******************************/ 107/******************** Descriptors and Strings *******************************/
107 108
108static const struct { 109static const struct {
109 struct usb_functionfs_descs_head header; 110 struct usb_functionfs_descs_head_v2 header;
111 __le32 fs_count;
112 __le32 hs_count;
110 struct { 113 struct {
111 struct usb_interface_descriptor intf; 114 struct usb_interface_descriptor intf;
112 struct usb_endpoint_descriptor_no_audio sink; 115 struct usb_endpoint_descriptor_no_audio sink;
@@ -114,11 +117,12 @@ static const struct {
114 } __attribute__((packed)) fs_descs, hs_descs; 117 } __attribute__((packed)) fs_descs, hs_descs;
115} __attribute__((packed)) descriptors = { 118} __attribute__((packed)) descriptors = {
116 .header = { 119 .header = {
117 .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC), 120 .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
121 .flags = cpu_to_le32(FUNCTIONFS_HAS_FS_DESC |
122 FUNCTIONFS_HAS_HS_DESC),
118 .length = cpu_to_le32(sizeof descriptors), 123 .length = cpu_to_le32(sizeof descriptors),
119 .fs_count = cpu_to_le32(3),
120 .hs_count = cpu_to_le32(3),
121 }, 124 },
125 .fs_count = cpu_to_le32(3),
122 .fs_descs = { 126 .fs_descs = {
123 .intf = { 127 .intf = {
124 .bLength = sizeof descriptors.fs_descs.intf, 128 .bLength = sizeof descriptors.fs_descs.intf,
@@ -142,6 +146,7 @@ static const struct {
142 /* .wMaxPacketSize = autoconfiguration (kernel) */ 146 /* .wMaxPacketSize = autoconfiguration (kernel) */
143 }, 147 },
144 }, 148 },
149 .hs_count = cpu_to_le32(3),
145 .hs_descs = { 150 .hs_descs = {
146 .intf = { 151 .intf = {
147 .bLength = sizeof descriptors.fs_descs.intf, 152 .bLength = sizeof descriptors.fs_descs.intf,
@@ -168,6 +173,89 @@ static const struct {
168 }, 173 },
169}; 174};
170 175
176static size_t descs_to_legacy(void **legacy, const void *descriptors_v2)
177{
178 const unsigned char *descs_end, *descs_start;
179 __u32 length, fs_count = 0, hs_count = 0, count;
180
181 /* Read v2 header */
182 {
183 const struct {
184 const struct usb_functionfs_descs_head_v2 header;
185 const __le32 counts[];
186 } __attribute__((packed)) *const in = descriptors_v2;
187 const __le32 *counts = in->counts;
188 __u32 flags;
189
190 if (le32_to_cpu(in->header.magic) !=
191 FUNCTIONFS_DESCRIPTORS_MAGIC_V2)
192 return 0;
193 length = le32_to_cpu(in->header.length);
194 if (length <= sizeof in->header)
195 return 0;
196 length -= sizeof in->header;
197 flags = le32_to_cpu(in->header.flags);
198 if (flags & ~(FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
199 FUNCTIONFS_HAS_SS_DESC))
200 return 0;
201
202#define GET_NEXT_COUNT_IF_FLAG(ret, flg) do { \
203 if (!(flags & (flg))) \
204 break; \
205 if (length < 4) \
206 return 0; \
207 ret = le32_to_cpu(*counts); \
208 length -= 4; \
209 ++counts; \
210 } while (0)
211
212 GET_NEXT_COUNT_IF_FLAG(fs_count, FUNCTIONFS_HAS_FS_DESC);
213 GET_NEXT_COUNT_IF_FLAG(hs_count, FUNCTIONFS_HAS_HS_DESC);
214 GET_NEXT_COUNT_IF_FLAG(count, FUNCTIONFS_HAS_SS_DESC);
215
216 count = fs_count + hs_count;
217 if (!count)
218 return 0;
219 descs_start = (const void *)counts;
220
221#undef GET_NEXT_COUNT_IF_FLAG
222 }
223
224 /*
225 * Find the end of FS and HS USB descriptors. SS descriptors
226 * are ignored since legacy format does not support them.
227 */
228 descs_end = descs_start;
229 do {
230 if (length < *descs_end)
231 return 0;
232 length -= *descs_end;
233 descs_end += *descs_end;
234 } while (--count);
235
236 /* Allocate legacy descriptors and copy the data. */
237 {
238#pragma GCC diagnostic push
239#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
240 struct {
241 struct usb_functionfs_descs_head header;
242 __u8 descriptors[];
243 } __attribute__((packed)) *out;
244#pragma GCC diagnostic pop
245
246 length = sizeof out->header + (descs_end - descs_start);
247 out = malloc(length);
248 out->header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
249 out->header.length = cpu_to_le32(length);
250 out->header.fs_count = cpu_to_le32(fs_count);
251 out->header.hs_count = cpu_to_le32(hs_count);
252 memcpy(out->descriptors, descs_start, descs_end - descs_start);
253 *legacy = out;
254 }
255
256 return length;
257}
258
171 259
172#define STR_INTERFACE_ "Source/Sink" 260#define STR_INTERFACE_ "Source/Sink"
173 261
@@ -487,12 +575,29 @@ ep0_consume(struct thread *ignore, const void *buf, size_t nbytes)
487 return nbytes; 575 return nbytes;
488} 576}
489 577
490static void ep0_init(struct thread *t) 578static void ep0_init(struct thread *t, bool legacy_descriptors)
491{ 579{
580 void *legacy;
492 ssize_t ret; 581 ssize_t ret;
582 size_t len;
583
584 if (legacy_descriptors) {
585 info("%s: writing descriptors\n", t->filename);
586 goto legacy;
587 }
493 588
494 info("%s: writing descriptors\n", t->filename); 589 info("%s: writing descriptors (in v2 format)\n", t->filename);
495 ret = write(t->fd, &descriptors, sizeof descriptors); 590 ret = write(t->fd, &descriptors, sizeof descriptors);
591
592 if (ret < 0 && errno == EINVAL) {
593 warn("%s: new format rejected, trying legacy\n", t->filename);
594legacy:
595 len = descs_to_legacy(&legacy, &descriptors);
596 if (len) {
597 ret = write(t->fd, legacy, len);
598 free(legacy);
599 }
600 }
496 die_on(ret < 0, "%s: write: descriptors", t->filename); 601 die_on(ret < 0, "%s: write: descriptors", t->filename);
497 602
498 info("%s: writing strings\n", t->filename); 603 info("%s: writing strings\n", t->filename);
@@ -503,14 +608,15 @@ static void ep0_init(struct thread *t)
503 608
504/******************** Main **************************************************/ 609/******************** Main **************************************************/
505 610
506int main(void) 611int main(int argc, char **argv)
507{ 612{
613 bool legacy_descriptors;
508 unsigned i; 614 unsigned i;
509 615
510 /* XXX TODO: Argument parsing missing */ 616 legacy_descriptors = argc > 2 && !strcmp(argv[1], "-l");
511 617
512 init_thread(threads); 618 init_thread(threads);
513 ep0_init(threads); 619 ep0_init(threads, legacy_descriptors);
514 620
515 for (i = 1; i < sizeof threads / sizeof *threads; ++i) 621 for (i = 1; i < sizeof threads / sizeof *threads; ++i)
516 init_thread(threads + i); 622 init_thread(threads + i);
diff --git a/tools/usb/usbip/.gitignore b/tools/usb/usbip/.gitignore
new file mode 100644
index 000000000000..9aad9e30a8ba
--- /dev/null
+++ b/tools/usb/usbip/.gitignore
@@ -0,0 +1,28 @@
1Makefile
2Makefile.in
3aclocal.m4
4autom4te.cache/
5config.guess
6config.h
7config.h.in
8config.log
9config.status
10config.sub
11configure
12depcomp
13install-sh
14libsrc/Makefile
15libsrc/Makefile.in
16libtool
17ltmain.sh
18missing
19src/Makefile
20src/Makefile.in
21stamp-h1
22libsrc/libusbip.la
23libsrc/libusbip_la-names.lo
24libsrc/libusbip_la-usbip_common.lo
25libsrc/libusbip_la-usbip_host_driver.lo
26libsrc/libusbip_la-vhci_driver.lo
27src/usbip
28src/usbipd
diff --git a/tools/usb/usbip/AUTHORS b/tools/usb/usbip/AUTHORS
new file mode 100644
index 000000000000..a27ea8d03aec
--- /dev/null
+++ b/tools/usb/usbip/AUTHORS
@@ -0,0 +1,3 @@
1Takahiro Hirofuchi
2Robert Leibl
3matt mooney <mfm@muteddisk.com>
diff --git a/tools/usb/usbip/COPYING b/tools/usb/usbip/COPYING
new file mode 100644
index 000000000000..c5611e48a8e1
--- /dev/null
+++ b/tools/usb/usbip/COPYING
@@ -0,0 +1,340 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Library General Public License instead.) You can apply it to
19your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40(2) offer you this license which gives you legal permission to copy,
41distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
281
282 How to Apply These Terms to Your New Programs
283
284 If you develop a new program, and you want it to be of the greatest
285possible use to the public, the best way to achieve this is to make it
286free software which everyone can redistribute and change under these terms.
287
288 To do so, attach the following notices to the program. It is safest
289to attach them to the start of each source file to most effectively
290convey the exclusion of warranty; and each file should have at least
291the "copyright" line and a pointer to where the full notice is found.
292
293 <one line to give the program's name and a brief idea of what it does.>
294 Copyright (C) <year> <name of author>
295
296 This program is free software; you can redistribute it and/or modify
297 it under the terms of the GNU General Public License as published by
298 the Free Software Foundation; either version 2 of the License, or
299 (at your option) any later version.
300
301 This program is distributed in the hope that it will be useful,
302 but WITHOUT ANY WARRANTY; without even the implied warranty of
303 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 GNU General Public License for more details.
305
306 You should have received a copy of the GNU General Public License
307 along with this program; if not, write to the Free Software
308 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
309
310
311Also add information on how to contact you by electronic and paper mail.
312
313If the program is interactive, make it output a short notice like this
314when it starts in an interactive mode:
315
316 Gnomovision version 69, Copyright (C) year name of author
317 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318 This is free software, and you are welcome to redistribute it
319 under certain conditions; type `show c' for details.
320
321The hypothetical commands `show w' and `show c' should show the appropriate
322parts of the General Public License. Of course, the commands you use may
323be called something other than `show w' and `show c'; they could even be
324mouse-clicks or menu items--whatever suits your program.
325
326You should also get your employer (if you work as a programmer) or your
327school, if any, to sign a "copyright disclaimer" for the program, if
328necessary. Here is a sample; alter the names:
329
330 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331 `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
333 <signature of Ty Coon>, 1 April 1989
334 Ty Coon, President of Vice
335
336This General Public License does not permit incorporating your program into
337proprietary programs. If your program is a subroutine library, you may
338consider it more useful to permit linking proprietary applications with the
339library. If this is what you want to do, use the GNU Library General
340Public License instead of this License.
diff --git a/tools/usb/usbip/INSTALL b/tools/usb/usbip/INSTALL
new file mode 100644
index 000000000000..d3c5b40a9409
--- /dev/null
+++ b/tools/usb/usbip/INSTALL
@@ -0,0 +1,237 @@
1Installation Instructions
2*************************
3
4Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
52006, 2007 Free Software Foundation, Inc.
6
7This file is free documentation; the Free Software Foundation gives
8unlimited permission to copy, distribute and modify it.
9
10Basic Installation
11==================
12
13Briefly, the shell commands `./configure; make; make install' should
14configure, build, and install this package. The following
15more-detailed instructions are generic; see the `README' file for
16instructions specific to this package.
17
18 The `configure' shell script attempts to guess correct values for
19various system-dependent variables used during compilation. It uses
20those values to create a `Makefile' in each directory of the package.
21It may also create one or more `.h' files containing system-dependent
22definitions. Finally, it creates a shell script `config.status' that
23you can run in the future to recreate the current configuration, and a
24file `config.log' containing compiler output (useful mainly for
25debugging `configure').
26
27 It can also use an optional file (typically called `config.cache'
28and enabled with `--cache-file=config.cache' or simply `-C') that saves
29the results of its tests to speed up reconfiguring. Caching is
30disabled by default to prevent problems with accidental use of stale
31cache files.
32
33 If you need to do unusual things to compile the package, please try
34to figure out how `configure' could check whether to do them, and mail
35diffs or instructions to the address given in the `README' so they can
36be considered for the next release. If you are using the cache, and at
37some point `config.cache' contains results you don't want to keep, you
38may remove or edit it.
39
40 The file `configure.ac' (or `configure.in') is used to create
41`configure' by a program called `autoconf'. You need `configure.ac' if
42you want to change it or regenerate `configure' using a newer version
43of `autoconf'.
44
45The simplest way to compile this package is:
46
47 1. `cd' to the directory containing the package's source code and type
48 `./configure' to configure the package for your system.
49
50 Running `configure' might take a while. While running, it prints
51 some messages telling which features it is checking for.
52
53 2. Type `make' to compile the package.
54
55 3. Optionally, type `make check' to run any self-tests that come with
56 the package.
57
58 4. Type `make install' to install the programs and any data files and
59 documentation.
60
61 5. You can remove the program binaries and object files from the
62 source code directory by typing `make clean'. To also remove the
63 files that `configure' created (so you can compile the package for
64 a different kind of computer), type `make distclean'. There is
65 also a `make maintainer-clean' target, but that is intended mainly
66 for the package's developers. If you use it, you may have to get
67 all sorts of other programs in order to regenerate files that came
68 with the distribution.
69
70 6. Often, you can also type `make uninstall' to remove the installed
71 files again.
72
73Compilers and Options
74=====================
75
76Some systems require unusual options for compilation or linking that the
77`configure' script does not know about. Run `./configure --help' for
78details on some of the pertinent environment variables.
79
80 You can give `configure' initial values for configuration parameters
81by setting variables in the command line or in the environment. Here
82is an example:
83
84 ./configure CC=c99 CFLAGS=-g LIBS=-lposix
85
86 *Note Defining Variables::, for more details.
87
88Compiling For Multiple Architectures
89====================================
90
91You can compile the package for more than one kind of computer at the
92same time, by placing the object files for each architecture in their
93own directory. To do this, you can use GNU `make'. `cd' to the
94directory where you want the object files and executables to go and run
95the `configure' script. `configure' automatically checks for the
96source code in the directory that `configure' is in and in `..'.
97
98 With a non-GNU `make', it is safer to compile the package for one
99architecture at a time in the source code directory. After you have
100installed the package for one architecture, use `make distclean' before
101reconfiguring for another architecture.
102
103Installation Names
104==================
105
106By default, `make install' installs the package's commands under
107`/usr/local/bin', include files under `/usr/local/include', etc. You
108can specify an installation prefix other than `/usr/local' by giving
109`configure' the option `--prefix=PREFIX'.
110
111 You can specify separate installation prefixes for
112architecture-specific files and architecture-independent files. If you
113pass the option `--exec-prefix=PREFIX' to `configure', the package uses
114PREFIX as the prefix for installing programs and libraries.
115Documentation and other data files still use the regular prefix.
116
117 In addition, if you use an unusual directory layout you can give
118options like `--bindir=DIR' to specify different values for particular
119kinds of files. Run `configure --help' for a list of the directories
120you can set and what kinds of files go in them.
121
122 If the package supports it, you can cause programs to be installed
123with an extra prefix or suffix on their names by giving `configure' the
124option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
125
126Optional Features
127=================
128
129Some packages pay attention to `--enable-FEATURE' options to
130`configure', where FEATURE indicates an optional part of the package.
131They may also pay attention to `--with-PACKAGE' options, where PACKAGE
132is something like `gnu-as' or `x' (for the X Window System). The
133`README' should mention any `--enable-' and `--with-' options that the
134package recognizes.
135
136 For packages that use the X Window System, `configure' can usually
137find the X include and library files automatically, but if it doesn't,
138you can use the `configure' options `--x-includes=DIR' and
139`--x-libraries=DIR' to specify their locations.
140
141Specifying the System Type
142==========================
143
144There may be some features `configure' cannot figure out automatically,
145but needs to determine by the type of machine the package will run on.
146Usually, assuming the package is built to be run on the _same_
147architectures, `configure' can figure that out, but if it prints a
148message saying it cannot guess the machine type, give it the
149`--build=TYPE' option. TYPE can either be a short name for the system
150type, such as `sun4', or a canonical name which has the form:
151
152 CPU-COMPANY-SYSTEM
153
154where SYSTEM can have one of these forms:
155
156 OS KERNEL-OS
157
158 See the file `config.sub' for the possible values of each field. If
159`config.sub' isn't included in this package, then this package doesn't
160need to know the machine type.
161
162 If you are _building_ compiler tools for cross-compiling, you should
163use the option `--target=TYPE' to select the type of system they will
164produce code for.
165
166 If you want to _use_ a cross compiler, that generates code for a
167platform different from the build platform, you should specify the
168"host" platform (i.e., that on which the generated programs will
169eventually be run) with `--host=TYPE'.
170
171Sharing Defaults
172================
173
174If you want to set default values for `configure' scripts to share, you
175can create a site shell script called `config.site' that gives default
176values for variables like `CC', `cache_file', and `prefix'.
177`configure' looks for `PREFIX/share/config.site' if it exists, then
178`PREFIX/etc/config.site' if it exists. Or, you can set the
179`CONFIG_SITE' environment variable to the location of the site script.
180A warning: not all `configure' scripts look for a site script.
181
182Defining Variables
183==================
184
185Variables not defined in a site shell script can be set in the
186environment passed to `configure'. However, some packages may run
187configure again during the build, and the customized values of these
188variables may be lost. In order to avoid this problem, you should set
189them in the `configure' command line, using `VAR=value'. For example:
190
191 ./configure CC=/usr/local2/bin/gcc
192
193causes the specified `gcc' to be used as the C compiler (unless it is
194overridden in the site shell script).
195
196Unfortunately, this technique does not work for `CONFIG_SHELL' due to
197an Autoconf bug. Until the bug is fixed you can use this workaround:
198
199 CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
200
201`configure' Invocation
202======================
203
204`configure' recognizes the following options to control how it operates.
205
206`--help'
207`-h'
208 Print a summary of the options to `configure', and exit.
209
210`--version'
211`-V'
212 Print the version of Autoconf used to generate the `configure'
213 script, and exit.
214
215`--cache-file=FILE'
216 Enable the cache: use and save the results of the tests in FILE,
217 traditionally `config.cache'. FILE defaults to `/dev/null' to
218 disable caching.
219
220`--config-cache'
221`-C'
222 Alias for `--cache-file=config.cache'.
223
224`--quiet'
225`--silent'
226`-q'
227 Do not print messages saying which checks are being made. To
228 suppress all normal output, redirect it to `/dev/null' (any error
229 messages will still be shown).
230
231`--srcdir=DIR'
232 Look for the package's source code in directory DIR. Usually
233 `configure' can determine that directory automatically.
234
235`configure' also accepts some other, not widely useful, options. Run
236`configure --help' for more details.
237
diff --git a/tools/usb/usbip/Makefile.am b/tools/usb/usbip/Makefile.am
new file mode 100644
index 000000000000..66f8bf038c9f
--- /dev/null
+++ b/tools/usb/usbip/Makefile.am
@@ -0,0 +1,6 @@
1SUBDIRS := libsrc src
2includedir = @includedir@/usbip
3include_HEADERS := $(addprefix libsrc/, \
4 usbip_common.h vhci_driver.h usbip_host_driver.h)
5
6dist_man_MANS := $(addprefix doc/, usbip.8 usbipd.8)
diff --git a/tools/usb/usbip/README b/tools/usb/usbip/README
new file mode 100644
index 000000000000..831f49fea3ce
--- /dev/null
+++ b/tools/usb/usbip/README
@@ -0,0 +1,202 @@
1#
2# README for usbip-utils
3#
4# Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
5# 2005-2008 Takahiro Hirofuchi
6
7
8[Requirements]
9 - USB/IP device drivers
10 Found in the staging directory of the Linux kernel.
11
12 - libudev >= 2.0
13 libudev library
14
15 - libwrap0-dev
16 tcp wrapper library
17
18 - gcc >= 4.0
19
20 - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config
21
22[Optional]
23 - hwdata
24 Contains USB device identification data.
25
26
27[Install]
28 0. Generate configuration scripts.
29 $ ./autogen.sh
30
31 1. Compile & install the userspace utilities.
32 $ ./configure [--with-tcp-wrappers=no] [--with-usbids-dir=<dir>]
33 $ make install
34
35 2. Compile & install USB/IP drivers.
36
37
38[Usage]
39 server:# (Physically attach your USB device.)
40
41 server:# insmod usbip-core.ko
42 server:# insmod usbip-host.ko
43
44 server:# usbipd -D
45 - Start usbip daemon.
46
47 server:# usbip list -l
48 - List driver assignments for USB devices.
49
50 server:# usbip bind --busid 1-2
51 - Bind usbip-host.ko to the device with busid 1-2.
52 - The USB device 1-2 is now exportable to other hosts!
53 - Use `usbip unbind --busid 1-2' to stop exporting the device.
54
55 client:# insmod usbip-core.ko
56 client:# insmod vhci-hcd.ko
57
58 client:# usbip list --remote <host>
59 - List exported USB devices on the <host>.
60
61 client:# usbip attach --remote <host> --busid 1-2
62 - Connect the remote USB device.
63
64 client:# usbip port
65 - Show virtual port status.
66
67 client:# usbip detach --port <port>
68 - Detach the USB device.
69
70
71[Example]
72---------------------------
73 SERVER SIDE
74---------------------------
75Physically attach your USB devices to this host.
76
77 trois:# insmod path/to/usbip-core.ko
78 trois:# insmod path/to/usbip-host.ko
79 trois:# usbipd -D
80
81In another terminal, let's look up what USB devices are physically
82attached to this host.
83
84 trois:# usbip list -l
85 Local USB devices
86 =================
87 - busid 1-1 (05a9:a511)
88 1-1:1.0 -> ov511
89
90 - busid 3-2 (0711:0902)
91 3-2:1.0 -> none
92
93 - busid 3-3.1 (08bb:2702)
94 3-3.1:1.0 -> snd-usb-audio
95 3-3.1:1.1 -> snd-usb-audio
96
97 - busid 3-3.2 (04bb:0206)
98 3-3.2:1.0 -> usb-storage
99
100 - busid 3-3 (0409:0058)
101 3-3:1.0 -> hub
102
103 - busid 4-1 (046d:08b2)
104 4-1:1.0 -> none
105 4-1:1.1 -> none
106 4-1:1.2 -> none
107
108 - busid 5-2 (058f:9254)
109 5-2:1.0 -> hub
110
111A USB storage device of busid 3-3.2 is now bound to the usb-storage
112driver. To export this device, we first mark the device as
113"exportable"; the device is bound to the usbip-host driver. Please
114remember you can not export a USB hub.
115
116Mark the device of busid 3-3.2 as exportable:
117
118 trois:# usbip --debug bind --busid 3-3.2
119 ...
120 usbip debug: usbip_bind.c:162:[unbind_other] 3-3.2:1.0 -> usb-storage
121 ...
122 bind device on busid 3-3.2: complete
123
124 trois:# usbip list -l
125 Local USB devices
126 =================
127 ...
128
129 - busid 3-3.2 (04bb:0206)
130 3-3.2:1.0 -> usbip-host
131 ...
132
133---------------------------
134 CLIENT SIDE
135---------------------------
136First, let's list available remote devices that are marked as
137exportable on the host.
138
139 deux:# insmod path/to/usbip-core.ko
140 deux:# insmod path/to/vhci-hcd.ko
141
142 deux:# usbip list --remote 10.0.0.3
143 Exportable USB devices
144 ======================
145 - 10.0.0.3
146 1-1: Prolific Technology, Inc. : unknown product (067b:3507)
147 : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-1
148 : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
149 : 0 - Mass Storage / SCSI / Bulk (Zip) (08/06/50)
150
151 1-2.2.1: Apple Computer, Inc. : unknown product (05ac:0203)
152 : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.1
153 : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
154 : 0 - Human Interface Devices / Boot Interface Subclass / Keyboard (03/01/01)
155
156 1-2.2.3: OmniVision Technologies, Inc. : OV511+ WebCam (05a9:a511)
157 : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.3
158 : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
159 : 0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00)
160
161 3-1: Logitech, Inc. : QuickCam Pro 4000 (046d:08b2)
162 : /sys/devices/pci0000:00/0000:00:1e.0/0000:02:0a.0/usb3/3-1
163 : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
164 : 0 - Data / unknown subclass / unknown protocol (0a/ff/00)
165 : 1 - Audio / Control Device / unknown protocol (01/01/00)
166 : 2 - Audio / Streaming / unknown protocol (01/02/00)
167
168Attach a remote USB device:
169
170 deux:# usbip attach --remote 10.0.0.3 --busid 1-1
171 port 0 attached
172
173Show the devices attached to this client:
174
175 deux:# usbip port
176 Port 00: <Port in Use> at Full Speed(12Mbps)
177 Prolific Technology, Inc. : unknown product (067b:3507)
178 6-1 -> usbip://10.0.0.3:3240/1-1 (remote bus/dev 001/004)
179 6-1:1.0 used by usb-storage
180 /sys/class/scsi_device/0:0:0:0/device
181 /sys/class/scsi_host/host0/device
182 /sys/block/sda/device
183
184Detach the imported device:
185
186 deux:# usbip detach --port 0
187 port 0 detached
188
189
190[Checklist]
191 - See 'Debug Tips' on the project wiki.
192 - http://usbip.wiki.sourceforge.net/how-to-debug-usbip
193 - usbip-host.ko must be bound to the target device.
194 - See /proc/bus/usb/devices and find "Driver=..." lines of the device.
195 - Shutdown firewall.
196 - usbip now uses TCP port 3240.
197 - Disable SELinux.
198 - Check the kernel and daemon messages.
199
200
201[Contact]
202 Mailing List: linux-usb@vger.kernel.org
diff --git a/tools/usb/usbip/autogen.sh b/tools/usb/usbip/autogen.sh
new file mode 100755
index 000000000000..e1112d3fcbf6
--- /dev/null
+++ b/tools/usb/usbip/autogen.sh
@@ -0,0 +1,9 @@
1#!/bin/sh -x
2
3#aclocal
4#autoheader
5#libtoolize --copy --force
6#automake-1.9 -acf
7#autoconf
8
9autoreconf -i -f -v
diff --git a/tools/usb/usbip/cleanup.sh b/tools/usb/usbip/cleanup.sh
new file mode 100755
index 000000000000..955c3ccb729a
--- /dev/null
+++ b/tools/usb/usbip/cleanup.sh
@@ -0,0 +1,12 @@
1#!/bin/sh
2
3if [ -r Makefile ]; then
4 make distclean
5fi
6
7FILES="aclocal.m4 autom4te.cache compile config.guess config.h.in config.log \
8 config.status config.sub configure cscope.out depcomp install-sh \
9 libsrc/Makefile libsrc/Makefile.in libtool ltmain.sh Makefile \
10 Makefile.in missing src/Makefile src/Makefile.in"
11
12rm -vRf $FILES
diff --git a/tools/usb/usbip/configure.ac b/tools/usb/usbip/configure.ac
new file mode 100644
index 000000000000..607d05c5ccfd
--- /dev/null
+++ b/tools/usb/usbip/configure.ac
@@ -0,0 +1,111 @@
1dnl Process this file with autoconf to produce a configure script.
2
3AC_PREREQ(2.59)
4AC_INIT([usbip-utils], [2.0], [linux-usb@vger.kernel.org])
5AC_DEFINE([USBIP_VERSION], [0x00000111], [binary-coded decimal version number])
6
7CURRENT=0
8REVISION=1
9AGE=0
10AC_SUBST([LIBUSBIP_VERSION], [$CURRENT:$REVISION:$AGE], [library version])
11
12AC_CONFIG_SRCDIR([src/usbipd.c])
13AC_CONFIG_HEADERS([config.h])
14
15AM_INIT_AUTOMAKE([foreign])
16LT_INIT
17
18# Silent build for automake >= 1.11
19m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
20
21AC_SUBST([EXTRA_CFLAGS], ["-Wall -Werror -Wextra -std=gnu99"])
22
23# Checks for programs.
24AC_PROG_CC
25AC_PROG_INSTALL
26AC_PROG_MAKE_SET
27
28# Checks for header files.
29AC_HEADER_DIRENT
30AC_HEADER_STDC
31AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h dnl
32 string.h sys/socket.h syslog.h unistd.h])
33
34# Checks for typedefs, structures, and compiler characteristics.
35AC_TYPE_INT32_T
36AC_TYPE_SIZE_T
37AC_TYPE_SSIZE_T
38AC_TYPE_UINT16_T
39AC_TYPE_UINT32_T
40AC_TYPE_UINT8_T
41
42# Checks for library functions.
43AC_FUNC_REALLOC
44AC_CHECK_FUNCS([memset mkdir regcomp socket strchr strerror strstr dnl
45 strtoul])
46
47AC_CHECK_HEADER([libudev.h],
48 [AC_CHECK_LIB([udev], [udev_new],
49 [LIBS="$LIBS -ludev"],
50 [AC_MSG_ERROR([Missing udev library!])])],
51 [AC_MSG_ERROR([Missing /usr/include/libudev.h])])
52
53# Checks for libwrap library.
54AC_MSG_CHECKING([whether to use the libwrap (TCP wrappers) library])
55AC_ARG_WITH([tcp-wrappers],
56 [AS_HELP_STRING([--with-tcp-wrappers],
57 [use the libwrap (TCP wrappers) library])],
58 dnl [ACTION-IF-GIVEN]
59 [if test "$withval" = "yes"; then
60 AC_MSG_RESULT([yes])
61 AC_MSG_CHECKING([for hosts_access in -lwrap])
62 saved_LIBS="$LIBS"
63 LIBS="-lwrap $saved_LIBS"
64 AC_TRY_LINK(
65 [int hosts_access(); int allow_severity, deny_severity;],
66 [hosts_access()],
67 [AC_MSG_RESULT([yes]);
68 AC_DEFINE([HAVE_LIBWRAP], [1],
69 [use tcp wrapper]) wrap_LIB="-lwrap"],
70 [AC_MSG_RESULT([not found]); exit 1])
71 else
72 AC_MSG_RESULT([no]);
73 fi],
74 dnl [ACTION-IF-NOT-GIVEN]
75 [AC_MSG_RESULT([(default)])
76 AC_MSG_CHECKING([for hosts_access in -lwrap])
77 saved_LIBS="$LIBS"
78 LIBS="-lwrap $saved_LIBS"
79 AC_TRY_LINK(
80 [int hosts_access(); int allow_severity, deny_severity;],
81 [hosts_access()],
82 [AC_MSG_RESULT([yes]);
83 AC_DEFINE([HAVE_LIBWRAP], [1], [use tcp wrapper])],
84 [AC_MSG_RESULT([no]); LIBS="$saved_LIBS"])])
85
86# Sets directory containing usb.ids.
87AC_ARG_WITH([usbids-dir],
88 [AS_HELP_STRING([--with-usbids-dir=DIR],
89 [where usb.ids is found (default /usr/share/hwdata/)])],
90 [USBIDS_DIR=$withval], [USBIDS_DIR="/usr/share/hwdata/"])
91AC_SUBST([USBIDS_DIR])
92
93# use _FORTIFY_SOURCE
94AC_MSG_CHECKING([whether to use fortify])
95AC_ARG_WITH([fortify],
96 [AS_HELP_STRING([--with-fortify],
97 [use _FORTIFY_SROUCE option when compiling)])],
98 dnl [ACTION-IF-GIVEN]
99 [if test "$withval" = "yes"; then
100 AC_MSG_RESULT([yes])
101 CFLAGS="$CFLAGS -D_FORTIFY_SOURCE -O"
102 else
103 AC_MSG_RESULT([no])
104 CFLAGS="$CFLAGS -U_FORTIFY_SOURCE"
105 fi
106 ],
107 dnl [ACTION-IF-NOT-GIVEN]
108 [AC_MSG_RESULT([default])])
109
110AC_CONFIG_FILES([Makefile libsrc/Makefile src/Makefile])
111AC_OUTPUT
diff --git a/tools/usb/usbip/doc/usbip.8 b/tools/usb/usbip/doc/usbip.8
new file mode 100644
index 000000000000..a6097be25d28
--- /dev/null
+++ b/tools/usb/usbip/doc/usbip.8
@@ -0,0 +1,95 @@
1.TH USBIP "8" "February 2009" "usbip" "System Administration Utilities"
2.SH NAME
3usbip \- manage USB/IP devices
4.SH SYNOPSIS
5.B usbip
6[\fIoptions\fR] <\fIcommand\fR> <\fIargs\fR>
7
8.SH DESCRIPTION
9On a USB/IP server, devices can be listed, bound, and unbound using
10this program. On a USB/IP client, devices exported by USB/IP servers
11can be listed, attached and detached.
12
13.SH OPTIONS
14.HP
15\fB\-\-debug\fR
16.IP
17Print debugging information.
18.PP
19
20.HP
21\fB\-\-log\fR
22.IP
23Log to syslog.
24.PP
25
26.HP
27\fB\-\-tcp-port PORT\fR
28.IP
29Connect to PORT on remote host (used for attach and list --remote).
30.PP
31
32.SH COMMANDS
33.HP
34\fBversion\fR
35.IP
36Show version and exit.
37.PP
38
39.HP
40\fBhelp\fR [\fIcommand\fR]
41.IP
42Print the program help message, or help on a specific command, and
43then exit.
44.PP
45
46.HP
47\fBattach\fR \-\-remote=<\fIhost\fR> \-\-busid=<\fIbus_id\fR>
48.IP
49Attach a remote USB device.
50.PP
51
52.HP
53\fBdetach\fR \-\-port=<\fIport\fR>
54.IP
55Detach an imported USB device.
56.PP
57
58.HP
59\fBbind\fR \-\-busid=<\fIbusid\fR>
60.IP
61Make a device exportable.
62.PP
63
64.HP
65\fBunbind\fR \-\-busid=<\fIbusid\fR>
66.IP
67Stop exporting a device so it can be used by a local driver.
68.PP
69
70.HP
71\fBlist\fR \-\-remote=<\fIhost\fR>
72.IP
73List USB devices exported by a remote host.
74.PP
75
76.HP
77\fBlist\fR \-\-local
78.IP
79List local USB devices.
80.PP
81
82
83.SH EXAMPLES
84
85 client:# usbip list --remote=server
86 - List exportable usb devices on the server.
87
88 client:# usbip attach --remote=server --busid=1-2
89 - Connect the remote USB device.
90
91 client:# usbip detach --port=0
92 - Detach the usb device.
93
94.SH "SEE ALSO"
95\fBusbipd\fP\fB(8)\fB\fP
diff --git a/tools/usb/usbip/doc/usbipd.8 b/tools/usb/usbip/doc/usbipd.8
new file mode 100644
index 000000000000..ac4635db3f03
--- /dev/null
+++ b/tools/usb/usbip/doc/usbipd.8
@@ -0,0 +1,91 @@
1.TH USBIP "8" "February 2009" "usbip" "System Administration Utilities"
2.SH NAME
3usbipd \- USB/IP server daemon
4.SH SYNOPSIS
5.B usbipd
6[\fIoptions\fR]
7
8.SH DESCRIPTION
9.B usbipd
10provides USB/IP clients access to exported USB devices.
11
12Devices have to explicitly be exported using
13.B usbip bind
14before usbipd makes them available to other hosts.
15
16The daemon accepts connections from USB/IP clients
17on TCP port 3240 by default.
18
19.SH OPTIONS
20.HP
21\fB\-4\fR, \fB\-\-ipv4\fR
22.IP
23Bind to IPv4. Default is both.
24.PP
25
26.HP
27\fB\-6\fR, \fB\-\-ipv6\fR
28.IP
29Bind to IPv6. Default is both.
30.PP
31
32.HP
33\fB\-D\fR, \fB\-\-daemon\fR
34.IP
35Run as a daemon process.
36.PP
37
38.HP
39\fB\-d\fR, \fB\-\-debug\fR
40.IP
41Print debugging information.
42.PP
43
44.HP
45\fB\-PFILE\fR, \fB\-\-pid FILE\fR
46.IP
47Write process id to FILE.
48.br
49If no FILE specified, use /var/run/usbipd.pid
50.PP
51
52\fB\-tPORT\fR, \fB\-\-tcp\-port PORT\fR
53.IP
54Listen on TCP/IP port PORT.
55.PP
56
57\fB\-h\fR, \fB\-\-help\fR
58.IP
59Print the program help message and exit.
60.PP
61
62.HP
63\fB\-v\fR, \fB\-\-version\fR
64.IP
65Show version.
66.PP
67
68.SH LIMITATIONS
69
70.B usbipd
71offers no authentication or authorization for USB/IP. Any
72USB/IP client can connect and use exported devices.
73
74.SH EXAMPLES
75
76 server:# modprobe usbip
77
78 server:# usbipd -D
79 - Start usbip daemon.
80
81 server:# usbip list --local
82 - List driver assignments for usb devices.
83
84 server:# usbip bind --busid=1-2
85 - Bind usbip-host.ko to the device of busid 1-2.
86 - A usb device 1-2 is now exportable to other hosts!
87 - Use 'usbip unbind --busid=1-2' when you want to shutdown exporting and use the device locally.
88
89.SH "SEE ALSO"
90\fBusbip\fP\fB(8)\fB\fP
91
diff --git a/tools/usb/usbip/libsrc/Makefile.am b/tools/usb/usbip/libsrc/Makefile.am
new file mode 100644
index 000000000000..7c8f8a4d54e4
--- /dev/null
+++ b/tools/usb/usbip/libsrc/Makefile.am
@@ -0,0 +1,8 @@
1libusbip_la_CPPFLAGS = -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
2libusbip_la_CFLAGS = @EXTRA_CFLAGS@
3libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@
4
5lib_LTLIBRARIES := libusbip.la
6libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \
7 usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h \
8 sysfs_utils.c sysfs_utils.h
diff --git a/tools/usb/usbip/libsrc/list.h b/tools/usb/usbip/libsrc/list.h
new file mode 100644
index 000000000000..8d0c936e184f
--- /dev/null
+++ b/tools/usb/usbip/libsrc/list.h
@@ -0,0 +1,136 @@
1#ifndef _LIST_H
2#define _LIST_H
3
4/* Stripped down implementation of linked list taken
5 * from the Linux Kernel.
6 */
7
8/*
9 * Simple doubly linked list implementation.
10 *
11 * Some of the internal functions ("__xxx") are useful when
12 * manipulating whole lists rather than single entries, as
13 * sometimes we already know the next/prev entries and we can
14 * generate better code by using them directly rather than
15 * using the generic single-entry routines.
16 */
17
18struct list_head {
19 struct list_head *next, *prev;
20};
21
22#define LIST_HEAD_INIT(name) { &(name), &(name) }
23
24#define LIST_HEAD(name) \
25 struct list_head name = LIST_HEAD_INIT(name)
26
27static inline void INIT_LIST_HEAD(struct list_head *list)
28{
29 list->next = list;
30 list->prev = list;
31}
32
33/*
34 * Insert a new entry between two known consecutive entries.
35 *
36 * This is only for internal list manipulation where we know
37 * the prev/next entries already!
38 */
39static inline void __list_add(struct list_head *new,
40 struct list_head *prev,
41 struct list_head *next)
42{
43 next->prev = new;
44 new->next = next;
45 new->prev = prev;
46 prev->next = new;
47}
48
49/**
50 * list_add - add a new entry
51 * @new: new entry to be added
52 * @head: list head to add it after
53 *
54 * Insert a new entry after the specified head.
55 * This is good for implementing stacks.
56 */
57static inline void list_add(struct list_head *new, struct list_head *head)
58{
59 __list_add(new, head, head->next);
60}
61
62/*
63 * Delete a list entry by making the prev/next entries
64 * point to each other.
65 *
66 * This is only for internal list manipulation where we know
67 * the prev/next entries already!
68 */
69static inline void __list_del(struct list_head * prev, struct list_head * next)
70{
71 next->prev = prev;
72 prev->next = next;
73}
74
75#define POISON_POINTER_DELTA 0
76#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
77#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
78
79/**
80 * list_del - deletes entry from list.
81 * @entry: the element to delete from the list.
82 * Note: list_empty() on entry does not return true after this, the entry is
83 * in an undefined state.
84 */
85static inline void __list_del_entry(struct list_head *entry)
86{
87 __list_del(entry->prev, entry->next);
88}
89
90static inline void list_del(struct list_head *entry)
91{
92 __list_del(entry->prev, entry->next);
93 entry->next = LIST_POISON1;
94 entry->prev = LIST_POISON2;
95}
96
97/**
98 * list_entry - get the struct for this entry
99 * @ptr: the &struct list_head pointer.
100 * @type: the type of the struct this is embedded in.
101 * @member: the name of the list_struct within the struct.
102 */
103#define list_entry(ptr, type, member) \
104 container_of(ptr, type, member)
105/**
106 * list_for_each - iterate over a list
107 * @pos: the &struct list_head to use as a loop cursor.
108 * @head: the head for your list.
109 */
110#define list_for_each(pos, head) \
111 for (pos = (head)->next; pos != (head); pos = pos->next)
112
113/**
114 * list_for_each_safe - iterate over a list safe against removal of list entry
115 * @pos: the &struct list_head to use as a loop cursor.
116 * @n: another &struct list_head to use as temporary storage
117 * @head: the head for your list.
118 */
119#define list_for_each_safe(pos, n, head) \
120 for (pos = (head)->next, n = pos->next; pos != (head); \
121 pos = n, n = pos->next)
122
123#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
124
125/**
126 * container_of - cast a member of a structure out to the containing structure
127 * @ptr: the pointer to the member.
128 * @type: the type of the container struct this is embedded in.
129 * @member: the name of the member within the struct.
130 *
131 */
132#define container_of(ptr, type, member) ({ \
133 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
134 (type *)( (char *)__mptr - offsetof(type,member) );})
135
136#endif
diff --git a/tools/usb/usbip/libsrc/names.c b/tools/usb/usbip/libsrc/names.c
new file mode 100644
index 000000000000..81ff8522405c
--- /dev/null
+++ b/tools/usb/usbip/libsrc/names.c
@@ -0,0 +1,504 @@
1/*
2 * names.c -- USB name database manipulation routines
3 *
4 * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 *
21 *
22 *
23 *
24 * Copyright (C) 2005 Takahiro Hirofuchi
25 * - names_deinit() is added.
26 *
27 */
28
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <dirent.h>
33#include <string.h>
34#include <errno.h>
35#include <stdlib.h>
36#include <unistd.h>
37#include <stdio.h>
38#include <ctype.h>
39
40#include "names.h"
41#include "usbip_common.h"
42
43struct vendor {
44 struct vendor *next;
45 u_int16_t vendorid;
46 char name[1];
47};
48
49struct product {
50 struct product *next;
51 u_int16_t vendorid, productid;
52 char name[1];
53};
54
55struct class {
56 struct class *next;
57 u_int8_t classid;
58 char name[1];
59};
60
61struct subclass {
62 struct subclass *next;
63 u_int8_t classid, subclassid;
64 char name[1];
65};
66
67struct protocol {
68 struct protocol *next;
69 u_int8_t classid, subclassid, protocolid;
70 char name[1];
71};
72
73struct genericstrtable {
74 struct genericstrtable *next;
75 unsigned int num;
76 char name[1];
77};
78
79
80#define HASH1 0x10
81#define HASH2 0x02
82#define HASHSZ 16
83
84static unsigned int hashnum(unsigned int num)
85{
86 unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
87
88 for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
89 if (num & mask1)
90 num ^= mask2;
91 return num & (HASHSZ-1);
92}
93
94
95static struct vendor *vendors[HASHSZ] = { NULL, };
96static struct product *products[HASHSZ] = { NULL, };
97static struct class *classes[HASHSZ] = { NULL, };
98static struct subclass *subclasses[HASHSZ] = { NULL, };
99static struct protocol *protocols[HASHSZ] = { NULL, };
100
101const char *names_vendor(u_int16_t vendorid)
102{
103 struct vendor *v;
104
105 v = vendors[hashnum(vendorid)];
106 for (; v; v = v->next)
107 if (v->vendorid == vendorid)
108 return v->name;
109 return NULL;
110}
111
112const char *names_product(u_int16_t vendorid, u_int16_t productid)
113{
114 struct product *p;
115
116 p = products[hashnum((vendorid << 16) | productid)];
117 for (; p; p = p->next)
118 if (p->vendorid == vendorid && p->productid == productid)
119 return p->name;
120 return NULL;
121}
122
123const char *names_class(u_int8_t classid)
124{
125 struct class *c;
126
127 c = classes[hashnum(classid)];
128 for (; c; c = c->next)
129 if (c->classid == classid)
130 return c->name;
131 return NULL;
132}
133
134const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
135{
136 struct subclass *s;
137
138 s = subclasses[hashnum((classid << 8) | subclassid)];
139 for (; s; s = s->next)
140 if (s->classid == classid && s->subclassid == subclassid)
141 return s->name;
142 return NULL;
143}
144
145const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
146 u_int8_t protocolid)
147{
148 struct protocol *p;
149
150 p = protocols[hashnum((classid << 16) | (subclassid << 8)
151 | protocolid)];
152 for (; p; p = p->next)
153 if (p->classid == classid && p->subclassid == subclassid &&
154 p->protocolid == protocolid)
155 return p->name;
156 return NULL;
157}
158
159/* add a cleanup function by takahiro */
160struct pool {
161 struct pool *next;
162 void *mem;
163};
164
165static struct pool *pool_head;
166
167static void *my_malloc(size_t size)
168{
169 struct pool *p;
170
171 p = calloc(1, sizeof(struct pool));
172 if (!p)
173 return NULL;
174
175 p->mem = calloc(1, size);
176 if (!p->mem) {
177 free(p);
178 return NULL;
179 }
180
181 p->next = pool_head;
182 pool_head = p;
183
184 return p->mem;
185}
186
187void names_free(void)
188{
189 struct pool *pool;
190
191 if (!pool_head)
192 return;
193
194 for (pool = pool_head; pool != NULL; ) {
195 struct pool *tmp;
196
197 if (pool->mem)
198 free(pool->mem);
199
200 tmp = pool;
201 pool = pool->next;
202 free(tmp);
203 }
204}
205
206static int new_vendor(const char *name, u_int16_t vendorid)
207{
208 struct vendor *v;
209 unsigned int h = hashnum(vendorid);
210
211 v = vendors[h];
212 for (; v; v = v->next)
213 if (v->vendorid == vendorid)
214 return -1;
215 v = my_malloc(sizeof(struct vendor) + strlen(name));
216 if (!v)
217 return -1;
218 strcpy(v->name, name);
219 v->vendorid = vendorid;
220 v->next = vendors[h];
221 vendors[h] = v;
222 return 0;
223}
224
225static int new_product(const char *name, u_int16_t vendorid,
226 u_int16_t productid)
227{
228 struct product *p;
229 unsigned int h = hashnum((vendorid << 16) | productid);
230
231 p = products[h];
232 for (; p; p = p->next)
233 if (p->vendorid == vendorid && p->productid == productid)
234 return -1;
235 p = my_malloc(sizeof(struct product) + strlen(name));
236 if (!p)
237 return -1;
238 strcpy(p->name, name);
239 p->vendorid = vendorid;
240 p->productid = productid;
241 p->next = products[h];
242 products[h] = p;
243 return 0;
244}
245
246static int new_class(const char *name, u_int8_t classid)
247{
248 struct class *c;
249 unsigned int h = hashnum(classid);
250
251 c = classes[h];
252 for (; c; c = c->next)
253 if (c->classid == classid)
254 return -1;
255 c = my_malloc(sizeof(struct class) + strlen(name));
256 if (!c)
257 return -1;
258 strcpy(c->name, name);
259 c->classid = classid;
260 c->next = classes[h];
261 classes[h] = c;
262 return 0;
263}
264
265static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
266{
267 struct subclass *s;
268 unsigned int h = hashnum((classid << 8) | subclassid);
269
270 s = subclasses[h];
271 for (; s; s = s->next)
272 if (s->classid == classid && s->subclassid == subclassid)
273 return -1;
274 s = my_malloc(sizeof(struct subclass) + strlen(name));
275 if (!s)
276 return -1;
277 strcpy(s->name, name);
278 s->classid = classid;
279 s->subclassid = subclassid;
280 s->next = subclasses[h];
281 subclasses[h] = s;
282 return 0;
283}
284
285static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
286 u_int8_t protocolid)
287{
288 struct protocol *p;
289 unsigned int h = hashnum((classid << 16) | (subclassid << 8)
290 | protocolid);
291
292 p = protocols[h];
293 for (; p; p = p->next)
294 if (p->classid == classid && p->subclassid == subclassid
295 && p->protocolid == protocolid)
296 return -1;
297 p = my_malloc(sizeof(struct protocol) + strlen(name));
298 if (!p)
299 return -1;
300 strcpy(p->name, name);
301 p->classid = classid;
302 p->subclassid = subclassid;
303 p->protocolid = protocolid;
304 p->next = protocols[h];
305 protocols[h] = p;
306 return 0;
307}
308
309static void parse(FILE *f)
310{
311 char buf[512], *cp;
312 unsigned int linectr = 0;
313 int lastvendor = -1;
314 int lastclass = -1;
315 int lastsubclass = -1;
316 int lasthut = -1;
317 int lastlang = -1;
318 unsigned int u;
319
320 while (fgets(buf, sizeof(buf), f)) {
321 linectr++;
322 /* remove line ends */
323 cp = strchr(buf, '\r');
324 if (cp)
325 *cp = 0;
326 cp = strchr(buf, '\n');
327 if (cp)
328 *cp = 0;
329 if (buf[0] == '#' || !buf[0])
330 continue;
331 cp = buf;
332 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
333 buf[3] == 'S' && buf[4] == 'D' &&
334 buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
335 buf[7] == ' ') {
336 continue;
337 }
338 if (buf[0] == 'P' && buf[1] == 'H' &&
339 buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
340 continue;
341 }
342 if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
343 buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
344 continue;
345 }
346 if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
347 lasthut = lastclass = lastvendor = lastsubclass = -1;
348 /*
349 * set 1 as pseudo-id to indicate that the parser is
350 * in a `L' section.
351 */
352 lastlang = 1;
353 continue;
354 }
355 if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
356 /* class spec */
357 cp = buf+2;
358 while (isspace(*cp))
359 cp++;
360 if (!isxdigit(*cp)) {
361 err("Invalid class spec at line %u", linectr);
362 continue;
363 }
364 u = strtoul(cp, &cp, 16);
365 while (isspace(*cp))
366 cp++;
367 if (!*cp) {
368 err("Invalid class spec at line %u", linectr);
369 continue;
370 }
371 if (new_class(cp, u))
372 err("Duplicate class spec at line %u class %04x %s",
373 linectr, u, cp);
374 dbg("line %5u class %02x %s", linectr, u, cp);
375 lasthut = lastlang = lastvendor = lastsubclass = -1;
376 lastclass = u;
377 continue;
378 }
379 if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
380 /* audio terminal type spec */
381 continue;
382 }
383 if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
384 && isspace(buf[3])) {
385 /* HID Descriptor bCountryCode */
386 continue;
387 }
388 if (isxdigit(*cp)) {
389 /* vendor */
390 u = strtoul(cp, &cp, 16);
391 while (isspace(*cp))
392 cp++;
393 if (!*cp) {
394 err("Invalid vendor spec at line %u", linectr);
395 continue;
396 }
397 if (new_vendor(cp, u))
398 err("Duplicate vendor spec at line %u vendor %04x %s",
399 linectr, u, cp);
400 dbg("line %5u vendor %04x %s", linectr, u, cp);
401 lastvendor = u;
402 lasthut = lastlang = lastclass = lastsubclass = -1;
403 continue;
404 }
405 if (buf[0] == '\t' && isxdigit(buf[1])) {
406 /* product or subclass spec */
407 u = strtoul(buf+1, &cp, 16);
408 while (isspace(*cp))
409 cp++;
410 if (!*cp) {
411 err("Invalid product/subclass spec at line %u",
412 linectr);
413 continue;
414 }
415 if (lastvendor != -1) {
416 if (new_product(cp, lastvendor, u))
417 err("Duplicate product spec at line %u product %04x:%04x %s",
418 linectr, lastvendor, u, cp);
419 dbg("line %5u product %04x:%04x %s", linectr,
420 lastvendor, u, cp);
421 continue;
422 }
423 if (lastclass != -1) {
424 if (new_subclass(cp, lastclass, u))
425 err("Duplicate subclass spec at line %u class %02x:%02x %s",
426 linectr, lastclass, u, cp);
427 dbg("line %5u subclass %02x:%02x %s", linectr,
428 lastclass, u, cp);
429 lastsubclass = u;
430 continue;
431 }
432 if (lasthut != -1) {
433 /* do not store hut */
434 continue;
435 }
436 if (lastlang != -1) {
437 /* do not store langid */
438 continue;
439 }
440 err("Product/Subclass spec without prior Vendor/Class spec at line %u",
441 linectr);
442 continue;
443 }
444 if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
445 /* protocol spec */
446 u = strtoul(buf+2, &cp, 16);
447 while (isspace(*cp))
448 cp++;
449 if (!*cp) {
450 err("Invalid protocol spec at line %u",
451 linectr);
452 continue;
453 }
454 if (lastclass != -1 && lastsubclass != -1) {
455 if (new_protocol(cp, lastclass, lastsubclass,
456 u))
457 err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
458 linectr, lastclass, lastsubclass,
459 u, cp);
460 dbg("line %5u protocol %02x:%02x:%02x %s",
461 linectr, lastclass, lastsubclass, u, cp);
462 continue;
463 }
464 err("Protocol spec without prior Class and Subclass spec at line %u",
465 linectr);
466 continue;
467 }
468 if (buf[0] == 'H' && buf[1] == 'I' &&
469 buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
470 continue;
471 }
472 if (buf[0] == 'H' && buf[1] == 'U' &&
473 buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
474 lastlang = lastclass = lastvendor = lastsubclass = -1;
475 /*
476 * set 1 as pseudo-id to indicate that the parser is
477 * in a `HUT' section.
478 */
479 lasthut = 1;
480 continue;
481 }
482 if (buf[0] == 'R' && buf[1] == ' ')
483 continue;
484
485 if (buf[0] == 'V' && buf[1] == 'T')
486 continue;
487
488 err("Unknown line at line %u", linectr);
489 }
490}
491
492
493int names_init(char *n)
494{
495 FILE *f;
496
497 f = fopen(n, "r");
498 if (!f)
499 return errno;
500
501 parse(f);
502 fclose(f);
503 return 0;
504}
diff --git a/tools/usb/usbip/libsrc/names.h b/tools/usb/usbip/libsrc/names.h
new file mode 100644
index 000000000000..680926512de2
--- /dev/null
+++ b/tools/usb/usbip/libsrc/names.h
@@ -0,0 +1,41 @@
1/*
2 * names.h -- USB name database manipulation routines
3 *
4 * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 *
21 *
22 * Copyright (C) 2005 Takahiro Hirofuchi
23 * - names_free() is added.
24 */
25
26#ifndef _NAMES_H
27#define _NAMES_H
28
29#include <sys/types.h>
30
31/* used by usbip_common.c */
32extern const char *names_vendor(u_int16_t vendorid);
33extern const char *names_product(u_int16_t vendorid, u_int16_t productid);
34extern const char *names_class(u_int8_t classid);
35extern const char *names_subclass(u_int8_t classid, u_int8_t subclassid);
36extern const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
37 u_int8_t protocolid);
38extern int names_init(char *n);
39extern void names_free(void);
40
41#endif /* _NAMES_H */
diff --git a/tools/usb/usbip/libsrc/sysfs_utils.c b/tools/usb/usbip/libsrc/sysfs_utils.c
new file mode 100644
index 000000000000..36ac88ece0b8
--- /dev/null
+++ b/tools/usb/usbip/libsrc/sysfs_utils.c
@@ -0,0 +1,31 @@
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <fcntl.h>
4#include <errno.h>
5
6#include "sysfs_utils.h"
7#include "usbip_common.h"
8
9int write_sysfs_attribute(const char *attr_path, const char *new_value,
10 size_t len)
11{
12 int fd;
13 int length;
14
15 fd = open(attr_path, O_WRONLY);
16 if (fd < 0) {
17 dbg("error opening attribute %s", attr_path);
18 return -1;
19 }
20
21 length = write(fd, new_value, len);
22 if (length < 0) {
23 dbg("error writing to attribute %s", attr_path);
24 close(fd);
25 return -1;
26 }
27
28 close(fd);
29
30 return 0;
31}
diff --git a/tools/usb/usbip/libsrc/sysfs_utils.h b/tools/usb/usbip/libsrc/sysfs_utils.h
new file mode 100644
index 000000000000..32ac1d105d18
--- /dev/null
+++ b/tools/usb/usbip/libsrc/sysfs_utils.h
@@ -0,0 +1,8 @@
1
2#ifndef __SYSFS_UTILS_H
3#define __SYSFS_UTILS_H
4
5int write_sysfs_attribute(const char *attr_path, const char *new_value,
6 size_t len);
7
8#endif
diff --git a/tools/usb/usbip/libsrc/usbip_common.c b/tools/usb/usbip/libsrc/usbip_common.c
new file mode 100644
index 000000000000..ac73710473de
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_common.c
@@ -0,0 +1,285 @@
1/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */
4
5#include <libudev.h>
6#include "usbip_common.h"
7#include "names.h"
8
9#undef PROGNAME
10#define PROGNAME "libusbip"
11
12int usbip_use_syslog;
13int usbip_use_stderr;
14int usbip_use_debug;
15
16extern struct udev *udev_context;
17
18struct speed_string {
19 int num;
20 char *speed;
21 char *desc;
22};
23
24static const struct speed_string speed_strings[] = {
25 { USB_SPEED_UNKNOWN, "unknown", "Unknown Speed"},
26 { USB_SPEED_LOW, "1.5", "Low Speed(1.5Mbps)" },
27 { USB_SPEED_FULL, "12", "Full Speed(12Mbps)" },
28 { USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
29 { USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
30 { USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
31 { 0, NULL, NULL }
32};
33
34struct portst_string {
35 int num;
36 char *desc;
37};
38
39static struct portst_string portst_strings[] = {
40 { SDEV_ST_AVAILABLE, "Device Available" },
41 { SDEV_ST_USED, "Device in Use" },
42 { SDEV_ST_ERROR, "Device Error"},
43 { VDEV_ST_NULL, "Port Available"},
44 { VDEV_ST_NOTASSIGNED, "Port Initializing"},
45 { VDEV_ST_USED, "Port in Use"},
46 { VDEV_ST_ERROR, "Port Error"},
47 { 0, NULL}
48};
49
50const char *usbip_status_string(int32_t status)
51{
52 for (int i = 0; portst_strings[i].desc != NULL; i++)
53 if (portst_strings[i].num == status)
54 return portst_strings[i].desc;
55
56 return "Unknown Status";
57}
58
59const char *usbip_speed_string(int num)
60{
61 for (int i = 0; speed_strings[i].speed != NULL; i++)
62 if (speed_strings[i].num == num)
63 return speed_strings[i].desc;
64
65 return "Unknown Speed";
66}
67
68
69#define DBG_UDEV_INTEGER(name)\
70 dbg("%-20s = %x", to_string(name), (int) udev->name)
71
72#define DBG_UINF_INTEGER(name)\
73 dbg("%-20s = %x", to_string(name), (int) uinf->name)
74
75void dump_usb_interface(struct usbip_usb_interface *uinf)
76{
77 char buff[100];
78
79 usbip_names_get_class(buff, sizeof(buff),
80 uinf->bInterfaceClass,
81 uinf->bInterfaceSubClass,
82 uinf->bInterfaceProtocol);
83 dbg("%-20s = %s", "Interface(C/SC/P)", buff);
84}
85
86void dump_usb_device(struct usbip_usb_device *udev)
87{
88 char buff[100];
89
90 dbg("%-20s = %s", "path", udev->path);
91 dbg("%-20s = %s", "busid", udev->busid);
92
93 usbip_names_get_class(buff, sizeof(buff),
94 udev->bDeviceClass,
95 udev->bDeviceSubClass,
96 udev->bDeviceProtocol);
97 dbg("%-20s = %s", "Device(C/SC/P)", buff);
98
99 DBG_UDEV_INTEGER(bcdDevice);
100
101 usbip_names_get_product(buff, sizeof(buff),
102 udev->idVendor,
103 udev->idProduct);
104 dbg("%-20s = %s", "Vendor/Product", buff);
105
106 DBG_UDEV_INTEGER(bNumConfigurations);
107 DBG_UDEV_INTEGER(bNumInterfaces);
108
109 dbg("%-20s = %s", "speed",
110 usbip_speed_string(udev->speed));
111
112 DBG_UDEV_INTEGER(busnum);
113 DBG_UDEV_INTEGER(devnum);
114}
115
116
117int read_attr_value(struct udev_device *dev, const char *name,
118 const char *format)
119{
120 const char *attr;
121 int num = 0;
122 int ret;
123
124 attr = udev_device_get_sysattr_value(dev, name);
125 if (!attr) {
126 err("udev_device_get_sysattr_value failed");
127 goto err;
128 }
129
130 /* The client chooses the device configuration
131 * when attaching it so right after being bound
132 * to usbip-host on the server the device will
133 * have no configuration.
134 * Therefore, attributes such as bConfigurationValue
135 * and bNumInterfaces will not exist and sscanf will
136 * fail. Check for these cases and don't treat them
137 * as errors.
138 */
139
140 ret = sscanf(attr, format, &num);
141 if (ret < 1) {
142 if (strcmp(name, "bConfigurationValue") &&
143 strcmp(name, "bNumInterfaces")) {
144 err("sscanf failed for attribute %s", name);
145 goto err;
146 }
147 }
148
149err:
150
151 return num;
152}
153
154
155int read_attr_speed(struct udev_device *dev)
156{
157 const char *speed;
158
159 speed = udev_device_get_sysattr_value(dev, "speed");
160 if (!speed) {
161 err("udev_device_get_sysattr_value failed");
162 goto err;
163 }
164
165 for (int i = 0; speed_strings[i].speed != NULL; i++) {
166 if (!strcmp(speed, speed_strings[i].speed))
167 return speed_strings[i].num;
168 }
169
170err:
171
172 return USB_SPEED_UNKNOWN;
173}
174
175#define READ_ATTR(object, type, dev, name, format) \
176 do { \
177 (object)->name = (type) read_attr_value(dev, to_string(name), \
178 format); \
179 } while (0)
180
181
182int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev)
183{
184 uint32_t busnum, devnum;
185 const char *path, *name;
186
187 READ_ATTR(udev, uint8_t, sdev, bDeviceClass, "%02x\n");
188 READ_ATTR(udev, uint8_t, sdev, bDeviceSubClass, "%02x\n");
189 READ_ATTR(udev, uint8_t, sdev, bDeviceProtocol, "%02x\n");
190
191 READ_ATTR(udev, uint16_t, sdev, idVendor, "%04x\n");
192 READ_ATTR(udev, uint16_t, sdev, idProduct, "%04x\n");
193 READ_ATTR(udev, uint16_t, sdev, bcdDevice, "%04x\n");
194
195 READ_ATTR(udev, uint8_t, sdev, bConfigurationValue, "%02x\n");
196 READ_ATTR(udev, uint8_t, sdev, bNumConfigurations, "%02x\n");
197 READ_ATTR(udev, uint8_t, sdev, bNumInterfaces, "%02x\n");
198
199 READ_ATTR(udev, uint8_t, sdev, devnum, "%d\n");
200 udev->speed = read_attr_speed(sdev);
201
202 path = udev_device_get_syspath(sdev);
203 name = udev_device_get_sysname(sdev);
204
205 strncpy(udev->path, path, SYSFS_PATH_MAX);
206 strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE);
207
208 sscanf(name, "%u-%u", &busnum, &devnum);
209 udev->busnum = busnum;
210
211 return 0;
212}
213
214int read_usb_interface(struct usbip_usb_device *udev, int i,
215 struct usbip_usb_interface *uinf)
216{
217 char busid[SYSFS_BUS_ID_SIZE];
218 struct udev_device *sif;
219
220 sprintf(busid, "%s:%d.%d", udev->busid, udev->bConfigurationValue, i);
221
222 sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
223 if (!sif) {
224 err("udev_device_new_from_subsystem_sysname %s failed", busid);
225 return -1;
226 }
227
228 READ_ATTR(uinf, uint8_t, sif, bInterfaceClass, "%02x\n");
229 READ_ATTR(uinf, uint8_t, sif, bInterfaceSubClass, "%02x\n");
230 READ_ATTR(uinf, uint8_t, sif, bInterfaceProtocol, "%02x\n");
231
232 return 0;
233}
234
235int usbip_names_init(char *f)
236{
237 return names_init(f);
238}
239
240void usbip_names_free(void)
241{
242 names_free();
243}
244
245void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
246 uint16_t product)
247{
248 const char *prod, *vend;
249
250 prod = names_product(vendor, product);
251 if (!prod)
252 prod = "unknown product";
253
254
255 vend = names_vendor(vendor);
256 if (!vend)
257 vend = "unknown vendor";
258
259 snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
260}
261
262void usbip_names_get_class(char *buff, size_t size, uint8_t class,
263 uint8_t subclass, uint8_t protocol)
264{
265 const char *c, *s, *p;
266
267 if (class == 0 && subclass == 0 && protocol == 0) {
268 snprintf(buff, size, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass, protocol);
269 return;
270 }
271
272 p = names_protocol(class, subclass, protocol);
273 if (!p)
274 p = "unknown protocol";
275
276 s = names_subclass(class, subclass);
277 if (!s)
278 s = "unknown subclass";
279
280 c = names_class(class);
281 if (!c)
282 c = "unknown class";
283
284 snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
285}
diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h
new file mode 100644
index 000000000000..15fe792e1e96
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_common.h
@@ -0,0 +1,137 @@
1/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */
4
5#ifndef __USBIP_COMMON_H
6#define __USBIP_COMMON_H
7
8#include <libudev.h>
9
10#include <stdint.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15#include <syslog.h>
16#include <unistd.h>
17#include <linux/usb/ch9.h>
18#include <linux/usbip.h>
19
20#ifndef USBIDS_FILE
21#define USBIDS_FILE "/usr/share/hwdata/usb.ids"
22#endif
23
24#ifndef VHCI_STATE_PATH
25#define VHCI_STATE_PATH "/var/run/vhci_hcd"
26#endif
27
28/* kernel module names */
29#define USBIP_CORE_MOD_NAME "usbip-core"
30#define USBIP_HOST_DRV_NAME "usbip-host"
31#define USBIP_VHCI_DRV_NAME "vhci_hcd"
32
33/* sysfs constants */
34#define SYSFS_MNT_PATH "/sys"
35#define SYSFS_BUS_NAME "bus"
36#define SYSFS_BUS_TYPE "usb"
37#define SYSFS_DRIVERS_NAME "drivers"
38
39#define SYSFS_PATH_MAX 256
40#define SYSFS_BUS_ID_SIZE 32
41
42extern int usbip_use_syslog;
43extern int usbip_use_stderr;
44extern int usbip_use_debug ;
45
46#define PROGNAME "usbip"
47
48#define pr_fmt(fmt) "%s: %s: " fmt "\n", PROGNAME
49#define dbg_fmt(fmt) pr_fmt("%s:%d:[%s] " fmt), "debug", \
50 __FILE__, __LINE__, __func__
51
52#define err(fmt, args...) \
53 do { \
54 if (usbip_use_syslog) { \
55 syslog(LOG_ERR, pr_fmt(fmt), "error", ##args); \
56 } \
57 if (usbip_use_stderr) { \
58 fprintf(stderr, pr_fmt(fmt), "error", ##args); \
59 } \
60 } while (0)
61
62#define info(fmt, args...) \
63 do { \
64 if (usbip_use_syslog) { \
65 syslog(LOG_INFO, pr_fmt(fmt), "info", ##args); \
66 } \
67 if (usbip_use_stderr) { \
68 fprintf(stderr, pr_fmt(fmt), "info", ##args); \
69 } \
70 } while (0)
71
72#define dbg(fmt, args...) \
73 do { \
74 if (usbip_use_debug) { \
75 if (usbip_use_syslog) { \
76 syslog(LOG_DEBUG, dbg_fmt(fmt), ##args); \
77 } \
78 if (usbip_use_stderr) { \
79 fprintf(stderr, dbg_fmt(fmt), ##args); \
80 } \
81 } \
82 } while (0)
83
84#define BUG() \
85 do { \
86 err("sorry, it's a bug!"); \
87 abort(); \
88 } while (0)
89
90struct usbip_usb_interface {
91 uint8_t bInterfaceClass;
92 uint8_t bInterfaceSubClass;
93 uint8_t bInterfaceProtocol;
94 uint8_t padding; /* alignment */
95} __attribute__((packed));
96
97struct usbip_usb_device {
98 char path[SYSFS_PATH_MAX];
99 char busid[SYSFS_BUS_ID_SIZE];
100
101 uint32_t busnum;
102 uint32_t devnum;
103 uint32_t speed;
104
105 uint16_t idVendor;
106 uint16_t idProduct;
107 uint16_t bcdDevice;
108
109 uint8_t bDeviceClass;
110 uint8_t bDeviceSubClass;
111 uint8_t bDeviceProtocol;
112 uint8_t bConfigurationValue;
113 uint8_t bNumConfigurations;
114 uint8_t bNumInterfaces;
115} __attribute__((packed));
116
117#define to_string(s) #s
118
119void dump_usb_interface(struct usbip_usb_interface *);
120void dump_usb_device(struct usbip_usb_device *);
121int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev);
122int read_attr_value(struct udev_device *dev, const char *name,
123 const char *format);
124int read_usb_interface(struct usbip_usb_device *udev, int i,
125 struct usbip_usb_interface *uinf);
126
127const char *usbip_speed_string(int num);
128const char *usbip_status_string(int32_t status);
129
130int usbip_names_init(char *);
131void usbip_names_free(void);
132void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
133 uint16_t product);
134void usbip_names_get_class(char *buff, size_t size, uint8_t class,
135 uint8_t subclass, uint8_t protocol);
136
137#endif /* __USBIP_COMMON_H */
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.c b/tools/usb/usbip/libsrc/usbip_host_driver.c
new file mode 100644
index 000000000000..bef08d5c44e8
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_host_driver.c
@@ -0,0 +1,280 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22
23#include <errno.h>
24#include <unistd.h>
25
26#include <libudev.h>
27
28#include "usbip_common.h"
29#include "usbip_host_driver.h"
30#include "list.h"
31#include "sysfs_utils.h"
32
33#undef PROGNAME
34#define PROGNAME "libusbip"
35
36struct usbip_host_driver *host_driver;
37struct udev *udev_context;
38
39static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
40{
41 char status_attr_path[SYSFS_PATH_MAX];
42 int fd;
43 int length;
44 char status;
45 int value = 0;
46
47 snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
48 udev->path);
49
50 fd = open(status_attr_path, O_RDONLY);
51 if (fd < 0) {
52 err("error opening attribute %s", status_attr_path);
53 return -1;
54 }
55
56 length = read(fd, &status, 1);
57 if (length < 0) {
58 err("error reading attribute %s", status_attr_path);
59 close(fd);
60 return -1;
61 }
62
63 value = atoi(&status);
64
65 return value;
66}
67
68static
69struct usbip_exported_device *usbip_exported_device_new(const char *sdevpath)
70{
71 struct usbip_exported_device *edev = NULL;
72 struct usbip_exported_device *edev_old;
73 size_t size;
74 int i;
75
76 edev = calloc(1, sizeof(struct usbip_exported_device));
77
78 edev->sudev = udev_device_new_from_syspath(udev_context, sdevpath);
79 if (!edev->sudev) {
80 err("udev_device_new_from_syspath: %s", sdevpath);
81 goto err;
82 }
83
84 read_usb_device(edev->sudev, &edev->udev);
85
86 edev->status = read_attr_usbip_status(&edev->udev);
87 if (edev->status < 0)
88 goto err;
89
90 /* reallocate buffer to include usb interface data */
91 size = sizeof(struct usbip_exported_device) +
92 edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
93
94 edev_old = edev;
95 edev = realloc(edev, size);
96 if (!edev) {
97 edev = edev_old;
98 dbg("realloc failed");
99 goto err;
100 }
101
102 for (i = 0; i < edev->udev.bNumInterfaces; i++)
103 read_usb_interface(&edev->udev, i, &edev->uinf[i]);
104
105 return edev;
106err:
107 if (edev->sudev)
108 udev_device_unref(edev->sudev);
109 if (edev)
110 free(edev);
111
112 return NULL;
113}
114
115static int refresh_exported_devices(void)
116{
117 struct usbip_exported_device *edev;
118 struct udev_enumerate *enumerate;
119 struct udev_list_entry *devices, *dev_list_entry;
120 struct udev_device *dev;
121 const char *path;
122 const char *driver;
123
124 enumerate = udev_enumerate_new(udev_context);
125 udev_enumerate_add_match_subsystem(enumerate, "usb");
126 udev_enumerate_scan_devices(enumerate);
127
128 devices = udev_enumerate_get_list_entry(enumerate);
129
130 udev_list_entry_foreach(dev_list_entry, devices) {
131 path = udev_list_entry_get_name(dev_list_entry);
132 dev = udev_device_new_from_syspath(udev_context, path);
133 if (dev == NULL)
134 continue;
135
136 /* Check whether device uses usbip-host driver. */
137 driver = udev_device_get_driver(dev);
138 if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
139 edev = usbip_exported_device_new(path);
140 if (!edev) {
141 dbg("usbip_exported_device_new failed");
142 continue;
143 }
144
145 list_add(&edev->node, &host_driver->edev_list);
146 host_driver->ndevs++;
147 }
148 }
149
150 return 0;
151}
152
153static void usbip_exported_device_destroy(void)
154{
155 struct list_head *i, *tmp;
156 struct usbip_exported_device *edev;
157
158 list_for_each_safe(i, tmp, &host_driver->edev_list) {
159 edev = list_entry(i, struct usbip_exported_device, node);
160 list_del(i);
161 free(edev);
162 }
163}
164
165int usbip_host_driver_open(void)
166{
167 int rc;
168
169 udev_context = udev_new();
170 if (!udev_context) {
171 err("udev_new failed");
172 return -1;
173 }
174
175 host_driver = calloc(1, sizeof(*host_driver));
176
177 host_driver->ndevs = 0;
178 INIT_LIST_HEAD(&host_driver->edev_list);
179
180 rc = refresh_exported_devices();
181 if (rc < 0)
182 goto err_free_host_driver;
183
184 return 0;
185
186err_free_host_driver:
187 free(host_driver);
188 host_driver = NULL;
189
190 udev_unref(udev_context);
191
192 return -1;
193}
194
195void usbip_host_driver_close(void)
196{
197 if (!host_driver)
198 return;
199
200 usbip_exported_device_destroy();
201
202 free(host_driver);
203 host_driver = NULL;
204
205 udev_unref(udev_context);
206}
207
208int usbip_host_refresh_device_list(void)
209{
210 int rc;
211
212 usbip_exported_device_destroy();
213
214 host_driver->ndevs = 0;
215 INIT_LIST_HEAD(&host_driver->edev_list);
216
217 rc = refresh_exported_devices();
218 if (rc < 0)
219 return -1;
220
221 return 0;
222}
223
224int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd)
225{
226 char attr_name[] = "usbip_sockfd";
227 char sockfd_attr_path[SYSFS_PATH_MAX];
228 char sockfd_buff[30];
229 int ret;
230
231 if (edev->status != SDEV_ST_AVAILABLE) {
232 dbg("device not available: %s", edev->udev.busid);
233 switch (edev->status) {
234 case SDEV_ST_ERROR:
235 dbg("status SDEV_ST_ERROR");
236 break;
237 case SDEV_ST_USED:
238 dbg("status SDEV_ST_USED");
239 break;
240 default:
241 dbg("status unknown: 0x%x", edev->status);
242 }
243 return -1;
244 }
245
246 /* only the first interface is true */
247 snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
248 edev->udev.path, attr_name);
249
250 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
251
252 ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
253 strlen(sockfd_buff));
254 if (ret < 0) {
255 err("write_sysfs_attribute failed: sockfd %s to %s",
256 sockfd_buff, sockfd_attr_path);
257 return ret;
258 }
259
260 info("connect: %s", edev->udev.busid);
261
262 return ret;
263}
264
265struct usbip_exported_device *usbip_host_get_device(int num)
266{
267 struct list_head *i;
268 struct usbip_exported_device *edev;
269 int cnt = 0;
270
271 list_for_each(i, &host_driver->edev_list) {
272 edev = list_entry(i, struct usbip_exported_device, node);
273 if (num == cnt)
274 return edev;
275 else
276 cnt++;
277 }
278
279 return NULL;
280}
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.h b/tools/usb/usbip/libsrc/usbip_host_driver.h
new file mode 100644
index 000000000000..2a31f855c616
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_host_driver.h
@@ -0,0 +1,49 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef __USBIP_HOST_DRIVER_H
20#define __USBIP_HOST_DRIVER_H
21
22#include <stdint.h>
23#include "usbip_common.h"
24#include "list.h"
25
26struct usbip_host_driver {
27 int ndevs;
28 /* list of exported device */
29 struct list_head edev_list;
30};
31
32struct usbip_exported_device {
33 struct udev_device *sudev;
34 int32_t status;
35 struct usbip_usb_device udev;
36 struct list_head node;
37 struct usbip_usb_interface uinf[];
38};
39
40extern struct usbip_host_driver *host_driver;
41
42int usbip_host_driver_open(void);
43void usbip_host_driver_close(void);
44
45int usbip_host_refresh_device_list(void);
46int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd);
47struct usbip_exported_device *usbip_host_get_device(int num);
48
49#endif /* __USBIP_HOST_DRIVER_H */
diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c
new file mode 100644
index 000000000000..ad9204773533
--- /dev/null
+++ b/tools/usb/usbip/libsrc/vhci_driver.c
@@ -0,0 +1,411 @@
1/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */
4
5#include "usbip_common.h"
6#include "vhci_driver.h"
7#include <limits.h>
8#include <netdb.h>
9#include <libudev.h>
10#include "sysfs_utils.h"
11
12#undef PROGNAME
13#define PROGNAME "libusbip"
14
15struct usbip_vhci_driver *vhci_driver;
16struct udev *udev_context;
17
18static struct usbip_imported_device *
19imported_device_init(struct usbip_imported_device *idev, char *busid)
20{
21 struct udev_device *sudev;
22
23 sudev = udev_device_new_from_subsystem_sysname(udev_context,
24 "usb", busid);
25 if (!sudev) {
26 dbg("udev_device_new_from_subsystem_sysname failed: %s", busid);
27 goto err;
28 }
29 read_usb_device(sudev, &idev->udev);
30 udev_device_unref(sudev);
31
32 return idev;
33
34err:
35 return NULL;
36}
37
38
39
40static int parse_status(const char *value)
41{
42 int ret = 0;
43 char *c;
44
45
46 for (int i = 0; i < vhci_driver->nports; i++)
47 memset(&vhci_driver->idev[i], 0, sizeof(vhci_driver->idev[i]));
48
49
50 /* skip a header line */
51 c = strchr(value, '\n');
52 if (!c)
53 return -1;
54 c++;
55
56 while (*c != '\0') {
57 int port, status, speed, devid;
58 unsigned long socket;
59 char lbusid[SYSFS_BUS_ID_SIZE];
60
61 ret = sscanf(c, "%d %d %d %x %lx %31s\n",
62 &port, &status, &speed,
63 &devid, &socket, lbusid);
64
65 if (ret < 5) {
66 dbg("sscanf failed: %d", ret);
67 BUG();
68 }
69
70 dbg("port %d status %d speed %d devid %x",
71 port, status, speed, devid);
72 dbg("socket %lx lbusid %s", socket, lbusid);
73
74
75 /* if a device is connected, look at it */
76 {
77 struct usbip_imported_device *idev = &vhci_driver->idev[port];
78
79 idev->port = port;
80 idev->status = status;
81
82 idev->devid = devid;
83
84 idev->busnum = (devid >> 16);
85 idev->devnum = (devid & 0x0000ffff);
86
87 if (idev->status != VDEV_ST_NULL
88 && idev->status != VDEV_ST_NOTASSIGNED) {
89 idev = imported_device_init(idev, lbusid);
90 if (!idev) {
91 dbg("imported_device_init failed");
92 return -1;
93 }
94 }
95 }
96
97
98 /* go to the next line */
99 c = strchr(c, '\n');
100 if (!c)
101 break;
102 c++;
103 }
104
105 dbg("exit");
106
107 return 0;
108}
109
110static int refresh_imported_device_list(void)
111{
112 const char *attr_status;
113
114 attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device,
115 "status");
116 if (!attr_status) {
117 err("udev_device_get_sysattr_value failed");
118 return -1;
119 }
120
121 return parse_status(attr_status);
122}
123
124static int get_nports(void)
125{
126 char *c;
127 int nports = 0;
128 const char *attr_status;
129
130 attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device,
131 "status");
132 if (!attr_status) {
133 err("udev_device_get_sysattr_value failed");
134 return -1;
135 }
136
137 /* skip a header line */
138 c = strchr(attr_status, '\n');
139 if (!c)
140 return 0;
141 c++;
142
143 while (*c != '\0') {
144 /* go to the next line */
145 c = strchr(c, '\n');
146 if (!c)
147 return nports;
148 c++;
149 nports += 1;
150 }
151
152 return nports;
153}
154
155/*
156 * Read the given port's record.
157 *
158 * To avoid buffer overflow we will read the entire line and
159 * validate each part's size. The initial buffer is padded by 4 to
160 * accommodate the 2 spaces, 1 newline and an additional character
161 * which is needed to properly validate the 3rd part without it being
162 * truncated to an acceptable length.
163 */
164static int read_record(int rhport, char *host, unsigned long host_len,
165 char *port, unsigned long port_len, char *busid)
166{
167 int part;
168 FILE *file;
169 char path[PATH_MAX+1];
170 char *buffer, *start, *end;
171 char delim[] = {' ', ' ', '\n'};
172 int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE};
173 size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4;
174
175 buffer = malloc(buffer_len);
176 if (!buffer)
177 return -1;
178
179 snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
180
181 file = fopen(path, "r");
182 if (!file) {
183 err("fopen");
184 free(buffer);
185 return -1;
186 }
187
188 if (fgets(buffer, buffer_len, file) == NULL) {
189 err("fgets");
190 free(buffer);
191 fclose(file);
192 return -1;
193 }
194 fclose(file);
195
196 /* validate the length of each of the 3 parts */
197 start = buffer;
198 for (part = 0; part < 3; part++) {
199 end = strchr(start, delim[part]);
200 if (end == NULL || (end - start) > max_len[part]) {
201 free(buffer);
202 return -1;
203 }
204 start = end + 1;
205 }
206
207 if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) {
208 err("sscanf");
209 free(buffer);
210 return -1;
211 }
212
213 free(buffer);
214
215 return 0;
216}
217
218/* ---------------------------------------------------------------------- */
219
220int usbip_vhci_driver_open(void)
221{
222 udev_context = udev_new();
223 if (!udev_context) {
224 err("udev_new failed");
225 return -1;
226 }
227
228 vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver));
229
230 /* will be freed in usbip_driver_close() */
231 vhci_driver->hc_device =
232 udev_device_new_from_subsystem_sysname(udev_context,
233 USBIP_VHCI_BUS_TYPE,
234 USBIP_VHCI_DRV_NAME);
235 if (!vhci_driver->hc_device) {
236 err("udev_device_new_from_subsystem_sysname failed");
237 goto err;
238 }
239
240 vhci_driver->nports = get_nports();
241
242 dbg("available ports: %d", vhci_driver->nports);
243
244 if (refresh_imported_device_list())
245 goto err;
246
247 return 0;
248
249err:
250 udev_device_unref(vhci_driver->hc_device);
251
252 if (vhci_driver)
253 free(vhci_driver);
254
255 vhci_driver = NULL;
256
257 udev_unref(udev_context);
258
259 return -1;
260}
261
262
263void usbip_vhci_driver_close(void)
264{
265 if (!vhci_driver)
266 return;
267
268 udev_device_unref(vhci_driver->hc_device);
269
270 free(vhci_driver);
271
272 vhci_driver = NULL;
273
274 udev_unref(udev_context);
275}
276
277
278int usbip_vhci_refresh_device_list(void)
279{
280
281 if (refresh_imported_device_list())
282 goto err;
283
284 return 0;
285err:
286 dbg("failed to refresh device list");
287 return -1;
288}
289
290
291int usbip_vhci_get_free_port(void)
292{
293 for (int i = 0; i < vhci_driver->nports; i++) {
294 if (vhci_driver->idev[i].status == VDEV_ST_NULL)
295 return i;
296 }
297
298 return -1;
299}
300
301int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
302 uint32_t speed) {
303 char buff[200]; /* what size should be ? */
304 char attach_attr_path[SYSFS_PATH_MAX];
305 char attr_attach[] = "attach";
306 const char *path;
307 int ret;
308
309 snprintf(buff, sizeof(buff), "%u %d %u %u",
310 port, sockfd, devid, speed);
311 dbg("writing: %s", buff);
312
313 path = udev_device_get_syspath(vhci_driver->hc_device);
314 snprintf(attach_attr_path, sizeof(attach_attr_path), "%s/%s",
315 path, attr_attach);
316 dbg("attach attribute path: %s", attach_attr_path);
317
318 ret = write_sysfs_attribute(attach_attr_path, buff, strlen(buff));
319 if (ret < 0) {
320 dbg("write_sysfs_attribute failed");
321 return -1;
322 }
323
324 dbg("attached port: %d", port);
325
326 return 0;
327}
328
329static unsigned long get_devid(uint8_t busnum, uint8_t devnum)
330{
331 return (busnum << 16) | devnum;
332}
333
334/* will be removed */
335int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
336 uint8_t devnum, uint32_t speed)
337{
338 int devid = get_devid(busnum, devnum);
339
340 return usbip_vhci_attach_device2(port, sockfd, devid, speed);
341}
342
343int usbip_vhci_detach_device(uint8_t port)
344{
345 char detach_attr_path[SYSFS_PATH_MAX];
346 char attr_detach[] = "detach";
347 char buff[200]; /* what size should be ? */
348 const char *path;
349 int ret;
350
351 snprintf(buff, sizeof(buff), "%u", port);
352 dbg("writing: %s", buff);
353
354 path = udev_device_get_syspath(vhci_driver->hc_device);
355 snprintf(detach_attr_path, sizeof(detach_attr_path), "%s/%s",
356 path, attr_detach);
357 dbg("detach attribute path: %s", detach_attr_path);
358
359 ret = write_sysfs_attribute(detach_attr_path, buff, strlen(buff));
360 if (ret < 0) {
361 dbg("write_sysfs_attribute failed");
362 return -1;
363 }
364
365 dbg("detached port: %d", port);
366
367 return 0;
368}
369
370int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
371{
372 char product_name[100];
373 char host[NI_MAXHOST] = "unknown host";
374 char serv[NI_MAXSERV] = "unknown port";
375 char remote_busid[SYSFS_BUS_ID_SIZE];
376 int ret;
377 int read_record_error = 0;
378
379 if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED)
380 return 0;
381
382 ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv),
383 remote_busid);
384 if (ret) {
385 err("read_record");
386 read_record_error = 1;
387 }
388
389 printf("Port %02d: <%s> at %s\n", idev->port,
390 usbip_status_string(idev->status),
391 usbip_speed_string(idev->udev.speed));
392
393 usbip_names_get_product(product_name, sizeof(product_name),
394 idev->udev.idVendor, idev->udev.idProduct);
395
396 printf(" %s\n", product_name);
397
398 if (!read_record_error) {
399 printf("%10s -> usbip://%s:%s/%s\n", idev->udev.busid,
400 host, serv, remote_busid);
401 printf("%10s -> remote bus/dev %03d/%03d\n", " ",
402 idev->busnum, idev->devnum);
403 } else {
404 printf("%10s -> unknown host, remote port and remote busid\n",
405 idev->udev.busid);
406 printf("%10s -> remote bus/dev %03d/%03d\n", " ",
407 idev->busnum, idev->devnum);
408 }
409
410 return 0;
411}
diff --git a/tools/usb/usbip/libsrc/vhci_driver.h b/tools/usb/usbip/libsrc/vhci_driver.h
new file mode 100644
index 000000000000..fa2316cf2cac
--- /dev/null
+++ b/tools/usb/usbip/libsrc/vhci_driver.h
@@ -0,0 +1,59 @@
1/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */
4
5#ifndef __VHCI_DRIVER_H
6#define __VHCI_DRIVER_H
7
8#include <libudev.h>
9#include <stdint.h>
10
11#include "usbip_common.h"
12
13#define USBIP_VHCI_BUS_TYPE "platform"
14#define MAXNPORT 128
15
16struct usbip_imported_device {
17 uint8_t port;
18 uint32_t status;
19
20 uint32_t devid;
21
22 uint8_t busnum;
23 uint8_t devnum;
24
25 /* usbip_class_device list */
26 struct usbip_usb_device udev;
27};
28
29struct usbip_vhci_driver {
30
31 /* /sys/devices/platform/vhci_hcd */
32 struct udev_device *hc_device;
33
34 int nports;
35 struct usbip_imported_device idev[MAXNPORT];
36};
37
38
39extern struct usbip_vhci_driver *vhci_driver;
40
41int usbip_vhci_driver_open(void);
42void usbip_vhci_driver_close(void);
43
44int usbip_vhci_refresh_device_list(void);
45
46
47int usbip_vhci_get_free_port(void);
48int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
49 uint32_t speed);
50
51/* will be removed */
52int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
53 uint8_t devnum, uint32_t speed);
54
55int usbip_vhci_detach_device(uint8_t port);
56
57int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev);
58
59#endif /* __VHCI_DRIVER_H */
diff --git a/tools/usb/usbip/src/Makefile.am b/tools/usb/usbip/src/Makefile.am
new file mode 100644
index 000000000000..e81a4ebadeff
--- /dev/null
+++ b/tools/usb/usbip/src/Makefile.am
@@ -0,0 +1,11 @@
1AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
2AM_CFLAGS = @EXTRA_CFLAGS@
3LDADD = $(top_builddir)/libsrc/libusbip.la
4
5sbin_PROGRAMS := usbip usbipd
6
7usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \
8 usbip_attach.c usbip_detach.c usbip_list.c \
9 usbip_bind.c usbip_unbind.c usbip_port.c
10
11usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c
diff --git a/tools/usb/usbip/src/usbip.c b/tools/usb/usbip/src/usbip.c
new file mode 100644
index 000000000000..d7599d943529
--- /dev/null
+++ b/tools/usb/usbip/src/usbip.c
@@ -0,0 +1,201 @@
1/*
2 * command structure borrowed from udev
3 * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git)
4 *
5 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
6 * 2005-2007 Takahiro Hirofuchi
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24
25#include <getopt.h>
26#include <syslog.h>
27
28#include "usbip_common.h"
29#include "usbip_network.h"
30#include "usbip.h"
31
32static int usbip_help(int argc, char *argv[]);
33static int usbip_version(int argc, char *argv[]);
34
35static const char usbip_version_string[] = PACKAGE_STRING;
36
37static const char usbip_usage_string[] =
38 "usbip [--debug] [--log] [--tcp-port PORT] [version]\n"
39 " [help] <command> <args>\n";
40
41static void usbip_usage(void)
42{
43 printf("usage: %s", usbip_usage_string);
44}
45
46struct command {
47 const char *name;
48 int (*fn)(int argc, char *argv[]);
49 const char *help;
50 void (*usage)(void);
51};
52
53static const struct command cmds[] = {
54 {
55 .name = "help",
56 .fn = usbip_help,
57 .help = NULL,
58 .usage = NULL
59 },
60 {
61 .name = "version",
62 .fn = usbip_version,
63 .help = NULL,
64 .usage = NULL
65 },
66 {
67 .name = "attach",
68 .fn = usbip_attach,
69 .help = "Attach a remote USB device",
70 .usage = usbip_attach_usage
71 },
72 {
73 .name = "detach",
74 .fn = usbip_detach,
75 .help = "Detach a remote USB device",
76 .usage = usbip_detach_usage
77 },
78 {
79 .name = "list",
80 .fn = usbip_list,
81 .help = "List exportable or local USB devices",
82 .usage = usbip_list_usage
83 },
84 {
85 .name = "bind",
86 .fn = usbip_bind,
87 .help = "Bind device to " USBIP_HOST_DRV_NAME ".ko",
88 .usage = usbip_bind_usage
89 },
90 {
91 .name = "unbind",
92 .fn = usbip_unbind,
93 .help = "Unbind device from " USBIP_HOST_DRV_NAME ".ko",
94 .usage = usbip_unbind_usage
95 },
96 {
97 .name = "port",
98 .fn = usbip_port_show,
99 .help = "Show imported USB devices",
100 .usage = NULL
101 },
102 { NULL, NULL, NULL, NULL }
103};
104
105static int usbip_help(int argc, char *argv[])
106{
107 const struct command *cmd;
108 int i;
109 int ret = 0;
110
111 if (argc > 1 && argv++) {
112 for (i = 0; cmds[i].name != NULL; i++)
113 if (!strcmp(cmds[i].name, argv[0]) && cmds[i].usage) {
114 cmds[i].usage();
115 goto done;
116 }
117 ret = -1;
118 }
119
120 usbip_usage();
121 printf("\n");
122 for (cmd = cmds; cmd->name != NULL; cmd++)
123 if (cmd->help != NULL)
124 printf(" %-10s %s\n", cmd->name, cmd->help);
125 printf("\n");
126done:
127 return ret;
128}
129
130static int usbip_version(int argc, char *argv[])
131{
132 (void) argc;
133 (void) argv;
134
135 printf(PROGNAME " (%s)\n", usbip_version_string);
136 return 0;
137}
138
139static int run_command(const struct command *cmd, int argc, char *argv[])
140{
141 dbg("running command: `%s'", cmd->name);
142 return cmd->fn(argc, argv);
143}
144
145int main(int argc, char *argv[])
146{
147 static const struct option opts[] = {
148 { "debug", no_argument, NULL, 'd' },
149 { "log", no_argument, NULL, 'l' },
150 { "tcp-port", required_argument, NULL, 't' },
151 { NULL, 0, NULL, 0 }
152 };
153
154 char *cmd;
155 int opt;
156 int i, rc = -1;
157
158 usbip_use_stderr = 1;
159 opterr = 0;
160 for (;;) {
161 opt = getopt_long(argc, argv, "+dlt:", opts, NULL);
162
163 if (opt == -1)
164 break;
165
166 switch (opt) {
167 case 'd':
168 usbip_use_debug = 1;
169 break;
170 case 'l':
171 usbip_use_syslog = 1;
172 openlog("", LOG_PID, LOG_USER);
173 break;
174 case 't':
175 usbip_setup_port_number(optarg);
176 break;
177 case '?':
178 printf("usbip: invalid option\n");
179 default:
180 usbip_usage();
181 goto out;
182 }
183 }
184
185 cmd = argv[optind];
186 if (cmd) {
187 for (i = 0; cmds[i].name != NULL; i++)
188 if (!strcmp(cmds[i].name, cmd)) {
189 argc -= optind;
190 argv += optind;
191 optind = 0;
192 rc = run_command(&cmds[i], argc, argv);
193 goto out;
194 }
195 }
196
197 /* invalid command */
198 usbip_help(0, NULL);
199out:
200 return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
201}
diff --git a/tools/usb/usbip/src/usbip.h b/tools/usb/usbip/src/usbip.h
new file mode 100644
index 000000000000..84fe66a9d8ad
--- /dev/null
+++ b/tools/usb/usbip/src/usbip.h
@@ -0,0 +1,40 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef __USBIP_H
20#define __USBIP_H
21
22#ifdef HAVE_CONFIG_H
23#include "../config.h"
24#endif
25
26/* usbip commands */
27int usbip_attach(int argc, char *argv[]);
28int usbip_detach(int argc, char *argv[]);
29int usbip_list(int argc, char *argv[]);
30int usbip_bind(int argc, char *argv[]);
31int usbip_unbind(int argc, char *argv[]);
32int usbip_port_show(int argc, char *argv[]);
33
34void usbip_attach_usage(void);
35void usbip_detach_usage(void);
36void usbip_list_usage(void);
37void usbip_bind_usage(void);
38void usbip_unbind_usage(void);
39
40#endif /* __USBIP_H */
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
new file mode 100644
index 000000000000..d58a14dfc094
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -0,0 +1,241 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <sys/stat.h>
20
21#include <limits.h>
22#include <stdint.h>
23#include <stdio.h>
24#include <string.h>
25
26#include <fcntl.h>
27#include <getopt.h>
28#include <unistd.h>
29#include <errno.h>
30
31#include "vhci_driver.h"
32#include "usbip_common.h"
33#include "usbip_network.h"
34#include "usbip.h"
35
36static const char usbip_attach_usage_string[] =
37 "usbip attach <args>\n"
38 " -r, --remote=<host> The machine with exported USB devices\n"
39 " -b, --busid=<busid> Busid of the device on <host>\n";
40
41void usbip_attach_usage(void)
42{
43 printf("usage: %s", usbip_attach_usage_string);
44}
45
46#define MAX_BUFF 100
47static int record_connection(char *host, char *port, char *busid, int rhport)
48{
49 int fd;
50 char path[PATH_MAX+1];
51 char buff[MAX_BUFF+1];
52 int ret;
53
54 ret = mkdir(VHCI_STATE_PATH, 0700);
55 if (ret < 0) {
56 /* if VHCI_STATE_PATH exists, then it better be a directory */
57 if (errno == EEXIST) {
58 struct stat s;
59
60 ret = stat(VHCI_STATE_PATH, &s);
61 if (ret < 0)
62 return -1;
63 if (!(s.st_mode & S_IFDIR))
64 return -1;
65 } else
66 return -1;
67 }
68
69 snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
70
71 fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
72 if (fd < 0)
73 return -1;
74
75 snprintf(buff, MAX_BUFF, "%s %s %s\n",
76 host, port, busid);
77
78 ret = write(fd, buff, strlen(buff));
79 if (ret != (ssize_t) strlen(buff)) {
80 close(fd);
81 return -1;
82 }
83
84 close(fd);
85
86 return 0;
87}
88
89static int import_device(int sockfd, struct usbip_usb_device *udev)
90{
91 int rc;
92 int port;
93
94 rc = usbip_vhci_driver_open();
95 if (rc < 0) {
96 err("open vhci_driver");
97 return -1;
98 }
99
100 port = usbip_vhci_get_free_port();
101 if (port < 0) {
102 err("no free port");
103 usbip_vhci_driver_close();
104 return -1;
105 }
106
107 rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
108 udev->devnum, udev->speed);
109 if (rc < 0) {
110 err("import device");
111 usbip_vhci_driver_close();
112 return -1;
113 }
114
115 usbip_vhci_driver_close();
116
117 return port;
118}
119
120static int query_import_device(int sockfd, char *busid)
121{
122 int rc;
123 struct op_import_request request;
124 struct op_import_reply reply;
125 uint16_t code = OP_REP_IMPORT;
126
127 memset(&request, 0, sizeof(request));
128 memset(&reply, 0, sizeof(reply));
129
130 /* send a request */
131 rc = usbip_net_send_op_common(sockfd, OP_REQ_IMPORT, 0);
132 if (rc < 0) {
133 err("send op_common");
134 return -1;
135 }
136
137 strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
138
139 PACK_OP_IMPORT_REQUEST(0, &request);
140
141 rc = usbip_net_send(sockfd, (void *) &request, sizeof(request));
142 if (rc < 0) {
143 err("send op_import_request");
144 return -1;
145 }
146
147 /* receive a reply */
148 rc = usbip_net_recv_op_common(sockfd, &code);
149 if (rc < 0) {
150 err("recv op_common");
151 return -1;
152 }
153
154 rc = usbip_net_recv(sockfd, (void *) &reply, sizeof(reply));
155 if (rc < 0) {
156 err("recv op_import_reply");
157 return -1;
158 }
159
160 PACK_OP_IMPORT_REPLY(0, &reply);
161
162 /* check the reply */
163 if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
164 err("recv different busid %s", reply.udev.busid);
165 return -1;
166 }
167
168 /* import a device */
169 return import_device(sockfd, &reply.udev);
170}
171
172static int attach_device(char *host, char *busid)
173{
174 int sockfd;
175 int rc;
176 int rhport;
177
178 sockfd = usbip_net_tcp_connect(host, usbip_port_string);
179 if (sockfd < 0) {
180 err("tcp connect");
181 return -1;
182 }
183
184 rhport = query_import_device(sockfd, busid);
185 if (rhport < 0) {
186 err("query");
187 return -1;
188 }
189
190 close(sockfd);
191
192 rc = record_connection(host, usbip_port_string, busid, rhport);
193 if (rc < 0) {
194 err("record connection");
195 return -1;
196 }
197
198 return 0;
199}
200
201int usbip_attach(int argc, char *argv[])
202{
203 static const struct option opts[] = {
204 { "remote", required_argument, NULL, 'r' },
205 { "busid", required_argument, NULL, 'b' },
206 { NULL, 0, NULL, 0 }
207 };
208 char *host = NULL;
209 char *busid = NULL;
210 int opt;
211 int ret = -1;
212
213 for (;;) {
214 opt = getopt_long(argc, argv, "r:b:", opts, NULL);
215
216 if (opt == -1)
217 break;
218
219 switch (opt) {
220 case 'r':
221 host = optarg;
222 break;
223 case 'b':
224 busid = optarg;
225 break;
226 default:
227 goto err_out;
228 }
229 }
230
231 if (!host || !busid)
232 goto err_out;
233
234 ret = attach_device(host, busid);
235 goto out;
236
237err_out:
238 usbip_attach_usage();
239out:
240 return ret;
241}
diff --git a/tools/usb/usbip/src/usbip_bind.c b/tools/usb/usbip/src/usbip_bind.c
new file mode 100644
index 000000000000..fa46141ae68b
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_bind.c
@@ -0,0 +1,214 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <libudev.h>
20
21#include <errno.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <getopt.h>
27
28#include "usbip_common.h"
29#include "utils.h"
30#include "usbip.h"
31#include "sysfs_utils.h"
32
33enum unbind_status {
34 UNBIND_ST_OK,
35 UNBIND_ST_USBIP_HOST,
36 UNBIND_ST_FAILED
37};
38
39static const char usbip_bind_usage_string[] =
40 "usbip bind <args>\n"
41 " -b, --busid=<busid> Bind " USBIP_HOST_DRV_NAME ".ko to device "
42 "on <busid>\n";
43
44void usbip_bind_usage(void)
45{
46 printf("usage: %s", usbip_bind_usage_string);
47}
48
49/* call at unbound state */
50static int bind_usbip(char *busid)
51{
52 char attr_name[] = "bind";
53 char bind_attr_path[SYSFS_PATH_MAX];
54 int rc = -1;
55
56 snprintf(bind_attr_path, sizeof(bind_attr_path), "%s/%s/%s/%s/%s/%s",
57 SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
58 SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name);
59
60 rc = write_sysfs_attribute(bind_attr_path, busid, strlen(busid));
61 if (rc < 0) {
62 err("error binding device %s to driver: %s", busid,
63 strerror(errno));
64 return -1;
65 }
66
67 return 0;
68}
69
70/* buggy driver may cause dead lock */
71static int unbind_other(char *busid)
72{
73 enum unbind_status status = UNBIND_ST_OK;
74
75 char attr_name[] = "unbind";
76 char unbind_attr_path[SYSFS_PATH_MAX];
77 int rc = -1;
78
79 struct udev *udev;
80 struct udev_device *dev;
81 const char *driver;
82 const char *bDevClass;
83
84 /* Create libudev context. */
85 udev = udev_new();
86
87 /* Get the device. */
88 dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
89 if (!dev) {
90 dbg("unable to find device with bus ID %s", busid);
91 goto err_close_busid_dev;
92 }
93
94 /* Check what kind of device it is. */
95 bDevClass = udev_device_get_sysattr_value(dev, "bDeviceClass");
96 if (!bDevClass) {
97 dbg("unable to get bDevClass device attribute");
98 goto err_close_busid_dev;
99 }
100
101 if (!strncmp(bDevClass, "09", strlen(bDevClass))) {
102 dbg("skip unbinding of hub");
103 goto err_close_busid_dev;
104 }
105
106 /* Get the device driver. */
107 driver = udev_device_get_driver(dev);
108 if (!driver) {
109 /* No driver bound to this device. */
110 goto out;
111 }
112
113 if (!strncmp(USBIP_HOST_DRV_NAME, driver,
114 strlen(USBIP_HOST_DRV_NAME))) {
115 /* Already bound to usbip-host. */
116 status = UNBIND_ST_USBIP_HOST;
117 goto out;
118 }
119
120 /* Unbind device from driver. */
121 snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
122 SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
123 SYSFS_DRIVERS_NAME, driver, attr_name);
124
125 rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
126 if (rc < 0) {
127 err("error unbinding device %s from driver", busid);
128 goto err_close_busid_dev;
129 }
130
131 goto out;
132
133err_close_busid_dev:
134 status = UNBIND_ST_FAILED;
135out:
136 udev_device_unref(dev);
137 udev_unref(udev);
138
139 return status;
140}
141
142static int bind_device(char *busid)
143{
144 int rc;
145 struct udev *udev;
146 struct udev_device *dev;
147
148 /* Check whether the device with this bus ID exists. */
149 udev = udev_new();
150 dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
151 if (!dev) {
152 err("device with the specified bus ID does not exist");
153 return -1;
154 }
155 udev_unref(udev);
156
157 rc = unbind_other(busid);
158 if (rc == UNBIND_ST_FAILED) {
159 err("could not unbind driver from device on busid %s", busid);
160 return -1;
161 } else if (rc == UNBIND_ST_USBIP_HOST) {
162 err("device on busid %s is already bound to %s", busid,
163 USBIP_HOST_DRV_NAME);
164 return -1;
165 }
166
167 rc = modify_match_busid(busid, 1);
168 if (rc < 0) {
169 err("unable to bind device on %s", busid);
170 return -1;
171 }
172
173 rc = bind_usbip(busid);
174 if (rc < 0) {
175 err("could not bind device to %s", USBIP_HOST_DRV_NAME);
176 modify_match_busid(busid, 0);
177 return -1;
178 }
179
180 info("bind device on busid %s: complete", busid);
181
182 return 0;
183}
184
185int usbip_bind(int argc, char *argv[])
186{
187 static const struct option opts[] = {
188 { "busid", required_argument, NULL, 'b' },
189 { NULL, 0, NULL, 0 }
190 };
191
192 int opt;
193 int ret = -1;
194
195 for (;;) {
196 opt = getopt_long(argc, argv, "b:", opts, NULL);
197
198 if (opt == -1)
199 break;
200
201 switch (opt) {
202 case 'b':
203 ret = bind_device(optarg);
204 goto out;
205 default:
206 goto err_out;
207 }
208 }
209
210err_out:
211 usbip_bind_usage();
212out:
213 return ret;
214}
diff --git a/tools/usb/usbip/src/usbip_detach.c b/tools/usb/usbip/src/usbip_detach.c
new file mode 100644
index 000000000000..05c6d15856eb
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_detach.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <ctype.h>
20#include <limits.h>
21#include <stdint.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <getopt.h>
27#include <unistd.h>
28
29#include "vhci_driver.h"
30#include "usbip_common.h"
31#include "usbip_network.h"
32#include "usbip.h"
33
34static const char usbip_detach_usage_string[] =
35 "usbip detach <args>\n"
36 " -p, --port=<port> " USBIP_VHCI_DRV_NAME
37 " port the device is on\n";
38
39void usbip_detach_usage(void)
40{
41 printf("usage: %s", usbip_detach_usage_string);
42}
43
44static int detach_port(char *port)
45{
46 int ret;
47 uint8_t portnum;
48 char path[PATH_MAX+1];
49
50 for (unsigned int i = 0; i < strlen(port); i++)
51 if (!isdigit(port[i])) {
52 err("invalid port %s", port);
53 return -1;
54 }
55
56 /* check max port */
57
58 portnum = atoi(port);
59
60 /* remove the port state file */
61
62 snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum);
63
64 remove(path);
65 rmdir(VHCI_STATE_PATH);
66
67 ret = usbip_vhci_driver_open();
68 if (ret < 0) {
69 err("open vhci_driver");
70 return -1;
71 }
72
73 ret = usbip_vhci_detach_device(portnum);
74 if (ret < 0)
75 return -1;
76
77 usbip_vhci_driver_close();
78
79 return ret;
80}
81
82int usbip_detach(int argc, char *argv[])
83{
84 static const struct option opts[] = {
85 { "port", required_argument, NULL, 'p' },
86 { NULL, 0, NULL, 0 }
87 };
88 int opt;
89 int ret = -1;
90
91 for (;;) {
92 opt = getopt_long(argc, argv, "p:", opts, NULL);
93
94 if (opt == -1)
95 break;
96
97 switch (opt) {
98 case 'p':
99 ret = detach_port(optarg);
100 goto out;
101 default:
102 goto err_out;
103 }
104 }
105
106err_out:
107 usbip_detach_usage();
108out:
109 return ret;
110}
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
new file mode 100644
index 000000000000..d5ce34a410e7
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -0,0 +1,283 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <sys/types.h>
20#include <libudev.h>
21
22#include <errno.h>
23#include <stdbool.h>
24#include <stdint.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <getopt.h>
30#include <netdb.h>
31#include <unistd.h>
32
33#include "usbip_common.h"
34#include "usbip_network.h"
35#include "usbip.h"
36
37static const char usbip_list_usage_string[] =
38 "usbip list [-p|--parsable] <args>\n"
39 " -p, --parsable Parsable list format\n"
40 " -r, --remote=<host> List the exportable USB devices on <host>\n"
41 " -l, --local List the local USB devices\n";
42
43void usbip_list_usage(void)
44{
45 printf("usage: %s", usbip_list_usage_string);
46}
47
48static int get_exported_devices(char *host, int sockfd)
49{
50 char product_name[100];
51 char class_name[100];
52 struct op_devlist_reply reply;
53 uint16_t code = OP_REP_DEVLIST;
54 struct usbip_usb_device udev;
55 struct usbip_usb_interface uintf;
56 unsigned int i;
57 int rc, j;
58
59 rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
60 if (rc < 0) {
61 dbg("usbip_net_send_op_common failed");
62 return -1;
63 }
64
65 rc = usbip_net_recv_op_common(sockfd, &code);
66 if (rc < 0) {
67 dbg("usbip_net_recv_op_common failed");
68 return -1;
69 }
70
71 memset(&reply, 0, sizeof(reply));
72 rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
73 if (rc < 0) {
74 dbg("usbip_net_recv_op_devlist failed");
75 return -1;
76 }
77 PACK_OP_DEVLIST_REPLY(0, &reply);
78 dbg("exportable devices: %d\n", reply.ndev);
79
80 if (reply.ndev == 0) {
81 info("no exportable devices found on %s", host);
82 return 0;
83 }
84
85 printf("Exportable USB devices\n");
86 printf("======================\n");
87 printf(" - %s\n", host);
88
89 for (i = 0; i < reply.ndev; i++) {
90 memset(&udev, 0, sizeof(udev));
91 rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
92 if (rc < 0) {
93 dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
94 return -1;
95 }
96 usbip_net_pack_usb_device(0, &udev);
97
98 usbip_names_get_product(product_name, sizeof(product_name),
99 udev.idVendor, udev.idProduct);
100 usbip_names_get_class(class_name, sizeof(class_name),
101 udev.bDeviceClass, udev.bDeviceSubClass,
102 udev.bDeviceProtocol);
103 printf("%11s: %s\n", udev.busid, product_name);
104 printf("%11s: %s\n", "", udev.path);
105 printf("%11s: %s\n", "", class_name);
106
107 for (j = 0; j < udev.bNumInterfaces; j++) {
108 rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
109 if (rc < 0) {
110 err("usbip_net_recv failed: usbip_usb_intf[%d]",
111 j);
112
113 return -1;
114 }
115 usbip_net_pack_usb_interface(0, &uintf);
116
117 usbip_names_get_class(class_name, sizeof(class_name),
118 uintf.bInterfaceClass,
119 uintf.bInterfaceSubClass,
120 uintf.bInterfaceProtocol);
121 printf("%11s: %2d - %s\n", "", j, class_name);
122 }
123
124 printf("\n");
125 }
126
127 return 0;
128}
129
130static int list_exported_devices(char *host)
131{
132 int rc;
133 int sockfd;
134
135 sockfd = usbip_net_tcp_connect(host, usbip_port_string);
136 if (sockfd < 0) {
137 err("could not connect to %s:%s: %s", host,
138 usbip_port_string, gai_strerror(sockfd));
139 return -1;
140 }
141 dbg("connected to %s:%s", host, usbip_port_string);
142
143 rc = get_exported_devices(host, sockfd);
144 if (rc < 0) {
145 err("failed to get device list from %s", host);
146 return -1;
147 }
148
149 close(sockfd);
150
151 return 0;
152}
153
154static void print_device(const char *busid, const char *vendor,
155 const char *product, bool parsable)
156{
157 if (parsable)
158 printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
159 else
160 printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
161}
162
163static void print_product_name(char *product_name, bool parsable)
164{
165 if (!parsable)
166 printf(" %s\n", product_name);
167}
168
169static int list_devices(bool parsable)
170{
171 struct udev *udev;
172 struct udev_enumerate *enumerate;
173 struct udev_list_entry *devices, *dev_list_entry;
174 struct udev_device *dev;
175 const char *path;
176 const char *idVendor;
177 const char *idProduct;
178 const char *bConfValue;
179 const char *bNumIntfs;
180 const char *busid;
181 char product_name[128];
182 int ret = -1;
183
184 /* Create libudev context. */
185 udev = udev_new();
186
187 /* Create libudev device enumeration. */
188 enumerate = udev_enumerate_new(udev);
189
190 /* Take only USB devices that are not hubs and do not have
191 * the bInterfaceNumber attribute, i.e. are not interfaces.
192 */
193 udev_enumerate_add_match_subsystem(enumerate, "usb");
194 udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09");
195 udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL);
196 udev_enumerate_scan_devices(enumerate);
197
198 devices = udev_enumerate_get_list_entry(enumerate);
199
200 /* Show information about each device. */
201 udev_list_entry_foreach(dev_list_entry, devices) {
202 path = udev_list_entry_get_name(dev_list_entry);
203 dev = udev_device_new_from_syspath(udev, path);
204
205 /* Get device information. */
206 idVendor = udev_device_get_sysattr_value(dev, "idVendor");
207 idProduct = udev_device_get_sysattr_value(dev, "idProduct");
208 bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue");
209 bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces");
210 busid = udev_device_get_sysname(dev);
211 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
212 err("problem getting device attributes: %s",
213 strerror(errno));
214 goto err_out;
215 }
216
217 /* Get product name. */
218 usbip_names_get_product(product_name, sizeof(product_name),
219 strtol(idVendor, NULL, 16),
220 strtol(idProduct, NULL, 16));
221
222 /* Print information. */
223 print_device(busid, idVendor, idProduct, parsable);
224 print_product_name(product_name, parsable);
225
226 printf("\n");
227
228 udev_device_unref(dev);
229 }
230
231 ret = 0;
232
233err_out:
234 udev_enumerate_unref(enumerate);
235 udev_unref(udev);
236
237 return ret;
238}
239
240int usbip_list(int argc, char *argv[])
241{
242 static const struct option opts[] = {
243 { "parsable", no_argument, NULL, 'p' },
244 { "remote", required_argument, NULL, 'r' },
245 { "local", no_argument, NULL, 'l' },
246 { NULL, 0, NULL, 0 }
247 };
248
249 bool parsable = false;
250 int opt;
251 int ret = -1;
252
253 if (usbip_names_init(USBIDS_FILE))
254 err("failed to open %s", USBIDS_FILE);
255
256 for (;;) {
257 opt = getopt_long(argc, argv, "pr:l", opts, NULL);
258
259 if (opt == -1)
260 break;
261
262 switch (opt) {
263 case 'p':
264 parsable = true;
265 break;
266 case 'r':
267 ret = list_exported_devices(optarg);
268 goto out;
269 case 'l':
270 ret = list_devices(parsable);
271 goto out;
272 default:
273 goto err_out;
274 }
275 }
276
277err_out:
278 usbip_list_usage();
279out:
280 usbip_names_free();
281
282 return ret;
283}
diff --git a/tools/usb/usbip/src/usbip_network.c b/tools/usb/usbip/src/usbip_network.c
new file mode 100644
index 000000000000..b4c37e76a6e0
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_network.c
@@ -0,0 +1,303 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <sys/socket.h>
20
21#include <string.h>
22
23#include <arpa/inet.h>
24#include <netdb.h>
25#include <netinet/tcp.h>
26#include <unistd.h>
27
28#ifdef HAVE_LIBWRAP
29#include <tcpd.h>
30#endif
31
32#include "usbip_common.h"
33#include "usbip_network.h"
34
35int usbip_port = 3240;
36char *usbip_port_string = "3240";
37
38void usbip_setup_port_number(char *arg)
39{
40 dbg("parsing port arg '%s'", arg);
41 char *end;
42 unsigned long int port = strtoul(arg, &end, 10);
43
44 if (end == arg) {
45 err("port: could not parse '%s' as a decimal integer", arg);
46 return;
47 }
48
49 if (*end != '\0') {
50 err("port: garbage at end of '%s'", arg);
51 return;
52 }
53
54 if (port > UINT16_MAX) {
55 err("port: %s too high (max=%d)",
56 arg, UINT16_MAX);
57 return;
58 }
59
60 usbip_port = port;
61 usbip_port_string = arg;
62 info("using port %d (\"%s\")", usbip_port, usbip_port_string);
63}
64
65void usbip_net_pack_uint32_t(int pack, uint32_t *num)
66{
67 uint32_t i;
68
69 if (pack)
70 i = htonl(*num);
71 else
72 i = ntohl(*num);
73
74 *num = i;
75}
76
77void usbip_net_pack_uint16_t(int pack, uint16_t *num)
78{
79 uint16_t i;
80
81 if (pack)
82 i = htons(*num);
83 else
84 i = ntohs(*num);
85
86 *num = i;
87}
88
89void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev)
90{
91 usbip_net_pack_uint32_t(pack, &udev->busnum);
92 usbip_net_pack_uint32_t(pack, &udev->devnum);
93 usbip_net_pack_uint32_t(pack, &udev->speed);
94
95 usbip_net_pack_uint16_t(pack, &udev->idVendor);
96 usbip_net_pack_uint16_t(pack, &udev->idProduct);
97 usbip_net_pack_uint16_t(pack, &udev->bcdDevice);
98}
99
100void usbip_net_pack_usb_interface(int pack __attribute__((unused)),
101 struct usbip_usb_interface *udev
102 __attribute__((unused)))
103{
104 /* uint8_t members need nothing */
105}
106
107static ssize_t usbip_net_xmit(int sockfd, void *buff, size_t bufflen,
108 int sending)
109{
110 ssize_t nbytes;
111 ssize_t total = 0;
112
113 if (!bufflen)
114 return 0;
115
116 do {
117 if (sending)
118 nbytes = send(sockfd, buff, bufflen, 0);
119 else
120 nbytes = recv(sockfd, buff, bufflen, MSG_WAITALL);
121
122 if (nbytes <= 0)
123 return -1;
124
125 buff = (void *)((intptr_t) buff + nbytes);
126 bufflen -= nbytes;
127 total += nbytes;
128
129 } while (bufflen > 0);
130
131 return total;
132}
133
134ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen)
135{
136 return usbip_net_xmit(sockfd, buff, bufflen, 0);
137}
138
139ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen)
140{
141 return usbip_net_xmit(sockfd, buff, bufflen, 1);
142}
143
144int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status)
145{
146 struct op_common op_common;
147 int rc;
148
149 memset(&op_common, 0, sizeof(op_common));
150
151 op_common.version = USBIP_VERSION;
152 op_common.code = code;
153 op_common.status = status;
154
155 PACK_OP_COMMON(1, &op_common);
156
157 rc = usbip_net_send(sockfd, &op_common, sizeof(op_common));
158 if (rc < 0) {
159 dbg("usbip_net_send failed: %d", rc);
160 return -1;
161 }
162
163 return 0;
164}
165
166int usbip_net_recv_op_common(int sockfd, uint16_t *code)
167{
168 struct op_common op_common;
169 int rc;
170
171 memset(&op_common, 0, sizeof(op_common));
172
173 rc = usbip_net_recv(sockfd, &op_common, sizeof(op_common));
174 if (rc < 0) {
175 dbg("usbip_net_recv failed: %d", rc);
176 goto err;
177 }
178
179 PACK_OP_COMMON(0, &op_common);
180
181 if (op_common.version != USBIP_VERSION) {
182 dbg("version mismatch: %d %d", op_common.version,
183 USBIP_VERSION);
184 goto err;
185 }
186
187 switch (*code) {
188 case OP_UNSPEC:
189 break;
190 default:
191 if (op_common.code != *code) {
192 dbg("unexpected pdu %#0x for %#0x", op_common.code,
193 *code);
194 goto err;
195 }
196 }
197
198 if (op_common.status != ST_OK) {
199 dbg("request failed at peer: %d", op_common.status);
200 goto err;
201 }
202
203 *code = op_common.code;
204
205 return 0;
206err:
207 return -1;
208}
209
210int usbip_net_set_reuseaddr(int sockfd)
211{
212 const int val = 1;
213 int ret;
214
215 ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
216 if (ret < 0)
217 dbg("setsockopt: SO_REUSEADDR");
218
219 return ret;
220}
221
222int usbip_net_set_nodelay(int sockfd)
223{
224 const int val = 1;
225 int ret;
226
227 ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
228 if (ret < 0)
229 dbg("setsockopt: TCP_NODELAY");
230
231 return ret;
232}
233
234int usbip_net_set_keepalive(int sockfd)
235{
236 const int val = 1;
237 int ret;
238
239 ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
240 if (ret < 0)
241 dbg("setsockopt: SO_KEEPALIVE");
242
243 return ret;
244}
245
246int usbip_net_set_v6only(int sockfd)
247{
248 const int val = 1;
249 int ret;
250
251 ret = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val));
252 if (ret < 0)
253 dbg("setsockopt: IPV6_V6ONLY");
254
255 return ret;
256}
257
258/*
259 * IPv6 Ready
260 */
261int usbip_net_tcp_connect(char *hostname, char *service)
262{
263 struct addrinfo hints, *res, *rp;
264 int sockfd;
265 int ret;
266
267 memset(&hints, 0, sizeof(hints));
268 hints.ai_family = AF_UNSPEC;
269 hints.ai_socktype = SOCK_STREAM;
270
271 /* get all possible addresses */
272 ret = getaddrinfo(hostname, service, &hints, &res);
273 if (ret < 0) {
274 dbg("getaddrinfo: %s service %s: %s", hostname, service,
275 gai_strerror(ret));
276 return ret;
277 }
278
279 /* try the addresses */
280 for (rp = res; rp; rp = rp->ai_next) {
281 sockfd = socket(rp->ai_family, rp->ai_socktype,
282 rp->ai_protocol);
283 if (sockfd < 0)
284 continue;
285
286 /* should set TCP_NODELAY for usbip */
287 usbip_net_set_nodelay(sockfd);
288 /* TODO: write code for heartbeat */
289 usbip_net_set_keepalive(sockfd);
290
291 if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
292 break;
293
294 close(sockfd);
295 }
296
297 freeaddrinfo(res);
298
299 if (!rp)
300 return EAI_SYSTEM;
301
302 return sockfd;
303}
diff --git a/tools/usb/usbip/src/usbip_network.h b/tools/usb/usbip/src/usbip_network.h
new file mode 100644
index 000000000000..c1e875cf1078
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_network.h
@@ -0,0 +1,185 @@
1/*
2 * Copyright (C) 2005-2007 Takahiro Hirofuchi
3 */
4
5#ifndef __USBIP_NETWORK_H
6#define __USBIP_NETWORK_H
7
8#ifdef HAVE_CONFIG_H
9#include "../config.h"
10#endif
11
12#include <sys/types.h>
13
14#include <stdint.h>
15
16extern int usbip_port;
17extern char *usbip_port_string;
18void usbip_setup_port_number(char *arg);
19
20/* ---------------------------------------------------------------------- */
21/* Common header for all the kinds of PDUs. */
22struct op_common {
23 uint16_t version;
24
25#define OP_REQUEST (0x80 << 8)
26#define OP_REPLY (0x00 << 8)
27 uint16_t code;
28
29 /* add more error code */
30#define ST_OK 0x00
31#define ST_NA 0x01
32 uint32_t status; /* op_code status (for reply) */
33
34} __attribute__((packed));
35
36#define PACK_OP_COMMON(pack, op_common) do {\
37 usbip_net_pack_uint16_t(pack, &(op_common)->version);\
38 usbip_net_pack_uint16_t(pack, &(op_common)->code);\
39 usbip_net_pack_uint32_t(pack, &(op_common)->status);\
40} while (0)
41
42/* ---------------------------------------------------------------------- */
43/* Dummy Code */
44#define OP_UNSPEC 0x00
45#define OP_REQ_UNSPEC OP_UNSPEC
46#define OP_REP_UNSPEC OP_UNSPEC
47
48/* ---------------------------------------------------------------------- */
49/* Retrieve USB device information. (still not used) */
50#define OP_DEVINFO 0x02
51#define OP_REQ_DEVINFO (OP_REQUEST | OP_DEVINFO)
52#define OP_REP_DEVINFO (OP_REPLY | OP_DEVINFO)
53
54struct op_devinfo_request {
55 char busid[SYSFS_BUS_ID_SIZE];
56} __attribute__((packed));
57
58struct op_devinfo_reply {
59 struct usbip_usb_device udev;
60 struct usbip_usb_interface uinf[];
61} __attribute__((packed));
62
63/* ---------------------------------------------------------------------- */
64/* Import a remote USB device. */
65#define OP_IMPORT 0x03
66#define OP_REQ_IMPORT (OP_REQUEST | OP_IMPORT)
67#define OP_REP_IMPORT (OP_REPLY | OP_IMPORT)
68
69struct op_import_request {
70 char busid[SYSFS_BUS_ID_SIZE];
71} __attribute__((packed));
72
73struct op_import_reply {
74 struct usbip_usb_device udev;
75// struct usbip_usb_interface uinf[];
76} __attribute__((packed));
77
78#define PACK_OP_IMPORT_REQUEST(pack, request) do {\
79} while (0)
80
81#define PACK_OP_IMPORT_REPLY(pack, reply) do {\
82 usbip_net_pack_usb_device(pack, &(reply)->udev);\
83} while (0)
84
85/* ---------------------------------------------------------------------- */
86/* Export a USB device to a remote host. */
87#define OP_EXPORT 0x06
88#define OP_REQ_EXPORT (OP_REQUEST | OP_EXPORT)
89#define OP_REP_EXPORT (OP_REPLY | OP_EXPORT)
90
91struct op_export_request {
92 struct usbip_usb_device udev;
93} __attribute__((packed));
94
95struct op_export_reply {
96 int returncode;
97} __attribute__((packed));
98
99
100#define PACK_OP_EXPORT_REQUEST(pack, request) do {\
101 usbip_net_pack_usb_device(pack, &(request)->udev);\
102} while (0)
103
104#define PACK_OP_EXPORT_REPLY(pack, reply) do {\
105} while (0)
106
107/* ---------------------------------------------------------------------- */
108/* un-Export a USB device from a remote host. */
109#define OP_UNEXPORT 0x07
110#define OP_REQ_UNEXPORT (OP_REQUEST | OP_UNEXPORT)
111#define OP_REP_UNEXPORT (OP_REPLY | OP_UNEXPORT)
112
113struct op_unexport_request {
114 struct usbip_usb_device udev;
115} __attribute__((packed));
116
117struct op_unexport_reply {
118 int returncode;
119} __attribute__((packed));
120
121#define PACK_OP_UNEXPORT_REQUEST(pack, request) do {\
122 usbip_net_pack_usb_device(pack, &(request)->udev);\
123} while (0)
124
125#define PACK_OP_UNEXPORT_REPLY(pack, reply) do {\
126} while (0)
127
128/* ---------------------------------------------------------------------- */
129/* Negotiate IPSec encryption key. (still not used) */
130#define OP_CRYPKEY 0x04
131#define OP_REQ_CRYPKEY (OP_REQUEST | OP_CRYPKEY)
132#define OP_REP_CRYPKEY (OP_REPLY | OP_CRYPKEY)
133
134struct op_crypkey_request {
135 /* 128bit key */
136 uint32_t key[4];
137} __attribute__((packed));
138
139struct op_crypkey_reply {
140 uint32_t __reserved;
141} __attribute__((packed));
142
143
144/* ---------------------------------------------------------------------- */
145/* Retrieve the list of exported USB devices. */
146#define OP_DEVLIST 0x05
147#define OP_REQ_DEVLIST (OP_REQUEST | OP_DEVLIST)
148#define OP_REP_DEVLIST (OP_REPLY | OP_DEVLIST)
149
150struct op_devlist_request {
151} __attribute__((packed));
152
153struct op_devlist_reply {
154 uint32_t ndev;
155 /* followed by reply_extra[] */
156} __attribute__((packed));
157
158struct op_devlist_reply_extra {
159 struct usbip_usb_device udev;
160 struct usbip_usb_interface uinf[];
161} __attribute__((packed));
162
163#define PACK_OP_DEVLIST_REQUEST(pack, request) do {\
164} while (0)
165
166#define PACK_OP_DEVLIST_REPLY(pack, reply) do {\
167 usbip_net_pack_uint32_t(pack, &(reply)->ndev);\
168} while (0)
169
170void usbip_net_pack_uint32_t(int pack, uint32_t *num);
171void usbip_net_pack_uint16_t(int pack, uint16_t *num);
172void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev);
173void usbip_net_pack_usb_interface(int pack, struct usbip_usb_interface *uinf);
174
175ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen);
176ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen);
177int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status);
178int usbip_net_recv_op_common(int sockfd, uint16_t *code);
179int usbip_net_set_reuseaddr(int sockfd);
180int usbip_net_set_nodelay(int sockfd);
181int usbip_net_set_keepalive(int sockfd);
182int usbip_net_set_v6only(int sockfd);
183int usbip_net_tcp_connect(char *hostname, char *port);
184
185#endif /* __USBIP_NETWORK_H */
diff --git a/tools/usb/usbip/src/usbip_port.c b/tools/usb/usbip/src/usbip_port.c
new file mode 100644
index 000000000000..a2e884fd9226
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_port.c
@@ -0,0 +1,57 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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
16#include "vhci_driver.h"
17#include "usbip_common.h"
18
19static int list_imported_devices(void)
20{
21 int i;
22 struct usbip_imported_device *idev;
23 int ret;
24
25 ret = usbip_vhci_driver_open();
26 if (ret < 0) {
27 err("open vhci_driver");
28 return -1;
29 }
30
31 printf("Imported USB devices\n");
32 printf("====================\n");
33
34 for (i = 0; i < vhci_driver->nports; i++) {
35 idev = &vhci_driver->idev[i];
36
37 if (usbip_vhci_imported_device_dump(idev) < 0)
38 ret = -1;
39 }
40
41 usbip_vhci_driver_close();
42
43 return ret;
44
45}
46
47int usbip_port_show(__attribute__((unused)) int argc,
48 __attribute__((unused)) char *argv[])
49{
50 int ret;
51
52 ret = list_imported_devices();
53 if (ret < 0)
54 err("list imported devices");
55
56 return ret;
57}
diff --git a/tools/usb/usbip/src/usbip_unbind.c b/tools/usb/usbip/src/usbip_unbind.c
new file mode 100644
index 000000000000..a4a496c9cbaf
--- /dev/null
+++ b/tools/usb/usbip/src/usbip_unbind.c
@@ -0,0 +1,141 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <libudev.h>
20
21#include <errno.h>
22#include <stdio.h>
23#include <string.h>
24
25#include <getopt.h>
26
27#include "usbip_common.h"
28#include "utils.h"
29#include "usbip.h"
30#include "sysfs_utils.h"
31
32static const char usbip_unbind_usage_string[] =
33 "usbip unbind <args>\n"
34 " -b, --busid=<busid> Unbind " USBIP_HOST_DRV_NAME ".ko from "
35 "device on <busid>\n";
36
37void usbip_unbind_usage(void)
38{
39 printf("usage: %s", usbip_unbind_usage_string);
40}
41
42static int unbind_device(char *busid)
43{
44 char bus_type[] = "usb";
45 int rc, ret = -1;
46
47 char unbind_attr_name[] = "unbind";
48 char unbind_attr_path[SYSFS_PATH_MAX];
49 char rebind_attr_name[] = "rebind";
50 char rebind_attr_path[SYSFS_PATH_MAX];
51
52 struct udev *udev;
53 struct udev_device *dev;
54 const char *driver;
55
56 /* Create libudev context. */
57 udev = udev_new();
58
59 /* Check whether the device with this bus ID exists. */
60 dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
61 if (!dev) {
62 err("device with the specified bus ID does not exist");
63 goto err_close_udev;
64 }
65
66 /* Check whether the device is using usbip-host driver. */
67 driver = udev_device_get_driver(dev);
68 if (!driver || strcmp(driver, "usbip-host")) {
69 err("device is not bound to usbip-host driver");
70 goto err_close_udev;
71 }
72
73 /* Unbind device from driver. */
74 snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
75 SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
76 USBIP_HOST_DRV_NAME, unbind_attr_name);
77
78 rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
79 if (rc < 0) {
80 err("error unbinding device %s from driver", busid);
81 goto err_close_udev;
82 }
83
84 /* Notify driver of unbind. */
85 rc = modify_match_busid(busid, 0);
86 if (rc < 0) {
87 err("unable to unbind device on %s", busid);
88 goto err_close_udev;
89 }
90
91 /* Trigger new probing. */
92 snprintf(rebind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
93 SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
94 USBIP_HOST_DRV_NAME, rebind_attr_name);
95
96 rc = write_sysfs_attribute(rebind_attr_path, busid, strlen(busid));
97 if (rc < 0) {
98 err("error rebinding");
99 goto err_close_udev;
100 }
101
102 ret = 0;
103 info("unbind device on busid %s: complete", busid);
104
105err_close_udev:
106 udev_device_unref(dev);
107 udev_unref(udev);
108
109 return ret;
110}
111
112int usbip_unbind(int argc, char *argv[])
113{
114 static const struct option opts[] = {
115 { "busid", required_argument, NULL, 'b' },
116 { NULL, 0, NULL, 0 }
117 };
118
119 int opt;
120 int ret = -1;
121
122 for (;;) {
123 opt = getopt_long(argc, argv, "b:", opts, NULL);
124
125 if (opt == -1)
126 break;
127
128 switch (opt) {
129 case 'b':
130 ret = unbind_device(optarg);
131 goto out;
132 default:
133 goto err_out;
134 }
135 }
136
137err_out:
138 usbip_unbind_usage();
139out:
140 return ret;
141}
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
new file mode 100644
index 000000000000..2f87f2d348ba
--- /dev/null
+++ b/tools/usb/usbip/src/usbipd.c
@@ -0,0 +1,679 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20#include "../config.h"
21#endif
22
23#define _GNU_SOURCE
24#include <errno.h>
25#include <unistd.h>
26#include <netdb.h>
27#include <string.h>
28#include <stdlib.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <arpa/inet.h>
32#include <sys/socket.h>
33#include <netinet/in.h>
34
35#ifdef HAVE_LIBWRAP
36#include <tcpd.h>
37#endif
38
39#include <getopt.h>
40#include <signal.h>
41#include <poll.h>
42
43#include "usbip_host_driver.h"
44#include "usbip_common.h"
45#include "usbip_network.h"
46#include "list.h"
47
48#undef PROGNAME
49#define PROGNAME "usbipd"
50#define MAXSOCKFD 20
51
52#define MAIN_LOOP_TIMEOUT 10
53
54#define DEFAULT_PID_FILE "/var/run/" PROGNAME ".pid"
55
56static const char usbip_version_string[] = PACKAGE_STRING;
57
58static const char usbipd_help_string[] =
59 "usage: usbipd [options]\n"
60 "\n"
61 " -4, --ipv4\n"
62 " Bind to IPv4. Default is both.\n"
63 "\n"
64 " -6, --ipv6\n"
65 " Bind to IPv6. Default is both.\n"
66 "\n"
67 " -D, --daemon\n"
68 " Run as a daemon process.\n"
69 "\n"
70 " -d, --debug\n"
71 " Print debugging information.\n"
72 "\n"
73 " -PFILE, --pid FILE\n"
74 " Write process id to FILE.\n"
75 " If no FILE specified, use " DEFAULT_PID_FILE "\n"
76 "\n"
77 " -tPORT, --tcp-port PORT\n"
78 " Listen on TCP/IP port PORT.\n"
79 "\n"
80 " -h, --help\n"
81 " Print this help.\n"
82 "\n"
83 " -v, --version\n"
84 " Show version.\n";
85
86static void usbipd_help(void)
87{
88 printf("%s\n", usbipd_help_string);
89}
90
91static int recv_request_import(int sockfd)
92{
93 struct op_import_request req;
94 struct op_common reply;
95 struct usbip_exported_device *edev;
96 struct usbip_usb_device pdu_udev;
97 struct list_head *i;
98 int found = 0;
99 int error = 0;
100 int rc;
101
102 memset(&req, 0, sizeof(req));
103 memset(&reply, 0, sizeof(reply));
104
105 rc = usbip_net_recv(sockfd, &req, sizeof(req));
106 if (rc < 0) {
107 dbg("usbip_net_recv failed: import request");
108 return -1;
109 }
110 PACK_OP_IMPORT_REQUEST(0, &req);
111
112 list_for_each(i, &host_driver->edev_list) {
113 edev = list_entry(i, struct usbip_exported_device, node);
114 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
115 info("found requested device: %s", req.busid);
116 found = 1;
117 break;
118 }
119 }
120
121 if (found) {
122 /* should set TCP_NODELAY for usbip */
123 usbip_net_set_nodelay(sockfd);
124
125 /* export device needs a TCP/IP socket descriptor */
126 rc = usbip_host_export_device(edev, sockfd);
127 if (rc < 0)
128 error = 1;
129 } else {
130 info("requested device not found: %s", req.busid);
131 error = 1;
132 }
133
134 rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT,
135 (!error ? ST_OK : ST_NA));
136 if (rc < 0) {
137 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
138 return -1;
139 }
140
141 if (error) {
142 dbg("import request busid %s: failed", req.busid);
143 return -1;
144 }
145
146 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
147 usbip_net_pack_usb_device(1, &pdu_udev);
148
149 rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev));
150 if (rc < 0) {
151 dbg("usbip_net_send failed: devinfo");
152 return -1;
153 }
154
155 dbg("import request busid %s: complete", req.busid);
156
157 return 0;
158}
159
160static int send_reply_devlist(int connfd)
161{
162 struct usbip_exported_device *edev;
163 struct usbip_usb_device pdu_udev;
164 struct usbip_usb_interface pdu_uinf;
165 struct op_devlist_reply reply;
166 struct list_head *j;
167 int rc, i;
168
169 reply.ndev = 0;
170 /* number of exported devices */
171 list_for_each(j, &host_driver->edev_list) {
172 reply.ndev += 1;
173 }
174 info("exportable devices: %d", reply.ndev);
175
176 rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK);
177 if (rc < 0) {
178 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST);
179 return -1;
180 }
181 PACK_OP_DEVLIST_REPLY(1, &reply);
182
183 rc = usbip_net_send(connfd, &reply, sizeof(reply));
184 if (rc < 0) {
185 dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST);
186 return -1;
187 }
188
189 list_for_each(j, &host_driver->edev_list) {
190 edev = list_entry(j, struct usbip_exported_device, node);
191 dump_usb_device(&edev->udev);
192 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
193 usbip_net_pack_usb_device(1, &pdu_udev);
194
195 rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev));
196 if (rc < 0) {
197 dbg("usbip_net_send failed: pdu_udev");
198 return -1;
199 }
200
201 for (i = 0; i < edev->udev.bNumInterfaces; i++) {
202 dump_usb_interface(&edev->uinf[i]);
203 memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf));
204 usbip_net_pack_usb_interface(1, &pdu_uinf);
205
206 rc = usbip_net_send(connfd, &pdu_uinf,
207 sizeof(pdu_uinf));
208 if (rc < 0) {
209 err("usbip_net_send failed: pdu_uinf");
210 return -1;
211 }
212 }
213 }
214
215 return 0;
216}
217
218static int recv_request_devlist(int connfd)
219{
220 struct op_devlist_request req;
221 int rc;
222
223 memset(&req, 0, sizeof(req));
224
225 rc = usbip_net_recv(connfd, &req, sizeof(req));
226 if (rc < 0) {
227 dbg("usbip_net_recv failed: devlist request");
228 return -1;
229 }
230
231 rc = send_reply_devlist(connfd);
232 if (rc < 0) {
233 dbg("send_reply_devlist failed");
234 return -1;
235 }
236
237 return 0;
238}
239
240static int recv_pdu(int connfd)
241{
242 uint16_t code = OP_UNSPEC;
243 int ret;
244
245 ret = usbip_net_recv_op_common(connfd, &code);
246 if (ret < 0) {
247 dbg("could not receive opcode: %#0x", code);
248 return -1;
249 }
250
251 ret = usbip_host_refresh_device_list();
252 if (ret < 0) {
253 dbg("could not refresh device list: %d", ret);
254 return -1;
255 }
256
257 info("received request: %#0x(%d)", code, connfd);
258 switch (code) {
259 case OP_REQ_DEVLIST:
260 ret = recv_request_devlist(connfd);
261 break;
262 case OP_REQ_IMPORT:
263 ret = recv_request_import(connfd);
264 break;
265 case OP_REQ_DEVINFO:
266 case OP_REQ_CRYPKEY:
267 default:
268 err("received an unknown opcode: %#0x", code);
269 ret = -1;
270 }
271
272 if (ret == 0)
273 info("request %#0x(%d): complete", code, connfd);
274 else
275 info("request %#0x(%d): failed", code, connfd);
276
277 return ret;
278}
279
280#ifdef HAVE_LIBWRAP
281static int tcpd_auth(int connfd)
282{
283 struct request_info request;
284 int rc;
285
286 request_init(&request, RQ_DAEMON, PROGNAME, RQ_FILE, connfd, 0);
287 fromhost(&request);
288 rc = hosts_access(&request);
289 if (rc == 0)
290 return -1;
291
292 return 0;
293}
294#endif
295
296static int do_accept(int listenfd)
297{
298 int connfd;
299 struct sockaddr_storage ss;
300 socklen_t len = sizeof(ss);
301 char host[NI_MAXHOST], port[NI_MAXSERV];
302 int rc;
303
304 memset(&ss, 0, sizeof(ss));
305
306 connfd = accept(listenfd, (struct sockaddr *)&ss, &len);
307 if (connfd < 0) {
308 err("failed to accept connection");
309 return -1;
310 }
311
312 rc = getnameinfo((struct sockaddr *)&ss, len, host, sizeof(host),
313 port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
314 if (rc)
315 err("getnameinfo: %s", gai_strerror(rc));
316
317#ifdef HAVE_LIBWRAP
318 rc = tcpd_auth(connfd);
319 if (rc < 0) {
320 info("denied access from %s", host);
321 close(connfd);
322 return -1;
323 }
324#endif
325 info("connection from %s:%s", host, port);
326
327 return connfd;
328}
329
330int process_request(int listenfd)
331{
332 pid_t childpid;
333 int connfd;
334
335 connfd = do_accept(listenfd);
336 if (connfd < 0)
337 return -1;
338 childpid = fork();
339 if (childpid == 0) {
340 close(listenfd);
341 recv_pdu(connfd);
342 exit(0);
343 }
344 close(connfd);
345 return 0;
346}
347
348static void addrinfo_to_text(struct addrinfo *ai, char buf[],
349 const size_t buf_size)
350{
351 char hbuf[NI_MAXHOST];
352 char sbuf[NI_MAXSERV];
353 int rc;
354
355 buf[0] = '\0';
356
357 rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),
358 sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
359 if (rc)
360 err("getnameinfo: %s", gai_strerror(rc));
361
362 snprintf(buf, buf_size, "%s:%s", hbuf, sbuf);
363}
364
365static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[],
366 int maxsockfd)
367{
368 struct addrinfo *ai;
369 int ret, nsockfd = 0;
370 const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2;
371 char ai_buf[ai_buf_size];
372
373 for (ai = ai_head; ai && nsockfd < maxsockfd; ai = ai->ai_next) {
374 int sock;
375
376 addrinfo_to_text(ai, ai_buf, ai_buf_size);
377 dbg("opening %s", ai_buf);
378 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
379 if (sock < 0) {
380 err("socket: %s: %d (%s)",
381 ai_buf, errno, strerror(errno));
382 continue;
383 }
384
385 usbip_net_set_reuseaddr(sock);
386 usbip_net_set_nodelay(sock);
387 /* We use seperate sockets for IPv4 and IPv6
388 * (see do_standalone_mode()) */
389 usbip_net_set_v6only(sock);
390
391 if (sock >= FD_SETSIZE) {
392 err("FD_SETSIZE: %s: sock=%d, max=%d",
393 ai_buf, sock, FD_SETSIZE);
394 close(sock);
395 continue;
396 }
397
398 ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
399 if (ret < 0) {
400 err("bind: %s: %d (%s)",
401 ai_buf, errno, strerror(errno));
402 close(sock);
403 continue;
404 }
405
406 ret = listen(sock, SOMAXCONN);
407 if (ret < 0) {
408 err("listen: %s: %d (%s)",
409 ai_buf, errno, strerror(errno));
410 close(sock);
411 continue;
412 }
413
414 info("listening on %s", ai_buf);
415 sockfdlist[nsockfd++] = sock;
416 }
417
418 return nsockfd;
419}
420
421static struct addrinfo *do_getaddrinfo(char *host, int ai_family)
422{
423 struct addrinfo hints, *ai_head;
424 int rc;
425
426 memset(&hints, 0, sizeof(hints));
427 hints.ai_family = ai_family;
428 hints.ai_socktype = SOCK_STREAM;
429 hints.ai_flags = AI_PASSIVE;
430
431 rc = getaddrinfo(host, usbip_port_string, &hints, &ai_head);
432 if (rc) {
433 err("failed to get a network address %s: %s", usbip_port_string,
434 gai_strerror(rc));
435 return NULL;
436 }
437
438 return ai_head;
439}
440
441static void signal_handler(int i)
442{
443 dbg("received '%s' signal", strsignal(i));
444}
445
446static void set_signal(void)
447{
448 struct sigaction act;
449
450 memset(&act, 0, sizeof(act));
451 act.sa_handler = signal_handler;
452 sigemptyset(&act.sa_mask);
453 sigaction(SIGTERM, &act, NULL);
454 sigaction(SIGINT, &act, NULL);
455 act.sa_handler = SIG_IGN;
456 sigaction(SIGCLD, &act, NULL);
457}
458
459static const char *pid_file;
460
461static void write_pid_file(void)
462{
463 if (pid_file) {
464 dbg("creating pid file %s", pid_file);
465 FILE *fp;
466
467 fp = fopen(pid_file, "w");
468 if (!fp) {
469 err("pid_file: %s: %d (%s)",
470 pid_file, errno, strerror(errno));
471 return;
472 }
473 fprintf(fp, "%d\n", getpid());
474 fclose(fp);
475 }
476}
477
478static void remove_pid_file(void)
479{
480 if (pid_file) {
481 dbg("removing pid file %s", pid_file);
482 unlink(pid_file);
483 }
484}
485
486static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
487{
488 struct addrinfo *ai_head;
489 int sockfdlist[MAXSOCKFD];
490 int nsockfd, family;
491 int i, terminate;
492 struct pollfd *fds;
493 struct timespec timeout;
494 sigset_t sigmask;
495
496 if (usbip_host_driver_open()) {
497 err("please load " USBIP_CORE_MOD_NAME ".ko and "
498 USBIP_HOST_DRV_NAME ".ko!");
499 return -1;
500 }
501
502 if (daemonize) {
503 if (daemon(0, 0) < 0) {
504 err("daemonizing failed: %s", strerror(errno));
505 usbip_host_driver_close();
506 return -1;
507 }
508 umask(0);
509 usbip_use_syslog = 1;
510 }
511 set_signal();
512 write_pid_file();
513
514 info("starting " PROGNAME " (%s)", usbip_version_string);
515
516 /*
517 * To suppress warnings on systems with bindv6only disabled
518 * (default), we use seperate sockets for IPv6 and IPv4 and set
519 * IPV6_V6ONLY on the IPv6 sockets.
520 */
521 if (ipv4 && ipv6)
522 family = AF_UNSPEC;
523 else if (ipv4)
524 family = AF_INET;
525 else
526 family = AF_INET6;
527
528 ai_head = do_getaddrinfo(NULL, family);
529 if (!ai_head) {
530 usbip_host_driver_close();
531 return -1;
532 }
533 nsockfd = listen_all_addrinfo(ai_head, sockfdlist,
534 sizeof(sockfdlist) / sizeof(*sockfdlist));
535 freeaddrinfo(ai_head);
536 if (nsockfd <= 0) {
537 err("failed to open a listening socket");
538 usbip_host_driver_close();
539 return -1;
540 }
541
542 dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
543
544 fds = calloc(nsockfd, sizeof(struct pollfd));
545 for (i = 0; i < nsockfd; i++) {
546 fds[i].fd = sockfdlist[i];
547 fds[i].events = POLLIN;
548 }
549 timeout.tv_sec = MAIN_LOOP_TIMEOUT;
550 timeout.tv_nsec = 0;
551
552 sigfillset(&sigmask);
553 sigdelset(&sigmask, SIGTERM);
554 sigdelset(&sigmask, SIGINT);
555
556 terminate = 0;
557 while (!terminate) {
558 int r;
559
560 r = ppoll(fds, nsockfd, &timeout, &sigmask);
561 if (r < 0) {
562 dbg("%s", strerror(errno));
563 terminate = 1;
564 } else if (r) {
565 for (i = 0; i < nsockfd; i++) {
566 if (fds[i].revents & POLLIN) {
567 dbg("read event on fd[%d]=%d",
568 i, sockfdlist[i]);
569 process_request(sockfdlist[i]);
570 }
571 }
572 } else {
573 dbg("heartbeat timeout on ppoll()");
574 }
575 }
576
577 info("shutting down " PROGNAME);
578 free(fds);
579 usbip_host_driver_close();
580
581 return 0;
582}
583
584int main(int argc, char *argv[])
585{
586 static const struct option longopts[] = {
587 { "ipv4", no_argument, NULL, '4' },
588 { "ipv6", no_argument, NULL, '6' },
589 { "daemon", no_argument, NULL, 'D' },
590 { "daemon", no_argument, NULL, 'D' },
591 { "debug", no_argument, NULL, 'd' },
592 { "pid", optional_argument, NULL, 'P' },
593 { "tcp-port", required_argument, NULL, 't' },
594 { "help", no_argument, NULL, 'h' },
595 { "version", no_argument, NULL, 'v' },
596 { NULL, 0, NULL, 0 }
597 };
598
599 enum {
600 cmd_standalone_mode = 1,
601 cmd_help,
602 cmd_version
603 } cmd;
604
605 int daemonize = 0;
606 int ipv4 = 0, ipv6 = 0;
607 int opt, rc = -1;
608
609 pid_file = NULL;
610
611 usbip_use_stderr = 1;
612 usbip_use_syslog = 0;
613
614 if (geteuid() != 0)
615 err("not running as root?");
616
617 cmd = cmd_standalone_mode;
618 for (;;) {
619 opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL);
620
621 if (opt == -1)
622 break;
623
624 switch (opt) {
625 case '4':
626 ipv4 = 1;
627 break;
628 case '6':
629 ipv6 = 1;
630 break;
631 case 'D':
632 daemonize = 1;
633 break;
634 case 'd':
635 usbip_use_debug = 1;
636 break;
637 case 'h':
638 cmd = cmd_help;
639 break;
640 case 'P':
641 pid_file = optarg ? optarg : DEFAULT_PID_FILE;
642 break;
643 case 't':
644 usbip_setup_port_number(optarg);
645 break;
646 case 'v':
647 cmd = cmd_version;
648 break;
649 case '?':
650 usbipd_help();
651 default:
652 goto err_out;
653 }
654 }
655
656 if (!ipv4 && !ipv6)
657 ipv4 = ipv6 = 1;
658
659 switch (cmd) {
660 case cmd_standalone_mode:
661 rc = do_standalone_mode(daemonize, ipv4, ipv6);
662 remove_pid_file();
663 break;
664 case cmd_version:
665 printf(PROGNAME " (%s)\n", usbip_version_string);
666 rc = 0;
667 break;
668 case cmd_help:
669 usbipd_help();
670 rc = 0;
671 break;
672 default:
673 usbipd_help();
674 goto err_out;
675 }
676
677err_out:
678 return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
679}
diff --git a/tools/usb/usbip/src/utils.c b/tools/usb/usbip/src/utils.c
new file mode 100644
index 000000000000..2b3d6d235015
--- /dev/null
+++ b/tools/usb/usbip/src/utils.c
@@ -0,0 +1,52 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <errno.h>
20#include <stdio.h>
21#include <string.h>
22
23#include "usbip_common.h"
24#include "utils.h"
25#include "sysfs_utils.h"
26
27int modify_match_busid(char *busid, int add)
28{
29 char attr_name[] = "match_busid";
30 char command[SYSFS_BUS_ID_SIZE + 4];
31 char match_busid_attr_path[SYSFS_PATH_MAX];
32 int rc;
33
34 snprintf(match_busid_attr_path, sizeof(match_busid_attr_path),
35 "%s/%s/%s/%s/%s/%s", SYSFS_MNT_PATH, SYSFS_BUS_NAME,
36 SYSFS_BUS_TYPE, SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME,
37 attr_name);
38
39 if (add)
40 snprintf(command, SYSFS_BUS_ID_SIZE + 4, "add %s", busid);
41 else
42 snprintf(command, SYSFS_BUS_ID_SIZE + 4, "del %s", busid);
43
44 rc = write_sysfs_attribute(match_busid_attr_path, command,
45 sizeof(command));
46 if (rc < 0) {
47 dbg("failed to write match_busid: %s", strerror(errno));
48 return -1;
49 }
50
51 return 0;
52}
diff --git a/tools/usb/usbip/src/utils.h b/tools/usb/usbip/src/utils.h
new file mode 100644
index 000000000000..5916fd3e02a6
--- /dev/null
+++ b/tools/usb/usbip/src/utils.h
@@ -0,0 +1,25 @@
1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef __UTILS_H
20#define __UTILS_H
21
22int modify_match_busid(char *busid, int add);
23
24#endif /* __UTILS_H */
25
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index c4d6d2e20e0d..264fbc297e0b 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -132,6 +132,7 @@ static const char * const page_flag_names[] = {
132 [KPF_NOPAGE] = "n:nopage", 132 [KPF_NOPAGE] = "n:nopage",
133 [KPF_KSM] = "x:ksm", 133 [KPF_KSM] = "x:ksm",
134 [KPF_THP] = "t:thp", 134 [KPF_THP] = "t:thp",
135 [KPF_BALLOON] = "o:balloon",
135 136
136 [KPF_RESERVED] = "r:reserved", 137 [KPF_RESERVED] = "r:reserved",
137 [KPF_MLOCKED] = "m:mlocked", 138 [KPF_MLOCKED] = "m:mlocked",