aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2011-03-19 02:38:50 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-03-19 02:38:50 -0400
commit97eb3f24352ec6632c2127b35d8087d2a809a9b9 (patch)
tree722948059bbd325bbca232269490124231df80d4 /tools
parent439581ec07fa9cf3f519dd461a2cf41cfd3adcb4 (diff)
parentdef179c271ac9b5020deca798470521f14d11edd (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-annotate.txt37
-rw-r--r--tools/perf/Documentation/perf-buildid-list.txt3
-rw-r--r--tools/perf/Documentation/perf-diff.txt21
-rw-r--r--tools/perf/Documentation/perf-kvm.txt8
-rw-r--r--tools/perf/Documentation/perf-lock.txt15
-rw-r--r--tools/perf/Documentation/perf-probe.txt4
-rw-r--r--tools/perf/Documentation/perf-record.txt25
-rw-r--r--tools/perf/Documentation/perf-report.txt55
-rw-r--r--tools/perf/Documentation/perf-sched.txt18
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt (renamed from tools/perf/Documentation/perf-trace-perl.txt)28
-rw-r--r--tools/perf/Documentation/perf-script-python.txt (renamed from tools/perf/Documentation/perf-trace-python.txt)88
-rw-r--r--tools/perf/Documentation/perf-script.txt118
-rw-r--r--tools/perf/Documentation/perf-stat.txt44
-rw-r--r--tools/perf/Documentation/perf-test.txt2
-rw-r--r--tools/perf/Documentation/perf-timechart.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt28
-rw-r--r--tools/perf/Documentation/perf-trace.txt70
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile34
-rw-r--r--tools/perf/arch/s390/Makefile4
-rw-r--r--tools/perf/arch/s390/util/dwarf-regs.c22
-rw-r--r--tools/perf/bench/mem-memcpy-arch.h12
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm-def.h4
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S2
-rw-r--r--tools/perf/bench/mem-memcpy.c219
-rw-r--r--tools/perf/builtin-annotate.c16
-rw-r--r--tools/perf/builtin-buildid-list.c6
-rw-r--r--tools/perf/builtin-diff.c21
-rw-r--r--tools/perf/builtin-inject.c41
-rw-r--r--tools/perf/builtin-kmem.c31
-rw-r--r--tools/perf/builtin-lock.c29
-rw-r--r--tools/perf/builtin-probe.c5
-rw-r--r--tools/perf/builtin-record.c254
-rw-r--r--tools/perf/builtin-report.c25
-rw-r--r--tools/perf/builtin-sched.c74
-rw-r--r--tools/perf/builtin-script.c (renamed from tools/perf/builtin-trace.c)326
-rw-r--r--tools/perf/builtin-stat.c535
-rw-r--r--tools/perf/builtin-test.c244
-rw-r--r--tools/perf/builtin-timechart.c132
-rw-r--r--tools/perf/builtin-top.c255
-rw-r--r--tools/perf/builtin.h2
-rw-r--r--tools/perf/command-list.txt2
-rw-r--r--tools/perf/feature-tests.mak4
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.c2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.xs4
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/README4
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm4
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm4
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-record2
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-report2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-record2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-report5
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-record2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-report5
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-record2
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-report5
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-record2
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-report5
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-record2
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-report6
-rw-r--r--tools/perf/scripts/perl/check-perf-trace.pl2
-rw-r--r--tools/perf/scripts/perl/rw-by-file.pl2
-rw-r--r--tools/perf/scripts/perl/workqueue-stats.pl2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py2
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-record2
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-report2
-rw-r--r--tools/perf/scripts/python/bin/futex-contention-record2
-rw-r--r--tools/perf/scripts/python/bin/futex-contention-report2
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-record2
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-report2
-rw-r--r--tools/perf/scripts/python/bin/sched-migration-record2
-rw-r--r--tools/perf/scripts/python/bin/sched-migration-report2
-rw-r--r--tools/perf/scripts/python/bin/sctop-record2
-rw-r--r--tools/perf/scripts/python/bin/sctop-report2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-record2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-report2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-record2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-report2
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py2
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py2
-rw-r--r--tools/perf/scripts/python/sched-migration.py2
-rw-r--r--tools/perf/scripts/python/sctop.py2
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py2
-rw-r--r--tools/perf/scripts/python/syscall-counts.py2
-rw-r--r--tools/perf/util/build-id.c7
-rw-r--r--tools/perf/util/cpumap.c123
-rw-r--r--tools/perf/util/cpumap.h10
-rw-r--r--tools/perf/util/debug.c42
-rw-r--r--tools/perf/util/debug.h2
-rw-r--r--tools/perf/util/event.c363
-rw-r--r--tools/perf/util/event.h30
-rw-r--r--tools/perf/util/evsel.c201
-rw-r--r--tools/perf/util/evsel.h115
-rw-r--r--tools/perf/util/header.c83
-rw-r--r--tools/perf/util/header.h5
-rw-r--r--tools/perf/util/hist.c42
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/include/asm/cpufeature.h9
-rw-r--r--tools/perf/util/include/asm/dwarf2.h11
-rw-r--r--tools/perf/util/include/linux/bitops.h6
-rw-r--r--tools/perf/util/include/linux/linkage.h13
-rw-r--r--tools/perf/util/map.c3
-rw-r--r--tools/perf/util/parse-events.c154
-rw-r--r--tools/perf/util/parse-events.h19
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/probe-event.c251
-rw-r--r--tools/perf/util/probe-finder.c127
-rw-r--r--tools/perf/util/probe-finder.h6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/session.c585
-rw-r--r--tools/perf/util/session.h26
-rw-r--r--tools/perf/util/sort.c6
-rw-r--r--tools/perf/util/string.c2
-rw-r--r--tools/perf/util/svghelper.c9
-rw-r--r--tools/perf/util/symbol.c220
-rw-r--r--tools/perf/util/symbol.h6
-rw-r--r--tools/perf/util/thread.c43
-rw-r--r--tools/perf/util/thread.h15
-rw-r--r--tools/perf/util/trace-event-info.c30
-rw-r--r--tools/perf/util/trace-event.h5
-rw-r--r--tools/perf/util/types.h10
-rw-r--r--tools/perf/util/ui/browsers/hists.c2
-rw-r--r--tools/perf/util/ui/browsers/map.c5
-rw-r--r--tools/perf/util/ui/util.c19
-rw-r--r--tools/perf/util/util.c17
-rw-r--r--tools/perf/util/util.h1
-rw-r--r--tools/perf/util/values.c10
-rw-r--r--tools/perf/util/xyarray.c20
-rw-r--r--tools/perf/util/xyarray.h20
-rw-r--r--tools/power/x86/turbostat/Makefile8
-rw-r--r--tools/power/x86/turbostat/turbostat.8172
-rw-r--r--tools/power/x86/turbostat/turbostat.c1048
-rw-r--r--tools/power/x86/x86_energy_perf_policy/Makefile8
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8104
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c325
-rw-r--r--tools/slub/slabinfo.c1364
-rwxr-xr-xtools/testing/ktest/compare-ktest-sample.pl30
-rwxr-xr-xtools/testing/ktest/ktest.pl2023
-rw-r--r--tools/testing/ktest/sample.conf622
-rw-r--r--tools/virtio/Makefile12
-rw-r--r--tools/virtio/linux/device.h2
-rw-r--r--tools/virtio/linux/slab.h2
-rw-r--r--tools/virtio/linux/virtio.h223
-rw-r--r--tools/virtio/vhost_test/Makefile2
-rw-r--r--tools/virtio/vhost_test/vhost_test.c1
-rw-r--r--tools/virtio/virtio_test.c248
152 files changed, 10129 insertions, 1736 deletions
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index b2c63309a651..6f5a498608b2 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -24,12 +24,47 @@ OPTIONS
24--input=:: 24--input=::
25 Input file name. (default: perf.data) 25 Input file name. (default: perf.data)
26 26
27-d::
28--dsos=<dso[,dso...]>::
29 Only consider symbols in these dsos.
30-s::
31--symbol=<symbol>::
32 Symbol to annotate.
33
34-f::
35--force::
36 Don't complain, do it.
37
38-v::
39--verbose::
40 Be more verbose. (Show symbol address, etc)
41
42-D::
43--dump-raw-trace::
44 Dump raw trace in ASCII.
45
46-k::
47--vmlinux=<file>::
48 vmlinux pathname.
49
50-m::
51--modules::
52 Load module symbols. WARNING: use only with -k and LIVE kernel.
53
54-l::
55--print-line::
56 Print matching source lines (may be slow).
57
58-P::
59--full-paths::
60 Don't shorten the displayed pathnames.
61
27--stdio:: Use the stdio interface. 62--stdio:: Use the stdio interface.
28 63
29--tui:: Use the TUI interface Use of --tui requires a tty, if one is not 64--tui:: Use the TUI interface Use of --tui requires a tty, if one is not
30 present, as when piping to other commands, the stdio interface is 65 present, as when piping to other commands, the stdio interface is
31 used. This interfaces starts by centering on the line with more 66 used. This interfaces starts by centering on the line with more
32 samples, TAB/UNTAB cycles thru the lines with more samples. 67 samples, TAB/UNTAB cycles through the lines with more samples.
33 68
34SEE ALSO 69SEE ALSO
35-------- 70--------
diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
index 01b642c0bf8f..5eaac6f26d51 100644
--- a/tools/perf/Documentation/perf-buildid-list.txt
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -18,6 +18,9 @@ perf report.
18 18
19OPTIONS 19OPTIONS
20------- 20-------
21-H::
22--with-hits::
23 Show only DSOs with hits.
21-i:: 24-i::
22--input=:: 25--input=::
23 Input file name. (default: perf.data) 26 Input file name. (default: perf.data)
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 20d97d84ea1c..74d7481ed7a6 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -19,6 +19,18 @@ If no parameters are passed it will assume perf.data.old and perf.data.
19 19
20OPTIONS 20OPTIONS
21------- 21-------
22-M::
23--displacement::
24 Show position displacement relative to baseline.
25
26-D::
27--dump-raw-trace::
28 Dump raw trace in ASCII.
29
30-m::
31--modules::
32 Load module symbols. WARNING: use only with -k and LIVE kernel
33
22-d:: 34-d::
23--dsos=:: 35--dsos=::
24 Only consider symbols in these dsos. CSV that understands 36 Only consider symbols in these dsos. CSV that understands
@@ -42,7 +54,7 @@ OPTIONS
42--field-separator=:: 54--field-separator=::
43 55
44 Use a special separator character and don't pad with spaces, replacing 56 Use a special separator character and don't pad with spaces, replacing
45 all occurances of this separator in symbol names (and other output) 57 all occurrences of this separator in symbol names (and other output)
46 with a '.' character, that thus it's the only non valid separator. 58 with a '.' character, that thus it's the only non valid separator.
47 59
48-v:: 60-v::
@@ -50,6 +62,13 @@ OPTIONS
50 Be verbose, for instance, show the raw counts in addition to the 62 Be verbose, for instance, show the raw counts in addition to the
51 diff. 63 diff.
52 64
65-f::
66--force::
67 Don't complain, do it.
68
69--symfs=<directory>::
70 Look for files with symbols relative to this directory.
71
53SEE ALSO 72SEE ALSO
54-------- 73--------
55linkperf:perf-record[1] 74linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index d004e19fe6d6..dd84cb2f0a88 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -22,7 +22,7 @@ There are a couple of variants of perf kvm:
22 a performance counter profile of guest os in realtime 22 a performance counter profile of guest os in realtime
23 of an arbitrary workload. 23 of an arbitrary workload.
24 24
25 'perf kvm record <command>' to record the performance couinter profile 25 'perf kvm record <command>' to record the performance counter profile
26 of an arbitrary workload and save it into a perf data file. If both 26 of an arbitrary workload and save it into a perf data file. If both
27 --host and --guest are input, the perf data file name is perf.data.kvm. 27 --host and --guest are input, the perf data file name is perf.data.kvm.
28 If there is no --host but --guest, the file name is perf.data.guest. 28 If there is no --host but --guest, the file name is perf.data.guest.
@@ -40,6 +40,12 @@ There are a couple of variants of perf kvm:
40 40
41OPTIONS 41OPTIONS
42------- 42-------
43-i::
44--input=::
45 Input file name.
46-o::
47--output::
48 Output file name.
43--host=:: 49--host=::
44 Collect host side performance profile. 50 Collect host side performance profile.
45--guest=:: 51--guest=::
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index b317102138c8..921de259ea10 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -24,6 +24,21 @@ and statistics with this 'perf lock' command.
24 24
25 'perf lock report' reports statistical data. 25 'perf lock report' reports statistical data.
26 26
27OPTIONS
28-------
29
30-i::
31--input=<file>::
32 Input file name.
33
34-v::
35--verbose::
36 Be more verbose (show symbol address, etc).
37
38-D::
39--dump-raw-trace::
40 Dump raw trace in ASCII.
41
27SEE ALSO 42SEE ALSO
28-------- 43--------
29linkperf:perf[1] 44linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 62de1b7f4e76..86b797a35aa6 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -115,9 +115,9 @@ Each probe argument follows below syntax.
115 115
116LINE SYNTAX 116LINE SYNTAX
117----------- 117-----------
118Line range is descripted by following syntax. 118Line range is described by following syntax.
119 119
120 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]" 120 "FUNC[:RLN[+NUM|-RLN2]]|SRC[:ALN[+NUM|-ALN2]]"
121 121
122FUNC specifies the function name of showing lines. 'RLN' is the start line 122FUNC specifies the function name of showing lines. 'RLN' is the start line
123number from function entry line, and 'RLN2' is the end line number. As same as 123number from function entry line, and 'RLN2' is the end line number. As same as
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index a91f9f9e6e5c..e032716c839b 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -39,19 +39,31 @@ OPTIONS
39 be passed as follows: '\mem:addr[:[r][w][x]]'. 39 be passed as follows: '\mem:addr[:[r][w][x]]'.
40 If you want to profile read-write accesses in 0x1000, just set 40 If you want to profile read-write accesses in 0x1000, just set
41 'mem:0x1000:rw'. 41 'mem:0x1000:rw'.
42
43--filter=<filter>::
44 Event filter.
45
42-a:: 46-a::
43 System-wide collection. 47--all-cpus::
48 System-wide collection from all CPUs.
44 49
45-l:: 50-l::
46 Scale counter values. 51 Scale counter values.
47 52
48-p:: 53-p::
49--pid=:: 54--pid=::
50 Record events on existing pid. 55 Record events on existing process ID.
56
57-t::
58--tid=::
59 Record events on existing thread ID.
51 60
52-r:: 61-r::
53--realtime=:: 62--realtime=::
54 Collect data with this RT SCHED_FIFO priority. 63 Collect data with this RT SCHED_FIFO priority.
64-D::
65--no-delay::
66 Collect data without buffering.
55-A:: 67-A::
56--append:: 68--append::
57 Append to the output file to do incremental profiling. 69 Append to the output file to do incremental profiling.
@@ -99,6 +111,11 @@ OPTIONS
99--data:: 111--data::
100 Sample addresses. 112 Sample addresses.
101 113
114-T::
115--timestamp::
116 Sample timestamps. Use it with 'perf report -D' to see the timestamps,
117 for instance.
118
102-n:: 119-n::
103--no-samples:: 120--no-samples::
104 Don't sample. 121 Don't sample.
@@ -109,8 +126,8 @@ Collect raw sample records from all opened counters (default for tracepoint coun
109 126
110-C:: 127-C::
111--cpu:: 128--cpu::
112Collect samples only on the list of cpus provided. Multiple CPUs can be provided as a 129Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a
113comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. 130comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
114In per-thread mode with inheritance mode on (default), samples are captured only when 131In per-thread mode with inheritance mode on (default), samples are captured only when
115the thread executes on the designated CPUs. Default is to monitor all CPUs. 132the thread executes on the designated CPUs. Default is to monitor all CPUs.
116 133
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 12052c9ed0ba..8ba03d6e5398 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -20,6 +20,11 @@ OPTIONS
20-i:: 20-i::
21--input=:: 21--input=::
22 Input file name. (default: perf.data) 22 Input file name. (default: perf.data)
23
24-v::
25--verbose::
26 Be more verbose. (show symbol address, etc)
27
23-d:: 28-d::
24--dsos=:: 29--dsos=::
25 Only consider symbols in these dsos. CSV that understands 30 Only consider symbols in these dsos. CSV that understands
@@ -27,6 +32,10 @@ OPTIONS
27-n:: 32-n::
28--show-nr-samples:: 33--show-nr-samples::
29 Show the number of samples for each symbol 34 Show the number of samples for each symbol
35
36--showcpuutilization::
37 Show sample percentage for different cpu modes.
38
30-T:: 39-T::
31--threads:: 40--threads::
32 Show per-thread event counters 41 Show per-thread event counters
@@ -39,12 +48,24 @@ OPTIONS
39 Only consider these symbols. CSV that understands 48 Only consider these symbols. CSV that understands
40 file://filename entries. 49 file://filename entries.
41 50
51-U::
52--hide-unresolved::
53 Only display entries resolved to a symbol.
54
42-s:: 55-s::
43--sort=:: 56--sort=::
44 Sort by key(s): pid, comm, dso, symbol, parent. 57 Sort by key(s): pid, comm, dso, symbol, parent.
45 58
59-p::
60--parent=<regex>::
61 regex filter to identify parent, see: '--sort parent'
62
63-x::
64--exclude-other::
65 Only display entries with parent-match.
66
46-w:: 67-w::
47--field-width=:: 68--column-widths=<width[,width...]>::
48 Force each column width to the provided list, for large terminal 69 Force each column width to the provided list, for large terminal
49 readability. 70 readability.
50 71
@@ -52,19 +73,26 @@ OPTIONS
52--field-separator=:: 73--field-separator=::
53 74
54 Use a special separator character and don't pad with spaces, replacing 75 Use a special separator character and don't pad with spaces, replacing
55 all occurances of this separator in symbol names (and other output) 76 all occurrences of this separator in symbol names (and other output)
56 with a '.' character, that thus it's the only non valid separator. 77 with a '.' character, that thus it's the only non valid separator.
57 78
79-D::
80--dump-raw-trace::
81 Dump raw trace in ASCII.
82
58-g [type,min]:: 83-g [type,min]::
59--call-graph:: 84--call-graph::
60 Display callchains using type and min percent threshold. 85 Display call chains using type and min percent threshold.
61 type can be either: 86 type can be either:
62 - flat: single column, linear exposure of callchains. 87 - flat: single column, linear exposure of call chains.
63 - graph: use a graph tree, displaying absolute overhead rates. 88 - graph: use a graph tree, displaying absolute overhead rates.
64 - fractal: like graph, but displays relative rates. Each branch of 89 - fractal: like graph, but displays relative rates. Each branch of
65 the tree is considered as a new profiled object. + 90 the tree is considered as a new profiled object. +
66 Default: fractal,0.5. 91 Default: fractal,0.5.
67 92
93--pretty=<key>::
94 Pretty printing style. key: normal, raw
95
68--stdio:: Use the stdio interface. 96--stdio:: Use the stdio interface.
69 97
70--tui:: Use the TUI interface, that is integrated with annotate and allows 98--tui:: Use the TUI interface, that is integrated with annotate and allows
@@ -72,6 +100,25 @@ OPTIONS
72 requires a tty, if one is not present, as when piping to other 100 requires a tty, if one is not present, as when piping to other
73 commands, the stdio interface is used. 101 commands, the stdio interface is used.
74 102
103-k::
104--vmlinux=<file>::
105 vmlinux pathname
106
107--kallsyms=<file>::
108 kallsyms pathname
109
110-m::
111--modules::
112 Load module symbols. WARNING: This should only be used with -k and
113 a LIVE kernel.
114
115-f::
116--force::
117 Don't complain, do it.
118
119--symfs=<directory>::
120 Look for files with symbols relative to this directory.
121
75SEE ALSO 122SEE ALSO
76-------- 123--------
77linkperf:perf-stat[1] 124linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 8417644a6166..46822d5fde1c 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -8,11 +8,11 @@ perf-sched - Tool to trace/measure scheduler properties (latencies)
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf sched' {record|latency|replay|trace} 11'perf sched' {record|latency|map|replay|trace}
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15There are four variants of perf sched: 15There are five variants of perf sched:
16 16
17 'perf sched record <command>' to record the scheduling events 17 'perf sched record <command>' to record the scheduling events
18 of an arbitrary workload. 18 of an arbitrary workload.
@@ -30,8 +30,22 @@ There are four variants of perf sched:
30 of the workload as it occurred when it was recorded - and can repeat 30 of the workload as it occurred when it was recorded - and can repeat
31 it a number of times, measuring its performance.) 31 it a number of times, measuring its performance.)
32 32
33 'perf sched map' to print a textual context-switching outline of
34 workload captured via perf sched record. Columns stand for
35 individual CPUs, and the two-letter shortcuts stand for tasks that
36 are running on a CPU. A '*' denotes the CPU that had the event, and
37 a dot signals an idle CPU.
38
33OPTIONS 39OPTIONS
34------- 40-------
41-i::
42--input=<file>::
43 Input file name. (default: perf.data)
44
45-v::
46--verbose::
47 Be more verbose. (show symbol address, etc)
48
35-D:: 49-D::
36--dump-raw-trace=:: 50--dump-raw-trace=::
37 Display verbose dump of the sched data. 51 Display verbose dump of the sched data.
diff --git a/tools/perf/Documentation/perf-trace-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index ee6525ee6d69..5bb41e55a3ac 100644
--- a/tools/perf/Documentation/perf-trace-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -1,19 +1,19 @@
1perf-trace-perl(1) 1perf-script-perl(1)
2================== 2==================
3 3
4NAME 4NAME
5---- 5----
6perf-trace-perl - Process trace data with a Perl script 6perf-script-perl - Process trace data with a Perl script
7 7
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf trace' [-s [Perl]:script[.pl] ] 11'perf script' [-s [Perl]:script[.pl] ]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15 15
16This perf trace option is used to process perf trace data using perf's 16This perf script option is used to process perf script data using perf's
17built-in Perl interpreter. It reads and processes the input file and 17built-in Perl interpreter. It reads and processes the input file and
18displays the results of the trace analysis implemented in the given 18displays the results of the trace analysis implemented in the given
19Perl script, if any. 19Perl script, if any.
@@ -21,7 +21,7 @@ Perl script, if any.
21STARTER SCRIPTS 21STARTER SCRIPTS
22--------------- 22---------------
23 23
24You can avoid reading the rest of this document by running 'perf trace 24You can avoid reading the rest of this document by running 'perf script
25-g perl' in the same directory as an existing perf.data trace file. 25-g perl' in the same directory as an existing perf.data trace file.
26That will generate a starter script containing a handler for each of 26That will generate a starter script containing a handler for each of
27the event types in the trace file; it simply prints every available 27the event types in the trace file; it simply prints every available
@@ -30,13 +30,13 @@ field for each event in the trace file.
30You can also look at the existing scripts in 30You can also look at the existing scripts in
31~/libexec/perf-core/scripts/perl for typical examples showing how to 31~/libexec/perf-core/scripts/perl for typical examples showing how to
32do basic things like aggregate event data, print results, etc. Also, 32do basic things like aggregate event data, print results, etc. Also,
33the check-perf-trace.pl script, while not interesting for its results, 33the check-perf-script.pl script, while not interesting for its results,
34attempts to exercise all of the main scripting features. 34attempts to exercise all of the main scripting features.
35 35
36EVENT HANDLERS 36EVENT HANDLERS
37-------------- 37--------------
38 38
39When perf trace is invoked using a trace script, a user-defined 39When perf script is invoked using a trace script, a user-defined
40'handler function' is called for each event in the trace. If there's 40'handler function' is called for each event in the trace. If there's
41no handler function defined for a given event type, the event is 41no handler function defined for a given event type, the event is
42ignored (or passed to a 'trace_handled' function, see below) and the 42ignored (or passed to a 'trace_handled' function, see below) and the
@@ -112,13 +112,13 @@ write a useful trace script. The sections below cover the rest.
112SCRIPT LAYOUT 112SCRIPT LAYOUT
113------------- 113-------------
114 114
115Every perf trace Perl script should start by setting up a Perl module 115Every perf script Perl script should start by setting up a Perl module
116search path and 'use'ing a few support modules (see module 116search path and 'use'ing a few support modules (see module
117descriptions below): 117descriptions below):
118 118
119---- 119----
120 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib"; 120 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/perf-script-Util/lib";
121 use lib "./Perf-Trace-Util/lib"; 121 use lib "./perf-script-Util/lib";
122 use Perf::Trace::Core; 122 use Perf::Trace::Core;
123 use Perf::Trace::Context; 123 use Perf::Trace::Context;
124 use Perf::Trace::Util; 124 use Perf::Trace::Util;
@@ -162,7 +162,7 @@ sub trace_unhandled
162---- 162----
163 163
164The remaining sections provide descriptions of each of the available 164The remaining sections provide descriptions of each of the available
165built-in perf trace Perl modules and their associated functions. 165built-in perf script Perl modules and their associated functions.
166 166
167AVAILABLE MODULES AND FUNCTIONS 167AVAILABLE MODULES AND FUNCTIONS
168------------------------------- 168-------------------------------
@@ -170,7 +170,7 @@ AVAILABLE MODULES AND FUNCTIONS
170The following sections describe the functions and variables available 170The following sections describe the functions and variables available
171via the various Perf::Trace::* Perl modules. To use the functions and 171via the various Perf::Trace::* Perl modules. To use the functions and
172variables from the given module, add the corresponding 'use 172variables from the given module, add the corresponding 'use
173Perf::Trace::XXX' line to your perf trace script. 173Perf::Trace::XXX' line to your perf script script.
174 174
175Perf::Trace::Core Module 175Perf::Trace::Core Module
176~~~~~~~~~~~~~~~~~~~~~~~~ 176~~~~~~~~~~~~~~~~~~~~~~~~
@@ -204,7 +204,7 @@ argument.
204Perf::Trace::Util Module 204Perf::Trace::Util Module
205~~~~~~~~~~~~~~~~~~~~~~~~ 205~~~~~~~~~~~~~~~~~~~~~~~~
206 206
207Various utility functions for use with perf trace: 207Various utility functions for use with perf script:
208 208
209 nsecs($secs, $nsecs) - returns total nsecs given secs/nsecs pair 209 nsecs($secs, $nsecs) - returns total nsecs given secs/nsecs pair
210 nsecs_secs($nsecs) - returns whole secs portion given nsecs 210 nsecs_secs($nsecs) - returns whole secs portion given nsecs
@@ -214,4 +214,4 @@ Various utility functions for use with perf trace:
214 214
215SEE ALSO 215SEE ALSO
216-------- 216--------
217linkperf:perf-trace[1] 217linkperf:perf-script[1]
diff --git a/tools/perf/Documentation/perf-trace-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 693be804dd3d..36b38277422c 100644
--- a/tools/perf/Documentation/perf-trace-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -1,19 +1,19 @@
1perf-trace-python(1) 1perf-script-python(1)
2==================== 2====================
3 3
4NAME 4NAME
5---- 5----
6perf-trace-python - Process trace data with a Python script 6perf-script-python - Process trace data with a Python script
7 7
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf trace' [-s [Python]:script[.py] ] 11'perf script' [-s [Python]:script[.py] ]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15 15
16This perf trace option is used to process perf trace data using perf's 16This perf script option is used to process perf script data using perf's
17built-in Python interpreter. It reads and processes the input file and 17built-in Python interpreter. It reads and processes the input file and
18displays the results of the trace analysis implemented in the given 18displays the results of the trace analysis implemented in the given
19Python script, if any. 19Python script, if any.
@@ -23,15 +23,15 @@ A QUICK EXAMPLE
23 23
24This section shows the process, start to finish, of creating a working 24This section shows the process, start to finish, of creating a working
25Python script that aggregates and extracts useful information from a 25Python script that aggregates and extracts useful information from a
26raw perf trace stream. You can avoid reading the rest of this 26raw perf script stream. You can avoid reading the rest of this
27document if an example is enough for you; the rest of the document 27document if an example is enough for you; the rest of the document
28provides more details on each step and lists the library functions 28provides more details on each step and lists the library functions
29available to script writers. 29available to script writers.
30 30
31This example actually details the steps that were used to create the 31This example actually details the steps that were used to create the
32'syscall-counts' script you see when you list the available perf trace 32'syscall-counts' script you see when you list the available perf script
33scripts via 'perf trace -l'. As such, this script also shows how to 33scripts via 'perf script -l'. As such, this script also shows how to
34integrate your script into the list of general-purpose 'perf trace' 34integrate your script into the list of general-purpose 'perf script'
35scripts listed by that command. 35scripts listed by that command.
36 36
37The syscall-counts script is a simple script, but demonstrates all the 37The syscall-counts script is a simple script, but demonstrates all the
@@ -105,31 +105,31 @@ That single stream will be recorded in a file in the current directory
105called perf.data. 105called perf.data.
106 106
107Once we have a perf.data file containing our data, we can use the -g 107Once we have a perf.data file containing our data, we can use the -g
108'perf trace' option to generate a Python script that will contain a 108'perf script' option to generate a Python script that will contain a
109callback handler for each event type found in the perf.data trace 109callback handler for each event type found in the perf.data trace
110stream (for more details, see the STARTER SCRIPTS section). 110stream (for more details, see the STARTER SCRIPTS section).
111 111
112---- 112----
113# perf trace -g python 113# perf script -g python
114generated Python script: perf-trace.py 114generated Python script: perf-script.py
115 115
116The output file created also in the current directory is named 116The output file created also in the current directory is named
117perf-trace.py. Here's the file in its entirety: 117perf-script.py. Here's the file in its entirety:
118 118
119# perf trace event handlers, generated by perf trace -g python 119# perf script event handlers, generated by perf script -g python
120# Licensed under the terms of the GNU GPL License version 2 120# Licensed under the terms of the GNU GPL License version 2
121 121
122# The common_* event handler fields are the most useful fields common to 122# The common_* event handler fields are the most useful fields common to
123# all events. They don't necessarily correspond to the 'common_*' fields 123# all events. They don't necessarily correspond to the 'common_*' fields
124# in the format files. Those fields not available as handler params can 124# in the format files. Those fields not available as handler params can
125# be retrieved using Python functions of the form common_*(context). 125# be retrieved using Python functions of the form common_*(context).
126# See the perf-trace-python Documentation for the list of available functions. 126# See the perf-script-python Documentation for the list of available functions.
127 127
128import os 128import os
129import sys 129import sys
130 130
131sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 131sys.path.append(os.environ['PERF_EXEC_PATH'] + \
132 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 132 '/scripts/python/perf-script-Util/lib/Perf/Trace')
133 133
134from perf_trace_context import * 134from perf_trace_context import *
135from Core import * 135from Core import *
@@ -160,7 +160,7 @@ def print_header(event_name, cpu, secs, nsecs, pid, comm):
160---- 160----
161 161
162At the top is a comment block followed by some import statements and a 162At the top is a comment block followed by some import statements and a
163path append which every perf trace script should include. 163path append which every perf script script should include.
164 164
165Following that are a couple generated functions, trace_begin() and 165Following that are a couple generated functions, trace_begin() and
166trace_end(), which are called at the beginning and the end of the 166trace_end(), which are called at the beginning and the end of the
@@ -189,8 +189,8 @@ simply a utility function used for that purpose. Let's rename the
189script and run it to see the default output: 189script and run it to see the default output:
190 190
191---- 191----
192# mv perf-trace.py syscall-counts.py 192# mv perf-script.py syscall-counts.py
193# perf trace -s syscall-counts.py 193# perf script -s syscall-counts.py
194 194
195raw_syscalls__sys_enter 1 00840.847582083 7506 perf id=1, args= 195raw_syscalls__sys_enter 1 00840.847582083 7506 perf id=1, args=
196raw_syscalls__sys_enter 1 00840.847595764 7506 perf id=1, args= 196raw_syscalls__sys_enter 1 00840.847595764 7506 perf id=1, args=
@@ -216,7 +216,7 @@ import os
216import sys 216import sys
217 217
218sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 218sys.path.append(os.environ['PERF_EXEC_PATH'] + \
219 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 219 '/scripts/python/perf-script-Util/lib/Perf/Trace')
220 220
221from perf_trace_context import * 221from perf_trace_context import *
222from Core import * 222from Core import *
@@ -279,7 +279,7 @@ import os
279import sys 279import sys
280 280
281sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 281sys.path.append(os.environ['PERF_EXEC_PATH'] + \
282 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 282 '/scripts/python/perf-script-Util/lib/Perf/Trace')
283 283
284from perf_trace_context import * 284from perf_trace_context import *
285from Core import * 285from Core import *
@@ -315,7 +315,7 @@ def print_syscall_totals():
315 315
316The script can be run just as before: 316The script can be run just as before:
317 317
318 # perf trace -s syscall-counts.py 318 # perf script -s syscall-counts.py
319 319
320So those are the essential steps in writing and running a script. The 320So those are the essential steps in writing and running a script. The
321process can be generalized to any tracepoint or set of tracepoints 321process can be generalized to any tracepoint or set of tracepoints
@@ -324,17 +324,17 @@ interested in by looking at the list of available events shown by
324'perf list' and/or look in /sys/kernel/debug/tracing events for 324'perf list' and/or look in /sys/kernel/debug/tracing events for
325detailed event and field info, record the corresponding trace data 325detailed event and field info, record the corresponding trace data
326using 'perf record', passing it the list of interesting events, 326using 'perf record', passing it the list of interesting events,
327generate a skeleton script using 'perf trace -g python' and modify the 327generate a skeleton script using 'perf script -g python' and modify the
328code to aggregate and display it for your particular needs. 328code to aggregate and display it for your particular needs.
329 329
330After you've done that you may end up with a general-purpose script 330After you've done that you may end up with a general-purpose script
331that you want to keep around and have available for future use. By 331that you want to keep around and have available for future use. By
332writing a couple of very simple shell scripts and putting them in the 332writing a couple of very simple shell scripts and putting them in the
333right place, you can have your script listed alongside the other 333right place, you can have your script listed alongside the other
334scripts listed by the 'perf trace -l' command e.g.: 334scripts listed by the 'perf script -l' command e.g.:
335 335
336---- 336----
337root@tropicana:~# perf trace -l 337root@tropicana:~# perf script -l
338List of available trace scripts: 338List of available trace scripts:
339 workqueue-stats workqueue stats (ins/exe/create/destroy) 339 workqueue-stats workqueue stats (ins/exe/create/destroy)
340 wakeup-latency system-wide min/max/avg wakeup latency 340 wakeup-latency system-wide min/max/avg wakeup latency
@@ -365,14 +365,14 @@ perf record -a -e raw_syscalls:sys_enter
365The 'report' script is also a shell script with the same base name as 365The 'report' script is also a shell script with the same base name as
366your script, but with -report appended. It should also be located in 366your script, but with -report appended. It should also be located in
367the perf/scripts/python/bin directory. In that script, you write the 367the perf/scripts/python/bin directory. In that script, you write the
368'perf trace -s' command-line needed for running your script: 368'perf script -s' command-line needed for running your script:
369 369
370---- 370----
371# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-report 371# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-report
372 372
373#!/bin/bash 373#!/bin/bash
374# description: system-wide syscall counts 374# description: system-wide syscall counts
375perf trace -s ~/libexec/perf-core/scripts/python/syscall-counts.py 375perf script -s ~/libexec/perf-core/scripts/python/syscall-counts.py
376---- 376----
377 377
378Note that the location of the Python script given in the shell script 378Note that the location of the Python script given in the shell script
@@ -390,17 +390,17 @@ total 32
390drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 . 390drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
391drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 .. 391drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
392drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin 392drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin
393-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-trace.py 393-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-script.py
394drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 Perf-Trace-Util 394drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 perf-script-Util
395-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py 395-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py
396---- 396----
397 397
398Once you've done that (don't forget to do a new 'make install', 398Once you've done that (don't forget to do a new 'make install',
399otherwise your script won't show up at run-time), 'perf trace -l' 399otherwise your script won't show up at run-time), 'perf script -l'
400should show a new entry for your script: 400should show a new entry for your script:
401 401
402---- 402----
403root@tropicana:~# perf trace -l 403root@tropicana:~# perf script -l
404List of available trace scripts: 404List of available trace scripts:
405 workqueue-stats workqueue stats (ins/exe/create/destroy) 405 workqueue-stats workqueue stats (ins/exe/create/destroy)
406 wakeup-latency system-wide min/max/avg wakeup latency 406 wakeup-latency system-wide min/max/avg wakeup latency
@@ -409,19 +409,19 @@ List of available trace scripts:
409 syscall-counts system-wide syscall counts 409 syscall-counts system-wide syscall counts
410---- 410----
411 411
412You can now perform the record step via 'perf trace record': 412You can now perform the record step via 'perf script record':
413 413
414 # perf trace record syscall-counts 414 # perf script record syscall-counts
415 415
416and display the output using 'perf trace report': 416and display the output using 'perf script report':
417 417
418 # perf trace report syscall-counts 418 # perf script report syscall-counts
419 419
420STARTER SCRIPTS 420STARTER SCRIPTS
421--------------- 421---------------
422 422
423You can quickly get started writing a script for a particular set of 423You can quickly get started writing a script for a particular set of
424trace data by generating a skeleton script using 'perf trace -g 424trace data by generating a skeleton script using 'perf script -g
425python' in the same directory as an existing perf.data trace file. 425python' in the same directory as an existing perf.data trace file.
426That will generate a starter script containing a handler for each of 426That will generate a starter script containing a handler for each of
427the event types in the trace file; it simply prints every available 427the event types in the trace file; it simply prints every available
@@ -430,13 +430,13 @@ field for each event in the trace file.
430You can also look at the existing scripts in 430You can also look at the existing scripts in
431~/libexec/perf-core/scripts/python for typical examples showing how to 431~/libexec/perf-core/scripts/python for typical examples showing how to
432do basic things like aggregate event data, print results, etc. Also, 432do basic things like aggregate event data, print results, etc. Also,
433the check-perf-trace.py script, while not interesting for its results, 433the check-perf-script.py script, while not interesting for its results,
434attempts to exercise all of the main scripting features. 434attempts to exercise all of the main scripting features.
435 435
436EVENT HANDLERS 436EVENT HANDLERS
437-------------- 437--------------
438 438
439When perf trace is invoked using a trace script, a user-defined 439When perf script is invoked using a trace script, a user-defined
440'handler function' is called for each event in the trace. If there's 440'handler function' is called for each event in the trace. If there's
441no handler function defined for a given event type, the event is 441no handler function defined for a given event type, the event is
442ignored (or passed to a 'trace_handled' function, see below) and the 442ignored (or passed to a 'trace_handled' function, see below) and the
@@ -510,7 +510,7 @@ write a useful trace script. The sections below cover the rest.
510SCRIPT LAYOUT 510SCRIPT LAYOUT
511------------- 511-------------
512 512
513Every perf trace Python script should start by setting up a Python 513Every perf script Python script should start by setting up a Python
514module search path and 'import'ing a few support modules (see module 514module search path and 'import'ing a few support modules (see module
515descriptions below): 515descriptions below):
516 516
@@ -519,7 +519,7 @@ descriptions below):
519 import sys 519 import sys
520 520
521 sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 521 sys.path.append(os.environ['PERF_EXEC_PATH'] + \
522 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 522 '/scripts/python/perf-script-Util/lib/Perf/Trace')
523 523
524 from perf_trace_context import * 524 from perf_trace_context import *
525 from Core import * 525 from Core import *
@@ -559,15 +559,15 @@ def trace_unhandled(event_name, context, common_cpu, common_secs,
559---- 559----
560 560
561The remaining sections provide descriptions of each of the available 561The remaining sections provide descriptions of each of the available
562built-in perf trace Python modules and their associated functions. 562built-in perf script Python modules and their associated functions.
563 563
564AVAILABLE MODULES AND FUNCTIONS 564AVAILABLE MODULES AND FUNCTIONS
565------------------------------- 565-------------------------------
566 566
567The following sections describe the functions and variables available 567The following sections describe the functions and variables available
568via the various perf trace Python modules. To use the functions and 568via the various perf script Python modules. To use the functions and
569variables from the given module, add the corresponding 'from XXXX 569variables from the given module, add the corresponding 'from XXXX
570import' line to your perf trace script. 570import' line to your perf script script.
571 571
572Core.py Module 572Core.py Module
573~~~~~~~~~~~~~~ 573~~~~~~~~~~~~~~
@@ -610,7 +610,7 @@ argument.
610Util.py Module 610Util.py Module
611~~~~~~~~~~~~~~ 611~~~~~~~~~~~~~~
612 612
613Various utility functions for use with perf trace: 613Various utility functions for use with perf script:
614 614
615 nsecs(secs, nsecs) - returns total nsecs given secs/nsecs pair 615 nsecs(secs, nsecs) - returns total nsecs given secs/nsecs pair
616 nsecs_secs(nsecs) - returns whole secs portion given nsecs 616 nsecs_secs(nsecs) - returns whole secs portion given nsecs
@@ -620,4 +620,4 @@ Various utility functions for use with perf trace:
620 620
621SEE ALSO 621SEE ALSO
622-------- 622--------
623linkperf:perf-trace[1] 623linkperf:perf-script[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
new file mode 100644
index 000000000000..29ad94293cd2
--- /dev/null
+++ b/tools/perf/Documentation/perf-script.txt
@@ -0,0 +1,118 @@
1perf-script(1)
2=============
3
4NAME
5----
6perf-script - Read perf.data (created by perf record) and display trace output
7
8SYNOPSIS
9--------
10[verse]
11'perf script' [<options>]
12'perf script' [<options>] record <script> [<record-options>] <command>
13'perf script' [<options>] report <script> [script-args]
14'perf script' [<options>] <script> <required-script-args> [<record-options>] <command>
15'perf script' [<options>] <top-script> [script-args]
16
17DESCRIPTION
18-----------
19This command reads the input file and displays the trace recorded.
20
21There are several variants of perf script:
22
23 'perf script' to see a detailed trace of the workload that was
24 recorded.
25
26 You can also run a set of pre-canned scripts that aggregate and
27 summarize the raw trace data in various ways (the list of scripts is
28 available via 'perf script -l'). The following variants allow you to
29 record and run those scripts:
30
31 'perf script record <script> <command>' to record the events required
32 for 'perf script report'. <script> is the name displayed in the
33 output of 'perf script --list' i.e. the actual script name minus any
34 language extension. If <command> is not specified, the events are
35 recorded using the -a (system-wide) 'perf record' option.
36
37 'perf script report <script> [args]' to run and display the results
38 of <script>. <script> is the name displayed in the output of 'perf
39 trace --list' i.e. the actual script name minus any language
40 extension. The perf.data output from a previous run of 'perf script
41 record <script>' is used and should be present for this command to
42 succeed. [args] refers to the (mainly optional) args expected by
43 the script.
44
45 'perf script <script> <required-script-args> <command>' to both
46 record the events required for <script> and to run the <script>
47 using 'live-mode' i.e. without writing anything to disk. <script>
48 is the name displayed in the output of 'perf script --list' i.e. the
49 actual script name minus any language extension. If <command> is
50 not specified, the events are recorded using the -a (system-wide)
51 'perf record' option. If <script> has any required args, they
52 should be specified before <command>. This mode doesn't allow for
53 optional script args to be specified; if optional script args are
54 desired, they can be specified using separate 'perf script record'
55 and 'perf script report' commands, with the stdout of the record step
56 piped to the stdin of the report script, using the '-o -' and '-i -'
57 options of the corresponding commands.
58
59 'perf script <top-script>' to both record the events required for
60 <top-script> and to run the <top-script> using 'live-mode'
61 i.e. without writing anything to disk. <top-script> is the name
62 displayed in the output of 'perf script --list' i.e. the actual
63 script name minus any language extension; a <top-script> is defined
64 as any script name ending with the string 'top'.
65
66 [<record-options>] can be passed to the record steps of 'perf script
67 record' and 'live-mode' variants; this isn't possible however for
68 <top-script> 'live-mode' or 'perf script report' variants.
69
70 See the 'SEE ALSO' section for links to language-specific
71 information on how to write and run your own trace scripts.
72
73OPTIONS
74-------
75<command>...::
76 Any command you can specify in a shell.
77
78-D::
79--dump-raw-script=::
80 Display verbose dump of the trace data.
81
82-L::
83--Latency=::
84 Show latency attributes (irqs/preemption disabled, etc).
85
86-l::
87--list=::
88 Display a list of available trace scripts.
89
90-s ['lang']::
91--script=::
92 Process trace data with the given script ([lang]:script[.ext]).
93 If the string 'lang' is specified in place of a script name, a
94 list of supported languages will be displayed instead.
95
96-g::
97--gen-script=::
98 Generate perf-script.[ext] starter script for given language,
99 using current perf.data.
100
101-a::
102 Force system-wide collection. Scripts run without a <command>
103 normally use -a by default, while scripts run with a <command>
104 normally don't - this option allows the latter to be run in
105 system-wide mode.
106
107-i::
108--input=::
109 Input file name.
110
111-d::
112--debug-mode::
113 Do various checks like samples ordering and lost events.
114
115SEE ALSO
116--------
117linkperf:perf-record[1], linkperf:perf-script-perl[1],
118linkperf:perf-script-python[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 4b3a2d46b437..b6da7affbbee 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -8,8 +8,8 @@ perf-stat - Run a command and gather performance counter statistics
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] <command> 11'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
12'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] -- <command> [<options>] 12'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
13 13
14DESCRIPTION 14DESCRIPTION
15----------- 15-----------
@@ -35,24 +35,54 @@ OPTIONS
35 child tasks do not inherit counters 35 child tasks do not inherit counters
36-p:: 36-p::
37--pid=<pid>:: 37--pid=<pid>::
38 stat events on existing pid 38 stat events on existing process id
39
40-t::
41--tid=<tid>::
42 stat events on existing thread id
43
39 44
40-a:: 45-a::
41 system-wide collection 46--all-cpus::
47 system-wide collection from all CPUs
42 48
43-c:: 49-c::
44 scale counter values 50--scale::
51 scale/normalize counter values
52
53-r::
54--repeat=<n>::
55 repeat command and print average + stddev (max: 100)
45 56
46-B:: 57-B::
58--big-num::
47 print large numbers with thousands' separators according to locale 59 print large numbers with thousands' separators according to locale
48 60
49-C:: 61-C::
50--cpu=:: 62--cpu=::
51Count only on the list of cpus provided. Multiple CPUs can be provided as a 63Count only on the list of CPUs provided. Multiple CPUs can be provided as a
52comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. 64comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
53In per-thread mode, this option is ignored. The -a option is still necessary 65In per-thread mode, this option is ignored. The -a option is still necessary
54to activate system-wide monitoring. Default is to count on all CPUs. 66to activate system-wide monitoring. Default is to count on all CPUs.
55 67
68-A::
69--no-aggr::
70Do not aggregate counts across all monitored CPUs in system-wide mode (-a).
71This option is only valid in system-wide mode.
72
73-n::
74--null::
75 null run - don't start any counters
76
77-v::
78--verbose::
79 be more verbose (show counter open errors, etc)
80
81-x SEP::
82--field-separator SEP::
83print counts using a CSV-style output to make it easy to import directly into
84spreadsheets. Columns are separated by the string specified in SEP.
85
56EXAMPLES 86EXAMPLES
57-------- 87--------
58 88
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index 1c4b5f5b7f71..2c3b462f64b0 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -12,7 +12,7 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command does assorted sanity tests, initially thru linked routines but 15This command does assorted sanity tests, initially through linked routines but
16also will look for a directory with more tests in the form of scripts. 16also will look for a directory with more tests in the form of scripts.
17 17
18OPTIONS 18OPTIONS
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 4b1788355eca..d7b79e2ba2ad 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -38,6 +38,8 @@ OPTIONS
38--process:: 38--process::
39 Select the processes to display, by name or PID 39 Select the processes to display, by name or PID
40 40
41--symfs=<directory>::
42 Look for files with symbols relative to this directory.
41 43
42SEE ALSO 44SEE ALSO
43-------- 45--------
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 1f9687663f2a..f6eb1cdafb77 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -12,7 +12,7 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command generates and displays a performance counter profile in realtime. 15This command generates and displays a performance counter profile in real time.
16 16
17 17
18OPTIONS 18OPTIONS
@@ -27,8 +27,8 @@ OPTIONS
27 27
28-C <cpu-list>:: 28-C <cpu-list>::
29--cpu=<cpu>:: 29--cpu=<cpu>::
30Monitor only on the list of cpus provided. Multiple CPUs can be provided as a 30Monitor only on the list of CPUs provided. Multiple CPUs can be provided as a
31comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. 31comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
32Default is to monitor all CPUS. 32Default is to monitor all CPUS.
33 33
34-d <seconds>:: 34-d <seconds>::
@@ -50,6 +50,10 @@ Default is to monitor all CPUS.
50--count-filter=<count>:: 50--count-filter=<count>::
51 Only display functions with more events than this. 51 Only display functions with more events than this.
52 52
53-g::
54--group::
55 Put the counters into a counter group.
56
53-F <freq>:: 57-F <freq>::
54--freq=<freq>:: 58--freq=<freq>::
55 Profile at this frequency. 59 Profile at this frequency.
@@ -68,7 +72,11 @@ Default is to monitor all CPUS.
68 72
69-p <pid>:: 73-p <pid>::
70--pid=<pid>:: 74--pid=<pid>::
71 Profile events on existing pid. 75 Profile events on existing Process ID.
76
77-t <tid>::
78--tid=<tid>::
79 Profile events on existing thread ID.
72 80
73-r <priority>:: 81-r <priority>::
74--realtime=<priority>:: 82--realtime=<priority>::
@@ -78,6 +86,18 @@ Default is to monitor all CPUS.
78--sym-annotate=<symbol>:: 86--sym-annotate=<symbol>::
79 Annotate this symbol. 87 Annotate this symbol.
80 88
89-K::
90--hide_kernel_symbols::
91 Hide kernel symbols.
92
93-U::
94--hide_user_symbols::
95 Hide user symbols.
96
97-D::
98--dump-symtab::
99 Dump the symbol table used for profiling.
100
81-v:: 101-v::
82--verbose:: 102--verbose::
83 Be more verbose (show counter open errors, etc). 103 Be more verbose (show counter open errors, etc).
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
deleted file mode 100644
index 122ec9dc4853..000000000000
--- a/tools/perf/Documentation/perf-trace.txt
+++ /dev/null
@@ -1,70 +0,0 @@
1perf-trace(1)
2=============
3
4NAME
5----
6perf-trace - Read perf.data (created by perf record) and display trace output
7
8SYNOPSIS
9--------
10[verse]
11'perf trace' {record <script> | report <script> [args] }
12
13DESCRIPTION
14-----------
15This command reads the input file and displays the trace recorded.
16
17There are several variants of perf trace:
18
19 'perf trace' to see a detailed trace of the workload that was
20 recorded.
21
22 You can also run a set of pre-canned scripts that aggregate and
23 summarize the raw trace data in various ways (the list of scripts is
24 available via 'perf trace -l'). The following variants allow you to
25 record and run those scripts:
26
27 'perf trace record <script>' to record the events required for 'perf
28 trace report'. <script> is the name displayed in the output of
29 'perf trace --list' i.e. the actual script name minus any language
30 extension.
31
32 'perf trace report <script>' to run and display the results of
33 <script>. <script> is the name displayed in the output of 'perf
34 trace --list' i.e. the actual script name minus any language
35 extension. The perf.data output from a previous run of 'perf trace
36 record <script>' is used and should be present for this command to
37 succeed.
38
39 See the 'SEE ALSO' section for links to language-specific
40 information on how to write and run your own trace scripts.
41
42OPTIONS
43-------
44-D::
45--dump-raw-trace=::
46 Display verbose dump of the trace data.
47
48-L::
49--Latency=::
50 Show latency attributes (irqs/preemption disabled, etc).
51
52-l::
53--list=::
54 Display a list of available trace scripts.
55
56-s ['lang']::
57--script=::
58 Process trace data with the given script ([lang]:script[.ext]).
59 If the string 'lang' is specified in place of a script name, a
60 list of supported languages will be displayed instead.
61
62-g::
63--gen-script=::
64 Generate perf-trace.[ext] starter script for given language,
65 using current perf.data.
66
67SEE ALSO
68--------
69linkperf:perf-record[1], linkperf:perf-trace-perl[1],
70linkperf:perf-trace-python[1]
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 8c7fc0c8f0b8..c12659d8cb26 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -7,6 +7,7 @@ include/linux/stringify.h
7lib/rbtree.c 7lib/rbtree.c
8include/linux/swab.h 8include/linux/swab.h
9arch/*/include/asm/unistd*.h 9arch/*/include/asm/unistd*.h
10arch/*/lib/memcpy*.S
10include/linux/poison.h 11include/linux/poison.h
11include/linux/magic.h 12include/linux/magic.h
12include/linux/hw_breakpoint.h 13include/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index d1db0f676a4b..7141c42e1469 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -185,7 +185,10 @@ ifeq ($(ARCH),i386)
185 ARCH := x86 185 ARCH := x86
186endif 186endif
187ifeq ($(ARCH),x86_64) 187ifeq ($(ARCH),x86_64)
188 RAW_ARCH := x86_64
188 ARCH := x86 189 ARCH := x86
190 ARCH_CFLAGS := -DARCH_X86_64
191 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S
189endif 192endif
190 193
191# CFLAGS and LDFLAGS are for the users to override from the command line. 194# CFLAGS and LDFLAGS are for the users to override from the command line.
@@ -201,13 +204,11 @@ EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
201EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self 204EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self
202EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked 205EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked
203EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls 206EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls
204EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstack-protector
205EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3 207EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3
206EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default 208EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default
207EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum 209EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum
208EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers 210EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers
209EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef 211EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef
210EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wvolatile-register-var
211EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings 212EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings
212EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast 213EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast
213EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations 214EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations
@@ -224,7 +225,7 @@ ifndef PERF_DEBUG
224 CFLAGS_OPTIMIZE = -O6 225 CFLAGS_OPTIMIZE = -O6
225endif 226endif
226 227
227CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 228CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
228EXTLIBS = -lpthread -lrt -lelf -lm 229EXTLIBS = -lpthread -lrt -lelf -lm
229ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 230ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
230ALL_LDFLAGS = $(LDFLAGS) 231ALL_LDFLAGS = $(LDFLAGS)
@@ -291,6 +292,13 @@ ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
291 CFLAGS := $(CFLAGS) -fstack-protector-all 292 CFLAGS := $(CFLAGS) -fstack-protector-all
292endif 293endif
293 294
295ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
296 CFLAGS := $(CFLAGS) -Wstack-protector
297endif
298
299ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
300 CFLAGS := $(CFLAGS) -Wvolatile-register-var
301endif
294 302
295### --- END CONFIGURATION SECTION --- 303### --- END CONFIGURATION SECTION ---
296 304
@@ -375,6 +383,7 @@ LIB_H += util/include/linux/prefetch.h
375LIB_H += util/include/linux/rbtree.h 383LIB_H += util/include/linux/rbtree.h
376LIB_H += util/include/linux/string.h 384LIB_H += util/include/linux/string.h
377LIB_H += util/include/linux/types.h 385LIB_H += util/include/linux/types.h
386LIB_H += util/include/linux/linkage.h
378LIB_H += util/include/asm/asm-offsets.h 387LIB_H += util/include/asm/asm-offsets.h
379LIB_H += util/include/asm/bug.h 388LIB_H += util/include/asm/bug.h
380LIB_H += util/include/asm/byteorder.h 389LIB_H += util/include/asm/byteorder.h
@@ -383,6 +392,8 @@ LIB_H += util/include/asm/swab.h
383LIB_H += util/include/asm/system.h 392LIB_H += util/include/asm/system.h
384LIB_H += util/include/asm/uaccess.h 393LIB_H += util/include/asm/uaccess.h
385LIB_H += util/include/dwarf-regs.h 394LIB_H += util/include/dwarf-regs.h
395LIB_H += util/include/asm/dwarf2.h
396LIB_H += util/include/asm/cpufeature.h
386LIB_H += perf.h 397LIB_H += perf.h
387LIB_H += util/cache.h 398LIB_H += util/cache.h
388LIB_H += util/callchain.h 399LIB_H += util/callchain.h
@@ -390,6 +401,7 @@ LIB_H += util/build-id.h
390LIB_H += util/debug.h 401LIB_H += util/debug.h
391LIB_H += util/debugfs.h 402LIB_H += util/debugfs.h
392LIB_H += util/event.h 403LIB_H += util/event.h
404LIB_H += util/evsel.h
393LIB_H += util/exec_cmd.h 405LIB_H += util/exec_cmd.h
394LIB_H += util/types.h 406LIB_H += util/types.h
395LIB_H += util/levenshtein.h 407LIB_H += util/levenshtein.h
@@ -398,6 +410,7 @@ LIB_H += util/parse-options.h
398LIB_H += util/parse-events.h 410LIB_H += util/parse-events.h
399LIB_H += util/quote.h 411LIB_H += util/quote.h
400LIB_H += util/util.h 412LIB_H += util/util.h
413LIB_H += util/xyarray.h
401LIB_H += util/header.h 414LIB_H += util/header.h
402LIB_H += util/help.h 415LIB_H += util/help.h
403LIB_H += util/session.h 416LIB_H += util/session.h
@@ -417,6 +430,7 @@ LIB_H += util/probe-finder.h
417LIB_H += util/probe-event.h 430LIB_H += util/probe-event.h
418LIB_H += util/pstack.h 431LIB_H += util/pstack.h
419LIB_H += util/cpumap.h 432LIB_H += util/cpumap.h
433LIB_H += $(ARCH_INCLUDE)
420 434
421LIB_OBJS += $(OUTPUT)util/abspath.o 435LIB_OBJS += $(OUTPUT)util/abspath.o
422LIB_OBJS += $(OUTPUT)util/alias.o 436LIB_OBJS += $(OUTPUT)util/alias.o
@@ -426,6 +440,7 @@ LIB_OBJS += $(OUTPUT)util/ctype.o
426LIB_OBJS += $(OUTPUT)util/debugfs.o 440LIB_OBJS += $(OUTPUT)util/debugfs.o
427LIB_OBJS += $(OUTPUT)util/environment.o 441LIB_OBJS += $(OUTPUT)util/environment.o
428LIB_OBJS += $(OUTPUT)util/event.o 442LIB_OBJS += $(OUTPUT)util/event.o
443LIB_OBJS += $(OUTPUT)util/evsel.o
429LIB_OBJS += $(OUTPUT)util/exec_cmd.o 444LIB_OBJS += $(OUTPUT)util/exec_cmd.o
430LIB_OBJS += $(OUTPUT)util/help.o 445LIB_OBJS += $(OUTPUT)util/help.o
431LIB_OBJS += $(OUTPUT)util/levenshtein.o 446LIB_OBJS += $(OUTPUT)util/levenshtein.o
@@ -463,6 +478,7 @@ LIB_OBJS += $(OUTPUT)util/sort.o
463LIB_OBJS += $(OUTPUT)util/hist.o 478LIB_OBJS += $(OUTPUT)util/hist.o
464LIB_OBJS += $(OUTPUT)util/probe-event.o 479LIB_OBJS += $(OUTPUT)util/probe-event.o
465LIB_OBJS += $(OUTPUT)util/util.o 480LIB_OBJS += $(OUTPUT)util/util.o
481LIB_OBJS += $(OUTPUT)util/xyarray.o
466LIB_OBJS += $(OUTPUT)util/cpumap.o 482LIB_OBJS += $(OUTPUT)util/cpumap.o
467 483
468BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 484BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
@@ -472,6 +488,9 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
472# Benchmark modules 488# Benchmark modules
473BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o 489BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
474BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o 490BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
491ifeq ($(RAW_ARCH),x86_64)
492BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
493endif
475BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 494BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
476 495
477BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 496BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
@@ -485,7 +504,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-report.o
485BUILTIN_OBJS += $(OUTPUT)builtin-stat.o 504BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
486BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o 505BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
487BUILTIN_OBJS += $(OUTPUT)builtin-top.o 506BUILTIN_OBJS += $(OUTPUT)builtin-top.o
488BUILTIN_OBJS += $(OUTPUT)builtin-trace.o 507BUILTIN_OBJS += $(OUTPUT)builtin-script.o
489BUILTIN_OBJS += $(OUTPUT)builtin-probe.o 508BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
490BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o 509BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
491BUILTIN_OBJS += $(OUTPUT)builtin-lock.o 510BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
@@ -507,7 +526,7 @@ PERFLIBS = $(LIB_FILE)
507-include config.mak 526-include config.mak
508 527
509ifndef NO_DWARF 528ifndef NO_DWARF
510FLAGS_DWARF=$(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) 529FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
511ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) 530ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
512 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 531 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
513 NO_DWARF := 1 532 NO_DWARF := 1
@@ -554,7 +573,7 @@ ifndef NO_DWARF
554ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 573ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
555 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 574 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
556else 575else
557 BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT 576 BASIC_CFLAGS += -DDWARF_SUPPORT
558 EXTLIBS += -lelf -ldw 577 EXTLIBS += -lelf -ldw
559 LIB_OBJS += $(OUTPUT)util/probe-finder.o 578 LIB_OBJS += $(OUTPUT)util/probe-finder.o
560endif # PERF_HAVE_DWARF_REGS 579endif # PERF_HAVE_DWARF_REGS
@@ -891,13 +910,14 @@ prefix_SQ = $(subst ','\'',$(prefix))
891SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) 910SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
892PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) 911PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
893 912
894LIBS = $(PERFLIBS) $(EXTLIBS) 913LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS)
895 914
896BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \ 915BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
897 $(COMPAT_CFLAGS) 916 $(COMPAT_CFLAGS)
898LIB_OBJS += $(COMPAT_OBJS) 917LIB_OBJS += $(COMPAT_OBJS)
899 918
900ALL_CFLAGS += $(BASIC_CFLAGS) 919ALL_CFLAGS += $(BASIC_CFLAGS)
920ALL_CFLAGS += $(ARCH_CFLAGS)
901ALL_LDFLAGS += $(BASIC_LDFLAGS) 921ALL_LDFLAGS += $(BASIC_LDFLAGS)
902 922
903export TAR INSTALL DESTDIR SHELL_PATH 923export TAR INSTALL DESTDIR SHELL_PATH
diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile
new file mode 100644
index 000000000000..15130b50dfe3
--- /dev/null
+++ b/tools/perf/arch/s390/Makefile
@@ -0,0 +1,4 @@
1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif
diff --git a/tools/perf/arch/s390/util/dwarf-regs.c b/tools/perf/arch/s390/util/dwarf-regs.c
new file mode 100644
index 000000000000..e19653e025fa
--- /dev/null
+++ b/tools/perf/arch/s390/util/dwarf-regs.c
@@ -0,0 +1,22 @@
1/*
2 * Mapping of DWARF debug register numbers into register names.
3 *
4 * Copyright IBM Corp. 2010
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
6 *
7 */
8
9#include <libio.h>
10#include <dwarf-regs.h>
11
12#define NUM_GPRS 16
13
14static const char *gpr_names[NUM_GPRS] = {
15 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
16 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
17};
18
19const char *get_arch_regstr(unsigned int n)
20{
21 return (n >= NUM_GPRS) ? NULL : gpr_names[n];
22}
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h
new file mode 100644
index 000000000000..a72e36cb5394
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-arch.h
@@ -0,0 +1,12 @@
1
2#ifdef ARCH_X86_64
3
4#define MEMCPY_FN(fn, name, desc) \
5 extern void *fn(void *, const void *, size_t);
6
7#include "mem-memcpy-x86-64-asm-def.h"
8
9#undef MEMCPY_FN
10
11#endif
12
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
new file mode 100644
index 000000000000..d588b87696fc
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -0,0 +1,4 @@
1
2MEMCPY_FN(__memcpy,
3 "x86-64-unrolled",
4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S")
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
new file mode 100644
index 000000000000..a57b66e853c2
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -0,0 +1,2 @@
1
2#include "../../../arch/x86/lib/memcpy_64.S"
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 38dae7465142..db82021f4b91 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -12,6 +12,7 @@
12#include "../util/parse-options.h" 12#include "../util/parse-options.h"
13#include "../util/header.h" 13#include "../util/header.h"
14#include "bench.h" 14#include "bench.h"
15#include "mem-memcpy-arch.h"
15 16
16#include <stdio.h> 17#include <stdio.h>
17#include <stdlib.h> 18#include <stdlib.h>
@@ -23,8 +24,10 @@
23 24
24static const char *length_str = "1MB"; 25static const char *length_str = "1MB";
25static const char *routine = "default"; 26static const char *routine = "default";
26static bool use_clock = false; 27static bool use_clock;
27static int clock_fd; 28static int clock_fd;
29static bool only_prefault;
30static bool no_prefault;
28 31
29static const struct option options[] = { 32static const struct option options[] = {
30 OPT_STRING('l', "length", &length_str, "1MB", 33 OPT_STRING('l', "length", &length_str, "1MB",
@@ -34,19 +37,33 @@ static const struct option options[] = {
34 "Specify routine to copy"), 37 "Specify routine to copy"),
35 OPT_BOOLEAN('c', "clock", &use_clock, 38 OPT_BOOLEAN('c', "clock", &use_clock,
36 "Use CPU clock for measuring"), 39 "Use CPU clock for measuring"),
40 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
41 "Show only the result with page faults before memcpy()"),
42 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
43 "Show only the result without page faults before memcpy()"),
37 OPT_END() 44 OPT_END()
38}; 45};
39 46
47typedef void *(*memcpy_t)(void *, const void *, size_t);
48
40struct routine { 49struct routine {
41 const char *name; 50 const char *name;
42 const char *desc; 51 const char *desc;
43 void * (*fn)(void *dst, const void *src, size_t len); 52 memcpy_t fn;
44}; 53};
45 54
46struct routine routines[] = { 55struct routine routines[] = {
47 { "default", 56 { "default",
48 "Default memcpy() provided by glibc", 57 "Default memcpy() provided by glibc",
49 memcpy }, 58 memcpy },
59#ifdef ARCH_X86_64
60
61#define MEMCPY_FN(fn, name, desc) { name, desc, fn },
62#include "mem-memcpy-x86-64-asm-def.h"
63#undef MEMCPY_FN
64
65#endif
66
50 { NULL, 67 { NULL,
51 NULL, 68 NULL,
52 NULL } 69 NULL }
@@ -89,29 +106,98 @@ static double timeval2double(struct timeval *ts)
89 (double)ts->tv_usec / (double)1000000; 106 (double)ts->tv_usec / (double)1000000;
90} 107}
91 108
109static void alloc_mem(void **dst, void **src, size_t length)
110{
111 *dst = zalloc(length);
112 if (!dst)
113 die("memory allocation failed - maybe length is too large?\n");
114
115 *src = zalloc(length);
116 if (!src)
117 die("memory allocation failed - maybe length is too large?\n");
118}
119
120static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
121{
122 u64 clock_start = 0ULL, clock_end = 0ULL;
123 void *src = NULL, *dst = NULL;
124
125 alloc_mem(&src, &dst, len);
126
127 if (prefault)
128 fn(dst, src, len);
129
130 clock_start = get_clock();
131 fn(dst, src, len);
132 clock_end = get_clock();
133
134 free(src);
135 free(dst);
136 return clock_end - clock_start;
137}
138
139static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
140{
141 struct timeval tv_start, tv_end, tv_diff;
142 void *src = NULL, *dst = NULL;
143
144 alloc_mem(&src, &dst, len);
145
146 if (prefault)
147 fn(dst, src, len);
148
149 BUG_ON(gettimeofday(&tv_start, NULL));
150 fn(dst, src, len);
151 BUG_ON(gettimeofday(&tv_end, NULL));
152
153 timersub(&tv_end, &tv_start, &tv_diff);
154
155 free(src);
156 free(dst);
157 return (double)((double)len / timeval2double(&tv_diff));
158}
159
160#define pf (no_prefault ? 0 : 1)
161
162#define print_bps(x) do { \
163 if (x < K) \
164 printf(" %14lf B/Sec", x); \
165 else if (x < K * K) \
166 printf(" %14lfd KB/Sec", x / K); \
167 else if (x < K * K * K) \
168 printf(" %14lf MB/Sec", x / K / K); \
169 else \
170 printf(" %14lf GB/Sec", x / K / K / K); \
171 } while (0)
172
92int bench_mem_memcpy(int argc, const char **argv, 173int bench_mem_memcpy(int argc, const char **argv,
93 const char *prefix __used) 174 const char *prefix __used)
94{ 175{
95 int i; 176 int i;
96 void *dst, *src; 177 size_t len;
97 size_t length; 178 double result_bps[2];
98 double bps = 0.0; 179 u64 result_clock[2];
99 struct timeval tv_start, tv_end, tv_diff;
100 u64 clock_start, clock_end, clock_diff;
101 180
102 clock_start = clock_end = clock_diff = 0ULL;
103 argc = parse_options(argc, argv, options, 181 argc = parse_options(argc, argv, options,
104 bench_mem_memcpy_usage, 0); 182 bench_mem_memcpy_usage, 0);
105 183
106 tv_diff.tv_sec = 0; 184 if (use_clock)
107 tv_diff.tv_usec = 0; 185 init_clock();
108 length = (size_t)perf_atoll((char *)length_str); 186
187 len = (size_t)perf_atoll((char *)length_str);
109 188
110 if ((s64)length <= 0) { 189 result_clock[0] = result_clock[1] = 0ULL;
190 result_bps[0] = result_bps[1] = 0.0;
191
192 if ((s64)len <= 0) {
111 fprintf(stderr, "Invalid length:%s\n", length_str); 193 fprintf(stderr, "Invalid length:%s\n", length_str);
112 return 1; 194 return 1;
113 } 195 }
114 196
197 /* same to without specifying either of prefault and no-prefault */
198 if (only_prefault && no_prefault)
199 only_prefault = no_prefault = false;
200
115 for (i = 0; routines[i].name; i++) { 201 for (i = 0; routines[i].name; i++) {
116 if (!strcmp(routines[i].name, routine)) 202 if (!strcmp(routines[i].name, routine))
117 break; 203 break;
@@ -126,61 +212,80 @@ int bench_mem_memcpy(int argc, const char **argv,
126 return 1; 212 return 1;
127 } 213 }
128 214
129 dst = zalloc(length); 215 if (bench_format == BENCH_FORMAT_DEFAULT)
130 if (!dst) 216 printf("# Copying %s Bytes ...\n\n", length_str);
131 die("memory allocation failed - maybe length is too large?\n");
132
133 src = zalloc(length);
134 if (!src)
135 die("memory allocation failed - maybe length is too large?\n");
136
137 if (bench_format == BENCH_FORMAT_DEFAULT) {
138 printf("# Copying %s Bytes from %p to %p ...\n\n",
139 length_str, src, dst);
140 }
141
142 if (use_clock) {
143 init_clock();
144 clock_start = get_clock();
145 } else {
146 BUG_ON(gettimeofday(&tv_start, NULL));
147 }
148
149 routines[i].fn(dst, src, length);
150 217
151 if (use_clock) { 218 if (!only_prefault && !no_prefault) {
152 clock_end = get_clock(); 219 /* show both of results */
153 clock_diff = clock_end - clock_start; 220 if (use_clock) {
221 result_clock[0] =
222 do_memcpy_clock(routines[i].fn, len, false);
223 result_clock[1] =
224 do_memcpy_clock(routines[i].fn, len, true);
225 } else {
226 result_bps[0] =
227 do_memcpy_gettimeofday(routines[i].fn,
228 len, false);
229 result_bps[1] =
230 do_memcpy_gettimeofday(routines[i].fn,
231 len, true);
232 }
154 } else { 233 } else {
155 BUG_ON(gettimeofday(&tv_end, NULL)); 234 if (use_clock) {
156 timersub(&tv_end, &tv_start, &tv_diff); 235 result_clock[pf] =
157 bps = (double)((double)length / timeval2double(&tv_diff)); 236 do_memcpy_clock(routines[i].fn,
237 len, only_prefault);
238 } else {
239 result_bps[pf] =
240 do_memcpy_gettimeofday(routines[i].fn,
241 len, only_prefault);
242 }
158 } 243 }
159 244
160 switch (bench_format) { 245 switch (bench_format) {
161 case BENCH_FORMAT_DEFAULT: 246 case BENCH_FORMAT_DEFAULT:
162 if (use_clock) { 247 if (!only_prefault && !no_prefault) {
163 printf(" %14lf Clock/Byte\n", 248 if (use_clock) {
164 (double)clock_diff / (double)length); 249 printf(" %14lf Clock/Byte\n",
165 } else { 250 (double)result_clock[0]
166 if (bps < K) 251 / (double)len);
167 printf(" %14lf B/Sec\n", bps); 252 printf(" %14lf Clock/Byte (with prefault)\n",
168 else if (bps < K * K) 253 (double)result_clock[1]
169 printf(" %14lfd KB/Sec\n", bps / 1024); 254 / (double)len);
170 else if (bps < K * K * K) 255 } else {
171 printf(" %14lf MB/Sec\n", bps / 1024 / 1024); 256 print_bps(result_bps[0]);
172 else { 257 printf("\n");
173 printf(" %14lf GB/Sec\n", 258 print_bps(result_bps[1]);
174 bps / 1024 / 1024 / 1024); 259 printf(" (with prefault)\n");
175 } 260 }
261 } else {
262 if (use_clock) {
263 printf(" %14lf Clock/Byte",
264 (double)result_clock[pf]
265 / (double)len);
266 } else
267 print_bps(result_bps[pf]);
268
269 printf("%s\n", only_prefault ? " (with prefault)" : "");
176 } 270 }
177 break; 271 break;
178 case BENCH_FORMAT_SIMPLE: 272 case BENCH_FORMAT_SIMPLE:
179 if (use_clock) { 273 if (!only_prefault && !no_prefault) {
180 printf("%14lf\n", 274 if (use_clock) {
181 (double)clock_diff / (double)length); 275 printf("%lf %lf\n",
182 } else 276 (double)result_clock[0] / (double)len,
183 printf("%lf\n", bps); 277 (double)result_clock[1] / (double)len);
278 } else {
279 printf("%lf %lf\n",
280 result_bps[0], result_bps[1]);
281 }
282 } else {
283 if (use_clock) {
284 printf("%lf\n", (double)result_clock[pf]
285 / (double)len);
286 } else
287 printf("%lf\n", result_bps[pf]);
288 }
184 break; 289 break;
185 default: 290 default:
186 /* reaching this means there's some disaster: */ 291 /* reaching this means there's some disaster: */
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6d5604d8df95..8879463807e4 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -58,12 +58,12 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
58 return hist_entry__inc_addr_samples(he, al->addr); 58 return hist_entry__inc_addr_samples(he, al->addr);
59} 59}
60 60
61static int process_sample_event(event_t *event, struct perf_session *session) 61static int process_sample_event(event_t *event, struct sample_data *sample,
62 struct perf_session *session)
62{ 63{
63 struct addr_location al; 64 struct addr_location al;
64 struct sample_data data;
65 65
66 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 66 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
67 pr_warning("problem processing %d event, skipping it.\n", 67 pr_warning("problem processing %d event, skipping it.\n",
68 event->header.type); 68 event->header.type);
69 return -1; 69 return -1;
@@ -212,7 +212,7 @@ get_source_line(struct hist_entry *he, int len, const char *filename)
212 continue; 212 continue;
213 213
214 offset = start + i; 214 offset = start + i;
215 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 215 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
216 fp = popen(cmd, "r"); 216 fp = popen(cmd, "r");
217 if (!fp) 217 if (!fp)
218 continue; 218 continue;
@@ -270,9 +270,9 @@ static void hist_entry__print_hits(struct hist_entry *self)
270 270
271 for (offset = 0; offset < len; ++offset) 271 for (offset = 0; offset < len; ++offset)
272 if (h->ip[offset] != 0) 272 if (h->ip[offset] != 0)
273 printf("%*Lx: %Lu\n", BITS_PER_LONG / 2, 273 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
274 sym->start + offset, h->ip[offset]); 274 sym->start + offset, h->ip[offset]);
275 printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum); 275 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
276} 276}
277 277
278static int hist_entry__tty_annotate(struct hist_entry *he) 278static int hist_entry__tty_annotate(struct hist_entry *he)
@@ -375,6 +375,8 @@ static struct perf_event_ops event_ops = {
375 .mmap = event__process_mmap, 375 .mmap = event__process_mmap,
376 .comm = event__process_comm, 376 .comm = event__process_comm,
377 .fork = event__process_task, 377 .fork = event__process_task,
378 .ordered_samples = true,
379 .ordering_requires_timestamps = true,
378}; 380};
379 381
380static int __cmd_annotate(void) 382static int __cmd_annotate(void)
@@ -382,7 +384,7 @@ static int __cmd_annotate(void)
382 int ret; 384 int ret;
383 struct perf_session *session; 385 struct perf_session *session;
384 386
385 session = perf_session__new(input_name, O_RDONLY, force, false); 387 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
386 if (session == NULL) 388 if (session == NULL)
387 return -ENOMEM; 389 return -ENOMEM;
388 390
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 44a47e13bd67..5af32ae9031e 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -36,10 +36,10 @@ static const struct option options[] = {
36 36
37static int __cmd_buildid_list(void) 37static int __cmd_buildid_list(void)
38{ 38{
39 int err = -1;
40 struct perf_session *session; 39 struct perf_session *session;
41 40
42 session = perf_session__new(input_name, O_RDONLY, force, false); 41 session = perf_session__new(input_name, O_RDONLY, force, false,
42 &build_id__mark_dso_hit_ops);
43 if (session == NULL) 43 if (session == NULL)
44 return -1; 44 return -1;
45 45
@@ -49,7 +49,7 @@ static int __cmd_buildid_list(void)
49 perf_session__fprintf_dsos_buildid(session, stdout, with_hits); 49 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
50 50
51 perf_session__delete(session); 51 perf_session__delete(session);
52 return err; 52 return 0;
53} 53}
54 54
55int cmd_buildid_list(int argc, const char **argv, const char *prefix __used) 55int cmd_buildid_list(int argc, const char **argv, const char *prefix __used)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index fca1d4402910..3153e492dbcc 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -30,12 +30,13 @@ static int hists__add_entry(struct hists *self,
30 return -ENOMEM; 30 return -ENOMEM;
31} 31}
32 32
33static int diff__process_sample_event(event_t *event, struct perf_session *session) 33static int diff__process_sample_event(event_t *event,
34 struct sample_data *sample,
35 struct perf_session *session)
34{ 36{
35 struct addr_location al; 37 struct addr_location al;
36 struct sample_data data = { .period = 1, };
37 38
38 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 39 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
39 pr_warning("problem processing %d event, skipping it.\n", 40 pr_warning("problem processing %d event, skipping it.\n",
40 event->header.type); 41 event->header.type);
41 return -1; 42 return -1;
@@ -44,12 +45,12 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi
44 if (al.filtered || al.sym == NULL) 45 if (al.filtered || al.sym == NULL)
45 return 0; 46 return 0;
46 47
47 if (hists__add_entry(&session->hists, &al, data.period)) { 48 if (hists__add_entry(&session->hists, &al, sample->period)) {
48 pr_warning("problem incrementing symbol period, skipping event\n"); 49 pr_warning("problem incrementing symbol period, skipping event\n");
49 return -1; 50 return -1;
50 } 51 }
51 52
52 session->hists.stats.total_period += data.period; 53 session->hists.stats.total_period += sample->period;
53 return 0; 54 return 0;
54} 55}
55 56
@@ -60,6 +61,8 @@ static struct perf_event_ops event_ops = {
60 .exit = event__process_task, 61 .exit = event__process_task,
61 .fork = event__process_task, 62 .fork = event__process_task,
62 .lost = event__process_lost, 63 .lost = event__process_lost,
64 .ordered_samples = true,
65 .ordering_requires_timestamps = true,
63}; 66};
64 67
65static void perf_session__insert_hist_entry_by_name(struct rb_root *root, 68static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
@@ -141,8 +144,8 @@ static int __cmd_diff(void)
141 int ret, i; 144 int ret, i;
142 struct perf_session *session[2]; 145 struct perf_session *session[2];
143 146
144 session[0] = perf_session__new(input_old, O_RDONLY, force, false); 147 session[0] = perf_session__new(input_old, O_RDONLY, force, false, &event_ops);
145 session[1] = perf_session__new(input_new, O_RDONLY, force, false); 148 session[1] = perf_session__new(input_new, O_RDONLY, force, false, &event_ops);
146 if (session[0] == NULL || session[1] == NULL) 149 if (session[0] == NULL || session[1] == NULL)
147 return -ENOMEM; 150 return -ENOMEM;
148 151
@@ -173,7 +176,7 @@ static const char * const diff_usage[] = {
173static const struct option options[] = { 176static const struct option options[] = {
174 OPT_INCR('v', "verbose", &verbose, 177 OPT_INCR('v', "verbose", &verbose,
175 "be more verbose (show symbol address, etc)"), 178 "be more verbose (show symbol address, etc)"),
176 OPT_BOOLEAN('m', "displacement", &show_displacement, 179 OPT_BOOLEAN('M', "displacement", &show_displacement,
177 "Show position displacement relative to baseline"), 180 "Show position displacement relative to baseline"),
178 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 181 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
179 "dump raw trace in ASCII"), 182 "dump raw trace in ASCII"),
@@ -191,6 +194,8 @@ static const struct option options[] = {
191 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 194 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
192 "separator for columns, no spaces will be added between " 195 "separator for columns, no spaces will be added between "
193 "columns '.' is reserved."), 196 "columns '.' is reserved."),
197 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
198 "Look for files with symbols relative to this directory"),
194 OPT_END() 199 OPT_END()
195}; 200};
196 201
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8e3e47b064ce..0c78ffa7bf67 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,8 +16,8 @@
16static char const *input_name = "-"; 16static char const *input_name = "-";
17static bool inject_build_ids; 17static bool inject_build_ids;
18 18
19static int event__repipe(event_t *event __used, 19static int event__repipe_synth(event_t *event,
20 struct perf_session *session __used) 20 struct perf_session *session __used)
21{ 21{
22 uint32_t size; 22 uint32_t size;
23 void *buf = event; 23 void *buf = event;
@@ -36,22 +36,30 @@ static int event__repipe(event_t *event __used,
36 return 0; 36 return 0;
37} 37}
38 38
39static int event__repipe_mmap(event_t *self, struct perf_session *session) 39static int event__repipe(event_t *event, struct sample_data *sample __used,
40 struct perf_session *session)
41{
42 return event__repipe_synth(event, session);
43}
44
45static int event__repipe_mmap(event_t *self, struct sample_data *sample,
46 struct perf_session *session)
40{ 47{
41 int err; 48 int err;
42 49
43 err = event__process_mmap(self, session); 50 err = event__process_mmap(self, sample, session);
44 event__repipe(self, session); 51 event__repipe(self, sample, session);
45 52
46 return err; 53 return err;
47} 54}
48 55
49static int event__repipe_task(event_t *self, struct perf_session *session) 56static int event__repipe_task(event_t *self, struct sample_data *sample,
57 struct perf_session *session)
50{ 58{
51 int err; 59 int err;
52 60
53 err = event__process_task(self, session); 61 err = event__process_task(self, sample, session);
54 event__repipe(self, session); 62 event__repipe(self, sample, session);
55 63
56 return err; 64 return err;
57} 65}
@@ -61,7 +69,7 @@ static int event__repipe_tracing_data(event_t *self,
61{ 69{
62 int err; 70 int err;
63 71
64 event__repipe(self, session); 72 event__repipe_synth(self, session);
65 err = event__process_tracing_data(self, session); 73 err = event__process_tracing_data(self, session);
66 74
67 return err; 75 return err;
@@ -111,7 +119,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
111 return 0; 119 return 0;
112} 120}
113 121
114static int event__inject_buildid(event_t *event, struct perf_session *session) 122static int event__inject_buildid(event_t *event, struct sample_data *sample,
123 struct perf_session *session)
115{ 124{
116 struct addr_location al; 125 struct addr_location al;
117 struct thread *thread; 126 struct thread *thread;
@@ -146,7 +155,7 @@ static int event__inject_buildid(event_t *event, struct perf_session *session)
146 } 155 }
147 156
148repipe: 157repipe:
149 event__repipe(event, session); 158 event__repipe(event, sample, session);
150 return 0; 159 return 0;
151} 160}
152 161
@@ -160,10 +169,10 @@ struct perf_event_ops inject_ops = {
160 .read = event__repipe, 169 .read = event__repipe,
161 .throttle = event__repipe, 170 .throttle = event__repipe,
162 .unthrottle = event__repipe, 171 .unthrottle = event__repipe,
163 .attr = event__repipe, 172 .attr = event__repipe_synth,
164 .event_type = event__repipe, 173 .event_type = event__repipe_synth,
165 .tracing_data = event__repipe, 174 .tracing_data = event__repipe_synth,
166 .build_id = event__repipe, 175 .build_id = event__repipe_synth,
167}; 176};
168 177
169extern volatile int session_done; 178extern volatile int session_done;
@@ -187,7 +196,7 @@ static int __cmd_inject(void)
187 inject_ops.tracing_data = event__repipe_tracing_data; 196 inject_ops.tracing_data = event__repipe_tracing_data;
188 } 197 }
189 198
190 session = perf_session__new(input_name, O_RDONLY, false, true); 199 session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops);
191 if (session == NULL) 200 if (session == NULL)
192 return -ENOMEM; 201 return -ENOMEM;
193 202
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 31f60a2535e0..d97256d65980 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -304,22 +304,11 @@ process_raw_event(event_t *raw_event __used, void *data,
304 } 304 }
305} 305}
306 306
307static int process_sample_event(event_t *event, struct perf_session *session) 307static int process_sample_event(event_t *event, struct sample_data *sample,
308 struct perf_session *session)
308{ 309{
309 struct sample_data data; 310 struct thread *thread = perf_session__findnew(session, event->ip.pid);
310 struct thread *thread;
311 311
312 memset(&data, 0, sizeof(data));
313 data.time = -1;
314 data.cpu = -1;
315 data.period = 1;
316
317 event__parse_sample(event, session->sample_type, &data);
318
319 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
320 data.pid, data.tid, data.ip, data.period);
321
322 thread = perf_session__findnew(session, event->ip.pid);
323 if (thread == NULL) { 312 if (thread == NULL) {
324 pr_debug("problem processing %d event, skipping it.\n", 313 pr_debug("problem processing %d event, skipping it.\n",
325 event->header.type); 314 event->header.type);
@@ -328,8 +317,8 @@ static int process_sample_event(event_t *event, struct perf_session *session)
328 317
329 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 318 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
330 319
331 process_raw_event(event, data.raw_data, data.cpu, 320 process_raw_event(event, sample->raw_data, sample->cpu,
332 data.time, thread); 321 sample->time, thread);
333 322
334 return 0; 323 return 0;
335} 324}
@@ -382,10 +371,10 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
382 addr = data->ptr; 371 addr = data->ptr;
383 372
384 if (sym != NULL) 373 if (sym != NULL)
385 snprintf(buf, sizeof(buf), "%s+%Lx", sym->name, 374 snprintf(buf, sizeof(buf), "%s+%" PRIx64 "", sym->name,
386 addr - map->unmap_ip(map, sym->start)); 375 addr - map->unmap_ip(map, sym->start));
387 else 376 else
388 snprintf(buf, sizeof(buf), "%#Lx", addr); 377 snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
389 printf(" %-34s |", buf); 378 printf(" %-34s |", buf);
390 379
391 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n", 380 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n",
@@ -492,7 +481,8 @@ static void sort_result(void)
492static int __cmd_kmem(void) 481static int __cmd_kmem(void)
493{ 482{
494 int err = -EINVAL; 483 int err = -EINVAL;
495 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 484 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
485 0, false, &event_ops);
496 if (session == NULL) 486 if (session == NULL)
497 return -ENOMEM; 487 return -ENOMEM;
498 488
@@ -747,6 +737,9 @@ static int __cmd_record(int argc, const char **argv)
747 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 737 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
748 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 738 rec_argv = calloc(rec_argc + 1, sizeof(char *));
749 739
740 if (rec_argv == NULL)
741 return -ENOMEM;
742
750 for (i = 0; i < ARRAY_SIZE(record_args); i++) 743 for (i = 0; i < ARRAY_SIZE(record_args); i++)
751 rec_argv[i] = strdup(record_args[i]); 744 rec_argv[i] = strdup(record_args[i]);
752 745
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 821c1586a22b..2b36defc5d73 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -782,9 +782,9 @@ static void print_result(void)
782 pr_info("%10u ", st->nr_acquired); 782 pr_info("%10u ", st->nr_acquired);
783 pr_info("%10u ", st->nr_contended); 783 pr_info("%10u ", st->nr_contended);
784 784
785 pr_info("%15llu ", st->wait_time_total); 785 pr_info("%15" PRIu64 " ", st->wait_time_total);
786 pr_info("%15llu ", st->wait_time_max); 786 pr_info("%15" PRIu64 " ", st->wait_time_max);
787 pr_info("%15llu ", st->wait_time_min == ULLONG_MAX ? 787 pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ?
788 0 : st->wait_time_min); 788 0 : st->wait_time_min);
789 pr_info("\n"); 789 pr_info("\n");
790 } 790 }
@@ -834,22 +834,18 @@ static void dump_info(void)
834 die("Unknown type of information\n"); 834 die("Unknown type of information\n");
835} 835}
836 836
837static int process_sample_event(event_t *self, struct perf_session *s) 837static int process_sample_event(event_t *self, struct sample_data *sample,
838 struct perf_session *s)
838{ 839{
839 struct sample_data data; 840 struct thread *thread = perf_session__findnew(s, sample->tid);
840 struct thread *thread;
841 841
842 bzero(&data, sizeof(data));
843 event__parse_sample(self, s->sample_type, &data);
844
845 thread = perf_session__findnew(s, data.tid);
846 if (thread == NULL) { 842 if (thread == NULL) {
847 pr_debug("problem processing %d event, skipping it.\n", 843 pr_debug("problem processing %d event, skipping it.\n",
848 self->header.type); 844 self->header.type);
849 return -1; 845 return -1;
850 } 846 }
851 847
852 process_raw_event(data.raw_data, data.cpu, data.time, thread); 848 process_raw_event(sample->raw_data, sample->cpu, sample->time, thread);
853 849
854 return 0; 850 return 0;
855} 851}
@@ -862,7 +858,7 @@ static struct perf_event_ops eops = {
862 858
863static int read_events(void) 859static int read_events(void)
864{ 860{
865 session = perf_session__new(input_name, O_RDONLY, 0, false); 861 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
866 if (!session) 862 if (!session)
867 die("Initializing perf session failed\n"); 863 die("Initializing perf session failed\n");
868 864
@@ -947,6 +943,9 @@ static int __cmd_record(int argc, const char **argv)
947 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 943 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
948 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 944 rec_argv = calloc(rec_argc + 1, sizeof(char *));
949 945
946 if (rec_argv == NULL)
947 return -ENOMEM;
948
950 for (i = 0; i < ARRAY_SIZE(record_args); i++) 949 for (i = 0; i < ARRAY_SIZE(record_args); i++)
951 rec_argv[i] = strdup(record_args[i]); 950 rec_argv[i] = strdup(record_args[i]);
952 951
@@ -982,9 +981,9 @@ int cmd_lock(int argc, const char **argv, const char *prefix __used)
982 usage_with_options(report_usage, report_options); 981 usage_with_options(report_usage, report_options);
983 } 982 }
984 __cmd_report(); 983 __cmd_report();
985 } else if (!strcmp(argv[0], "trace")) { 984 } else if (!strcmp(argv[0], "script")) {
986 /* Aliased to 'perf trace' */ 985 /* Aliased to 'perf script' */
987 return cmd_trace(argc, argv, prefix); 986 return cmd_script(argc, argv, prefix);
988 } else if (!strcmp(argv[0], "info")) { 987 } else if (!strcmp(argv[0], "info")) {
989 if (argc) { 988 if (argc) {
990 argc = parse_options(argc, argv, 989 argc = parse_options(argc, argv,
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 2e000c068cc5..add163c9f0e7 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -249,6 +249,11 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
249 !params.show_lines)) 249 !params.show_lines))
250 usage_with_options(probe_usage, options); 250 usage_with_options(probe_usage, options);
251 251
252 /*
253 * Only consider the user's kernel image path if given.
254 */
255 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
256
252 if (params.list_events) { 257 if (params.list_events) {
253 if (params.mod_events) { 258 if (params.mod_events) {
254 pr_err(" Error: Don't use --list with --add/--del.\n"); 259 pr_err(" Error: Don't use --list with --add/--del.\n");
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4e75583ddd6d..b2f729fdb317 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -18,6 +18,7 @@
18 18
19#include "util/header.h" 19#include "util/header.h"
20#include "util/event.h" 20#include "util/event.h"
21#include "util/evsel.h"
21#include "util/debug.h" 22#include "util/debug.h"
22#include "util/session.h" 23#include "util/session.h"
23#include "util/symbol.h" 24#include "util/symbol.h"
@@ -27,17 +28,18 @@
27#include <sched.h> 28#include <sched.h>
28#include <sys/mman.h> 29#include <sys/mman.h>
29 30
31#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
32
30enum write_mode_t { 33enum write_mode_t {
31 WRITE_FORCE, 34 WRITE_FORCE,
32 WRITE_APPEND 35 WRITE_APPEND
33}; 36};
34 37
35static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
36
37static u64 user_interval = ULLONG_MAX; 38static u64 user_interval = ULLONG_MAX;
38static u64 default_interval = 0; 39static u64 default_interval = 0;
40static u64 sample_type;
39 41
40static int nr_cpus = 0; 42static struct cpu_map *cpus;
41static unsigned int page_size; 43static unsigned int page_size;
42static unsigned int mmap_pages = 128; 44static unsigned int mmap_pages = 128;
43static unsigned int user_freq = UINT_MAX; 45static unsigned int user_freq = UINT_MAX;
@@ -47,12 +49,13 @@ static int pipe_output = 0;
47static const char *output_name = "perf.data"; 49static const char *output_name = "perf.data";
48static int group = 0; 50static int group = 0;
49static int realtime_prio = 0; 51static int realtime_prio = 0;
52static bool nodelay = false;
50static bool raw_samples = false; 53static bool raw_samples = false;
54static bool sample_id_all_avail = true;
51static bool system_wide = false; 55static bool system_wide = false;
52static pid_t target_pid = -1; 56static pid_t target_pid = -1;
53static pid_t target_tid = -1; 57static pid_t target_tid = -1;
54static pid_t *all_tids = NULL; 58static struct thread_map *threads;
55static int thread_num = 0;
56static pid_t child_pid = -1; 59static pid_t child_pid = -1;
57static bool no_inherit = false; 60static bool no_inherit = false;
58static enum write_mode_t write_mode = WRITE_FORCE; 61static enum write_mode_t write_mode = WRITE_FORCE;
@@ -60,7 +63,9 @@ static bool call_graph = false;
60static bool inherit_stat = false; 63static bool inherit_stat = false;
61static bool no_samples = false; 64static bool no_samples = false;
62static bool sample_address = false; 65static bool sample_address = false;
66static bool sample_time = false;
63static bool no_buildid = false; 67static bool no_buildid = false;
68static bool no_buildid_cache = false;
64 69
65static long samples = 0; 70static long samples = 0;
66static u64 bytes_written = 0; 71static u64 bytes_written = 0;
@@ -77,7 +82,6 @@ static struct perf_session *session;
77static const char *cpu_list; 82static const char *cpu_list;
78 83
79struct mmap_data { 84struct mmap_data {
80 int counter;
81 void *base; 85 void *base;
82 unsigned int mask; 86 unsigned int mask;
83 unsigned int prev; 87 unsigned int prev;
@@ -128,6 +132,7 @@ static void write_output(void *buf, size_t size)
128} 132}
129 133
130static int process_synthesized_event(event_t *event, 134static int process_synthesized_event(event_t *event,
135 struct sample_data *sample __used,
131 struct perf_session *self __used) 136 struct perf_session *self __used)
132{ 137{
133 write_output(event, event->header.size); 138 write_output(event, event->header.size);
@@ -197,7 +202,7 @@ static void sig_atexit(void)
197 if (child_pid > 0) 202 if (child_pid > 0)
198 kill(child_pid, SIGTERM); 203 kill(child_pid, SIGTERM);
199 204
200 if (signr == -1) 205 if (signr == -1 || signr == SIGUSR1)
201 return; 206 return;
202 207
203 signal(signr, SIG_DFL); 208 signal(signr, SIG_DFL);
@@ -224,12 +229,12 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
224 return h_attr; 229 return h_attr;
225} 230}
226 231
227static void create_counter(int counter, int cpu) 232static void create_counter(struct perf_evsel *evsel, int cpu)
228{ 233{
229 char *filter = filters[counter]; 234 char *filter = evsel->filter;
230 struct perf_event_attr *attr = attrs + counter; 235 struct perf_event_attr *attr = &evsel->attr;
231 struct perf_header_attr *h_attr; 236 struct perf_header_attr *h_attr;
232 int track = !counter; /* only the first counter needs these */ 237 int track = !evsel->idx; /* only the first counter needs these */
233 int thread_index; 238 int thread_index;
234 int ret; 239 int ret;
235 struct { 240 struct {
@@ -238,6 +243,19 @@ static void create_counter(int counter, int cpu)
238 u64 time_running; 243 u64 time_running;
239 u64 id; 244 u64 id;
240 } read_data; 245 } read_data;
246 /*
247 * Check if parse_single_tracepoint_event has already asked for
248 * PERF_SAMPLE_TIME.
249 *
250 * XXX this is kludgy but short term fix for problems introduced by
251 * eac23d1c that broke 'perf script' by having different sample_types
252 * when using multiple tracepoint events when we use a perf binary
253 * that tries to use sample_id_all on an older kernel.
254 *
255 * We need to move counter creation to perf_session, support
256 * different sample_types, etc.
257 */
258 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
241 259
242 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 260 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
243 PERF_FORMAT_TOTAL_TIME_RUNNING | 261 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -280,12 +298,21 @@ static void create_counter(int counter, int cpu)
280 if (system_wide) 298 if (system_wide)
281 attr->sample_type |= PERF_SAMPLE_CPU; 299 attr->sample_type |= PERF_SAMPLE_CPU;
282 300
301 if (sample_id_all_avail &&
302 (sample_time || system_wide || !no_inherit || cpu_list))
303 attr->sample_type |= PERF_SAMPLE_TIME;
304
283 if (raw_samples) { 305 if (raw_samples) {
284 attr->sample_type |= PERF_SAMPLE_TIME; 306 attr->sample_type |= PERF_SAMPLE_TIME;
285 attr->sample_type |= PERF_SAMPLE_RAW; 307 attr->sample_type |= PERF_SAMPLE_RAW;
286 attr->sample_type |= PERF_SAMPLE_CPU; 308 attr->sample_type |= PERF_SAMPLE_CPU;
287 } 309 }
288 310
311 if (nodelay) {
312 attr->watermark = 0;
313 attr->wakeup_events = 1;
314 }
315
289 attr->mmap = track; 316 attr->mmap = track;
290 attr->comm = track; 317 attr->comm = track;
291 attr->inherit = !no_inherit; 318 attr->inherit = !no_inherit;
@@ -293,13 +320,14 @@ static void create_counter(int counter, int cpu)
293 attr->disabled = 1; 320 attr->disabled = 1;
294 attr->enable_on_exec = 1; 321 attr->enable_on_exec = 1;
295 } 322 }
323retry_sample_id:
324 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
296 325
297 for (thread_index = 0; thread_index < thread_num; thread_index++) { 326 for (thread_index = 0; thread_index < threads->nr; thread_index++) {
298try_again: 327try_again:
299 fd[nr_cpu][counter][thread_index] = sys_perf_event_open(attr, 328 FD(evsel, nr_cpu, thread_index) = sys_perf_event_open(attr, threads->map[thread_index], cpu, group_fd, 0);
300 all_tids[thread_index], cpu, group_fd, 0);
301 329
302 if (fd[nr_cpu][counter][thread_index] < 0) { 330 if (FD(evsel, nr_cpu, thread_index) < 0) {
303 int err = errno; 331 int err = errno;
304 332
305 if (err == EPERM || err == EACCES) 333 if (err == EPERM || err == EACCES)
@@ -309,6 +337,15 @@ try_again:
309 else if (err == ENODEV && cpu_list) { 337 else if (err == ENODEV && cpu_list) {
310 die("No such device - did you specify" 338 die("No such device - did you specify"
311 " an out-of-range profile CPU?\n"); 339 " an out-of-range profile CPU?\n");
340 } else if (err == EINVAL && sample_id_all_avail) {
341 /*
342 * Old kernel, no attr->sample_id_type_all field
343 */
344 sample_id_all_avail = false;
345 if (!sample_time && !raw_samples && !time_needed)
346 attr->sample_type &= ~PERF_SAMPLE_TIME;
347
348 goto retry_sample_id;
312 } 349 }
313 350
314 /* 351 /*
@@ -326,8 +363,8 @@ try_again:
326 goto try_again; 363 goto try_again;
327 } 364 }
328 printf("\n"); 365 printf("\n");
329 error("perfcounter syscall returned with %d (%s)\n", 366 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
330 fd[nr_cpu][counter][thread_index], strerror(err)); 367 FD(evsel, nr_cpu, thread_index), strerror(err));
331 368
332#if defined(__i386__) || defined(__x86_64__) 369#if defined(__i386__) || defined(__x86_64__)
333 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 370 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
@@ -341,7 +378,7 @@ try_again:
341 exit(-1); 378 exit(-1);
342 } 379 }
343 380
344 h_attr = get_header_attr(attr, counter); 381 h_attr = get_header_attr(attr, evsel->idx);
345 if (h_attr == NULL) 382 if (h_attr == NULL)
346 die("nomem\n"); 383 die("nomem\n");
347 384
@@ -352,7 +389,7 @@ try_again:
352 } 389 }
353 } 390 }
354 391
355 if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) { 392 if (read(FD(evsel, nr_cpu, thread_index), &read_data, sizeof(read_data)) == -1) {
356 perror("Unable to read perf file descriptor"); 393 perror("Unable to read perf file descriptor");
357 exit(-1); 394 exit(-1);
358 } 395 }
@@ -362,43 +399,44 @@ try_again:
362 exit(-1); 399 exit(-1);
363 } 400 }
364 401
365 assert(fd[nr_cpu][counter][thread_index] >= 0); 402 assert(FD(evsel, nr_cpu, thread_index) >= 0);
366 fcntl(fd[nr_cpu][counter][thread_index], F_SETFL, O_NONBLOCK); 403 fcntl(FD(evsel, nr_cpu, thread_index), F_SETFL, O_NONBLOCK);
367 404
368 /* 405 /*
369 * First counter acts as the group leader: 406 * First counter acts as the group leader:
370 */ 407 */
371 if (group && group_fd == -1) 408 if (group && group_fd == -1)
372 group_fd = fd[nr_cpu][counter][thread_index]; 409 group_fd = FD(evsel, nr_cpu, thread_index);
373 410
374 if (counter || thread_index) { 411 if (evsel->idx || thread_index) {
375 ret = ioctl(fd[nr_cpu][counter][thread_index], 412 struct perf_evsel *first;
376 PERF_EVENT_IOC_SET_OUTPUT, 413 first = list_entry(evsel_list.next, struct perf_evsel, node);
377 fd[nr_cpu][0][0]); 414 ret = ioctl(FD(evsel, nr_cpu, thread_index),
415 PERF_EVENT_IOC_SET_OUTPUT,
416 FD(first, nr_cpu, 0));
378 if (ret) { 417 if (ret) {
379 error("failed to set output: %d (%s)\n", errno, 418 error("failed to set output: %d (%s)\n", errno,
380 strerror(errno)); 419 strerror(errno));
381 exit(-1); 420 exit(-1);
382 } 421 }
383 } else { 422 } else {
384 mmap_array[nr_cpu].counter = counter;
385 mmap_array[nr_cpu].prev = 0; 423 mmap_array[nr_cpu].prev = 0;
386 mmap_array[nr_cpu].mask = mmap_pages*page_size - 1; 424 mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
387 mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size, 425 mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size,
388 PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0); 426 PROT_READ | PROT_WRITE, MAP_SHARED, FD(evsel, nr_cpu, thread_index), 0);
389 if (mmap_array[nr_cpu].base == MAP_FAILED) { 427 if (mmap_array[nr_cpu].base == MAP_FAILED) {
390 error("failed to mmap with %d (%s)\n", errno, strerror(errno)); 428 error("failed to mmap with %d (%s)\n", errno, strerror(errno));
391 exit(-1); 429 exit(-1);
392 } 430 }
393 431
394 event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index]; 432 event_array[nr_poll].fd = FD(evsel, nr_cpu, thread_index);
395 event_array[nr_poll].events = POLLIN; 433 event_array[nr_poll].events = POLLIN;
396 nr_poll++; 434 nr_poll++;
397 } 435 }
398 436
399 if (filter != NULL) { 437 if (filter != NULL) {
400 ret = ioctl(fd[nr_cpu][counter][thread_index], 438 ret = ioctl(FD(evsel, nr_cpu, thread_index),
401 PERF_EVENT_IOC_SET_FILTER, filter); 439 PERF_EVENT_IOC_SET_FILTER, filter);
402 if (ret) { 440 if (ret) {
403 error("failed to set filter with %d (%s)\n", errno, 441 error("failed to set filter with %d (%s)\n", errno,
404 strerror(errno)); 442 strerror(errno));
@@ -406,15 +444,19 @@ try_again:
406 } 444 }
407 } 445 }
408 } 446 }
447
448 if (!sample_type)
449 sample_type = attr->sample_type;
409} 450}
410 451
411static void open_counters(int cpu) 452static void open_counters(int cpu)
412{ 453{
413 int counter; 454 struct perf_evsel *pos;
414 455
415 group_fd = -1; 456 group_fd = -1;
416 for (counter = 0; counter < nr_counters; counter++) 457
417 create_counter(counter, cpu); 458 list_for_each_entry(pos, &evsel_list, node)
459 create_counter(pos, cpu);
418 460
419 nr_cpu++; 461 nr_cpu++;
420} 462}
@@ -437,9 +479,11 @@ static void atexit_header(void)
437 if (!pipe_output) { 479 if (!pipe_output) {
438 session->header.data_size += bytes_written; 480 session->header.data_size += bytes_written;
439 481
440 process_buildids(); 482 if (!no_buildid)
483 process_buildids();
441 perf_header__write(&session->header, output, true); 484 perf_header__write(&session->header, output, true);
442 perf_session__delete(session); 485 perf_session__delete(session);
486 perf_evsel_list__delete();
443 symbol__exit(); 487 symbol__exit();
444 } 488 }
445} 489}
@@ -500,7 +544,7 @@ static void mmap_read_all(void)
500 544
501static int __cmd_record(int argc, const char **argv) 545static int __cmd_record(int argc, const char **argv)
502{ 546{
503 int i, counter; 547 int i;
504 struct stat st; 548 struct stat st;
505 int flags; 549 int flags;
506 int err; 550 int err;
@@ -515,6 +559,7 @@ static int __cmd_record(int argc, const char **argv)
515 atexit(sig_atexit); 559 atexit(sig_atexit);
516 signal(SIGCHLD, sig_handler); 560 signal(SIGCHLD, sig_handler);
517 signal(SIGINT, sig_handler); 561 signal(SIGINT, sig_handler);
562 signal(SIGUSR1, sig_handler);
518 563
519 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 564 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
520 perror("failed to create pipes"); 565 perror("failed to create pipes");
@@ -551,19 +596,22 @@ static int __cmd_record(int argc, const char **argv)
551 } 596 }
552 597
553 session = perf_session__new(output_name, O_WRONLY, 598 session = perf_session__new(output_name, O_WRONLY,
554 write_mode == WRITE_FORCE, false); 599 write_mode == WRITE_FORCE, false, NULL);
555 if (session == NULL) { 600 if (session == NULL) {
556 pr_err("Not enough memory for reading perf file header\n"); 601 pr_err("Not enough memory for reading perf file header\n");
557 return -1; 602 return -1;
558 } 603 }
559 604
605 if (!no_buildid)
606 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
607
560 if (!file_new) { 608 if (!file_new) {
561 err = perf_header__read(session, output); 609 err = perf_header__read(session, output);
562 if (err < 0) 610 if (err < 0)
563 goto out_delete_session; 611 goto out_delete_session;
564 } 612 }
565 613
566 if (have_tracepoints(attrs, nr_counters)) 614 if (have_tracepoints(&evsel_list))
567 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 615 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
568 616
569 /* 617 /*
@@ -606,11 +654,12 @@ static int __cmd_record(int argc, const char **argv)
606 execvp(argv[0], (char **)argv); 654 execvp(argv[0], (char **)argv);
607 655
608 perror(argv[0]); 656 perror(argv[0]);
657 kill(getppid(), SIGUSR1);
609 exit(-1); 658 exit(-1);
610 } 659 }
611 660
612 if (!system_wide && target_tid == -1 && target_pid == -1) 661 if (!system_wide && target_tid == -1 && target_pid == -1)
613 all_tids[0] = child_pid; 662 threads->map[0] = child_pid;
614 663
615 close(child_ready_pipe[1]); 664 close(child_ready_pipe[1]);
616 close(go_pipe[0]); 665 close(go_pipe[0]);
@@ -624,19 +673,15 @@ static int __cmd_record(int argc, const char **argv)
624 close(child_ready_pipe[0]); 673 close(child_ready_pipe[0]);
625 } 674 }
626 675
627 nr_cpus = read_cpu_map(cpu_list);
628 if (nr_cpus < 1) {
629 perror("failed to collect number of CPUs");
630 return -1;
631 }
632
633 if (!system_wide && no_inherit && !cpu_list) { 676 if (!system_wide && no_inherit && !cpu_list) {
634 open_counters(-1); 677 open_counters(-1);
635 } else { 678 } else {
636 for (i = 0; i < nr_cpus; i++) 679 for (i = 0; i < cpus->nr; i++)
637 open_counters(cpumap[i]); 680 open_counters(cpus->map[i]);
638 } 681 }
639 682
683 perf_session__set_sample_type(session, sample_type);
684
640 if (pipe_output) { 685 if (pipe_output) {
641 err = perf_header__write_pipe(output); 686 err = perf_header__write_pipe(output);
642 if (err < 0) 687 if (err < 0)
@@ -649,6 +694,8 @@ static int __cmd_record(int argc, const char **argv)
649 694
650 post_processing_offset = lseek(output, 0, SEEK_CUR); 695 post_processing_offset = lseek(output, 0, SEEK_CUR);
651 696
697 perf_session__set_sample_id_all(session, sample_id_all_avail);
698
652 if (pipe_output) { 699 if (pipe_output) {
653 err = event__synthesize_attrs(&session->header, 700 err = event__synthesize_attrs(&session->header,
654 process_synthesized_event, 701 process_synthesized_event,
@@ -665,7 +712,7 @@ static int __cmd_record(int argc, const char **argv)
665 return err; 712 return err;
666 } 713 }
667 714
668 if (have_tracepoints(attrs, nr_counters)) { 715 if (have_tracepoints(&evsel_list)) {
669 /* 716 /*
670 * FIXME err <= 0 here actually means that 717 * FIXME err <= 0 here actually means that
671 * there were no tracepoints so its not really 718 * there were no tracepoints so its not really
@@ -674,8 +721,7 @@ static int __cmd_record(int argc, const char **argv)
674 * return this more properly and also 721 * return this more properly and also
675 * propagate errors that now are calling die() 722 * propagate errors that now are calling die()
676 */ 723 */
677 err = event__synthesize_tracing_data(output, attrs, 724 err = event__synthesize_tracing_data(output, &evsel_list,
678 nr_counters,
679 process_synthesized_event, 725 process_synthesized_event,
680 session); 726 session);
681 if (err <= 0) { 727 if (err <= 0) {
@@ -697,17 +743,18 @@ static int __cmd_record(int argc, const char **argv)
697 if (err < 0) 743 if (err < 0)
698 err = event__synthesize_kernel_mmap(process_synthesized_event, 744 err = event__synthesize_kernel_mmap(process_synthesized_event,
699 session, machine, "_stext"); 745 session, machine, "_stext");
700 if (err < 0) { 746 if (err < 0)
701 pr_err("Couldn't record kernel reference relocation symbol.\n"); 747 pr_err("Couldn't record kernel reference relocation symbol\n"
702 return err; 748 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
703 } 749 "Check /proc/kallsyms permission or run as root.\n");
704 750
705 err = event__synthesize_modules(process_synthesized_event, 751 err = event__synthesize_modules(process_synthesized_event,
706 session, machine); 752 session, machine);
707 if (err < 0) { 753 if (err < 0)
708 pr_err("Couldn't record kernel reference relocation symbol.\n"); 754 pr_err("Couldn't record kernel module information.\n"
709 return err; 755 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
710 } 756 "Check /proc/modules permission or run as root.\n");
757
711 if (perf_guest) 758 if (perf_guest)
712 perf_session__process_machines(session, event__synthesize_guest_os); 759 perf_session__process_machines(session, event__synthesize_guest_os);
713 760
@@ -748,20 +795,20 @@ static int __cmd_record(int argc, const char **argv)
748 795
749 if (done) { 796 if (done) {
750 for (i = 0; i < nr_cpu; i++) { 797 for (i = 0; i < nr_cpu; i++) {
751 for (counter = 0; 798 struct perf_evsel *pos;
752 counter < nr_counters; 799
753 counter++) { 800 list_for_each_entry(pos, &evsel_list, node) {
754 for (thread = 0; 801 for (thread = 0;
755 thread < thread_num; 802 thread < threads->nr;
756 thread++) 803 thread++)
757 ioctl(fd[i][counter][thread], 804 ioctl(FD(pos, i, thread),
758 PERF_EVENT_IOC_DISABLE); 805 PERF_EVENT_IOC_DISABLE);
759 } 806 }
760 } 807 }
761 } 808 }
762 } 809 }
763 810
764 if (quiet) 811 if (quiet || signr == SIGUSR1)
765 return 0; 812 return 0;
766 813
767 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 814 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
@@ -770,7 +817,7 @@ static int __cmd_record(int argc, const char **argv)
770 * Approximate RIP event size: 24 bytes. 817 * Approximate RIP event size: 24 bytes.
771 */ 818 */
772 fprintf(stderr, 819 fprintf(stderr,
773 "[ perf record: Captured and wrote %.3f MB %s (~%lld samples) ]\n", 820 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
774 (double)bytes_written / 1024.0 / 1024.0, 821 (double)bytes_written / 1024.0 / 1024.0,
775 output_name, 822 output_name,
776 bytes_written / 24); 823 bytes_written / 24);
@@ -790,7 +837,7 @@ static const char * const record_usage[] = {
790 837
791static bool force, append_file; 838static bool force, append_file;
792 839
793static const struct option options[] = { 840const struct option record_options[] = {
794 OPT_CALLBACK('e', "event", NULL, "event", 841 OPT_CALLBACK('e', "event", NULL, "event",
795 "event selector. use 'perf list' to list available events", 842 "event selector. use 'perf list' to list available events",
796 parse_events), 843 parse_events),
@@ -802,6 +849,8 @@ static const struct option options[] = {
802 "record events on existing thread id"), 849 "record events on existing thread id"),
803 OPT_INTEGER('r', "realtime", &realtime_prio, 850 OPT_INTEGER('r', "realtime", &realtime_prio,
804 "collect data with this RT SCHED_FIFO priority"), 851 "collect data with this RT SCHED_FIFO priority"),
852 OPT_BOOLEAN('D', "no-delay", &nodelay,
853 "collect data without buffering"),
805 OPT_BOOLEAN('R', "raw-samples", &raw_samples, 854 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
806 "collect raw sample records from all opened counters"), 855 "collect raw sample records from all opened counters"),
807 OPT_BOOLEAN('a', "all-cpus", &system_wide, 856 OPT_BOOLEAN('a', "all-cpus", &system_wide,
@@ -828,27 +877,31 @@ static const struct option options[] = {
828 "per thread counts"), 877 "per thread counts"),
829 OPT_BOOLEAN('d', "data", &sample_address, 878 OPT_BOOLEAN('d', "data", &sample_address,
830 "Sample addresses"), 879 "Sample addresses"),
880 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
831 OPT_BOOLEAN('n', "no-samples", &no_samples, 881 OPT_BOOLEAN('n', "no-samples", &no_samples,
832 "don't sample"), 882 "don't sample"),
833 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid, 883 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
834 "do not update the buildid cache"), 884 "do not update the buildid cache"),
885 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
886 "do not collect buildids in perf.data"),
835 OPT_END() 887 OPT_END()
836}; 888};
837 889
838int cmd_record(int argc, const char **argv, const char *prefix __used) 890int cmd_record(int argc, const char **argv, const char *prefix __used)
839{ 891{
840 int i, j, err = -ENOMEM; 892 int err = -ENOMEM;
893 struct perf_evsel *pos;
841 894
842 argc = parse_options(argc, argv, options, record_usage, 895 argc = parse_options(argc, argv, record_options, record_usage,
843 PARSE_OPT_STOP_AT_NON_OPTION); 896 PARSE_OPT_STOP_AT_NON_OPTION);
844 if (!argc && target_pid == -1 && target_tid == -1 && 897 if (!argc && target_pid == -1 && target_tid == -1 &&
845 !system_wide && !cpu_list) 898 !system_wide && !cpu_list)
846 usage_with_options(record_usage, options); 899 usage_with_options(record_usage, record_options);
847 900
848 if (force && append_file) { 901 if (force && append_file) {
849 fprintf(stderr, "Can't overwrite and append at the same time." 902 fprintf(stderr, "Can't overwrite and append at the same time."
850 " You need to choose between -f and -A"); 903 " You need to choose between -f and -A");
851 usage_with_options(record_usage, options); 904 usage_with_options(record_usage, record_options);
852 } else if (append_file) { 905 } else if (append_file) {
853 write_mode = WRITE_APPEND; 906 write_mode = WRITE_APPEND;
854 } else { 907 } else {
@@ -856,41 +909,38 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
856 } 909 }
857 910
858 symbol__init(); 911 symbol__init();
859 if (no_buildid) 912
913 if (no_buildid_cache || no_buildid)
860 disable_buildid_cache(); 914 disable_buildid_cache();
861 915
862 if (!nr_counters) { 916 if (list_empty(&evsel_list) && perf_evsel_list__create_default() < 0) {
863 nr_counters = 1; 917 pr_err("Not enough memory for event selector list\n");
864 attrs[0].type = PERF_TYPE_HARDWARE; 918 goto out_symbol_exit;
865 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
866 } 919 }
867 920
868 if (target_pid != -1) { 921 if (target_pid != -1)
869 target_tid = target_pid; 922 target_tid = target_pid;
870 thread_num = find_all_tid(target_pid, &all_tids);
871 if (thread_num <= 0) {
872 fprintf(stderr, "Can't find all threads of pid %d\n",
873 target_pid);
874 usage_with_options(record_usage, options);
875 }
876 } else {
877 all_tids=malloc(sizeof(pid_t));
878 if (!all_tids)
879 goto out_symbol_exit;
880 923
881 all_tids[0] = target_tid; 924 threads = thread_map__new(target_pid, target_tid);
882 thread_num = 1; 925 if (threads == NULL) {
926 pr_err("Problems finding threads of monitor\n");
927 usage_with_options(record_usage, record_options);
883 } 928 }
884 929
885 for (i = 0; i < MAX_NR_CPUS; i++) { 930 cpus = cpu_map__new(cpu_list);
886 for (j = 0; j < MAX_COUNTERS; j++) { 931 if (cpus == NULL) {
887 fd[i][j] = malloc(sizeof(int)*thread_num); 932 perror("failed to parse CPUs map");
888 if (!fd[i][j]) 933 return -1;
889 goto out_free_fd;
890 }
891 } 934 }
892 event_array = malloc( 935
893 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num); 936 list_for_each_entry(pos, &evsel_list, node) {
937 if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
938 goto out_free_fd;
939 if (perf_header__push_event(pos->attr.config, event_name(pos)))
940 goto out_free_fd;
941 }
942 event_array = malloc((sizeof(struct pollfd) * MAX_NR_CPUS *
943 MAX_COUNTERS * threads->nr));
894 if (!event_array) 944 if (!event_array)
895 goto out_free_fd; 945 goto out_free_fd;
896 946
@@ -917,12 +967,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
917out_free_event_array: 967out_free_event_array:
918 free(event_array); 968 free(event_array);
919out_free_fd: 969out_free_fd:
920 for (i = 0; i < MAX_NR_CPUS; i++) { 970 thread_map__delete(threads);
921 for (j = 0; j < MAX_COUNTERS; j++) 971 threads = NULL;
922 free(fd[i][j]);
923 }
924 free(all_tids);
925 all_tids = NULL;
926out_symbol_exit: 972out_symbol_exit:
927 symbol__exit(); 973 symbol__exit();
928 return err; 974 return err;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5de405d45230..c27e31f289e6 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -150,13 +150,13 @@ static int add_event_total(struct perf_session *session,
150 return 0; 150 return 0;
151} 151}
152 152
153static int process_sample_event(event_t *event, struct perf_session *session) 153static int process_sample_event(event_t *event, struct sample_data *sample,
154 struct perf_session *session)
154{ 155{
155 struct sample_data data = { .period = 1, };
156 struct addr_location al; 156 struct addr_location al;
157 struct perf_event_attr *attr; 157 struct perf_event_attr *attr;
158 158
159 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 159 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
160 fprintf(stderr, "problem processing %d event, skipping it.\n", 160 fprintf(stderr, "problem processing %d event, skipping it.\n",
161 event->header.type); 161 event->header.type);
162 return -1; 162 return -1;
@@ -165,14 +165,14 @@ static int process_sample_event(event_t *event, struct perf_session *session)
165 if (al.filtered || (hide_unresolved && al.sym == NULL)) 165 if (al.filtered || (hide_unresolved && al.sym == NULL))
166 return 0; 166 return 0;
167 167
168 if (perf_session__add_hist_entry(session, &al, &data)) { 168 if (perf_session__add_hist_entry(session, &al, sample)) {
169 pr_debug("problem incrementing symbol period, skipping event\n"); 169 pr_debug("problem incrementing symbol period, skipping event\n");
170 return -1; 170 return -1;
171 } 171 }
172 172
173 attr = perf_header__find_attr(data.id, &session->header); 173 attr = perf_header__find_attr(sample->id, &session->header);
174 174
175 if (add_event_total(session, &data, attr)) { 175 if (add_event_total(session, sample, attr)) {
176 pr_debug("problem adding event period\n"); 176 pr_debug("problem adding event period\n");
177 return -1; 177 return -1;
178 } 178 }
@@ -180,7 +180,8 @@ static int process_sample_event(event_t *event, struct perf_session *session)
180 return 0; 180 return 0;
181} 181}
182 182
183static int process_read_event(event_t *event, struct perf_session *session __used) 183static int process_read_event(event_t *event, struct sample_data *sample __used,
184 struct perf_session *session __used)
184{ 185{
185 struct perf_event_attr *attr; 186 struct perf_event_attr *attr;
186 187
@@ -196,7 +197,7 @@ static int process_read_event(event_t *event, struct perf_session *session __use
196 event->read.value); 197 event->read.value);
197 } 198 }
198 199
199 dump_printf(": %d %d %s %Lu\n", event->read.pid, event->read.tid, 200 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
200 attr ? __event_name(attr->type, attr->config) : "FAIL", 201 attr ? __event_name(attr->type, attr->config) : "FAIL",
201 event->read.value); 202 event->read.value);
202 203
@@ -243,6 +244,8 @@ static struct perf_event_ops event_ops = {
243 .event_type = event__process_event_type, 244 .event_type = event__process_event_type,
244 .tracing_data = event__process_tracing_data, 245 .tracing_data = event__process_tracing_data,
245 .build_id = event__process_build_id, 246 .build_id = event__process_build_id,
247 .ordered_samples = true,
248 .ordering_requires_timestamps = true,
246}; 249};
247 250
248extern volatile int session_done; 251extern volatile int session_done;
@@ -307,7 +310,7 @@ static int __cmd_report(void)
307 310
308 signal(SIGINT, sig_handler); 311 signal(SIGINT, sig_handler);
309 312
310 session = perf_session__new(input_name, O_RDONLY, force, false); 313 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
311 if (session == NULL) 314 if (session == NULL)
312 return -ENOMEM; 315 return -ENOMEM;
313 316
@@ -442,6 +445,8 @@ static const struct option options[] = {
442 "dump raw trace in ASCII"), 445 "dump raw trace in ASCII"),
443 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 446 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
444 "file", "vmlinux pathname"), 447 "file", "vmlinux pathname"),
448 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
449 "file", "kallsyms pathname"),
445 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 450 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
446 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 451 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
447 "load module symbols - WARNING: use only with -k and LIVE kernel"), 452 "load module symbols - WARNING: use only with -k and LIVE kernel"),
@@ -478,6 +483,8 @@ static const struct option options[] = {
478 "columns '.' is reserved."), 483 "columns '.' is reserved."),
479 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved, 484 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved,
480 "Only display entries resolved to a symbol"), 485 "Only display entries resolved to a symbol"),
486 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
487 "Look for files with symbols relative to this directory"),
481 OPT_END() 488 OPT_END()
482}; 489};
483 490
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 55f3b5dcc731..29acb894e035 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -193,7 +193,7 @@ static void calibrate_run_measurement_overhead(void)
193 } 193 }
194 run_measurement_overhead = min_delta; 194 run_measurement_overhead = min_delta;
195 195
196 printf("run measurement overhead: %Ld nsecs\n", min_delta); 196 printf("run measurement overhead: %" PRIu64 " nsecs\n", min_delta);
197} 197}
198 198
199static void calibrate_sleep_measurement_overhead(void) 199static void calibrate_sleep_measurement_overhead(void)
@@ -211,7 +211,7 @@ static void calibrate_sleep_measurement_overhead(void)
211 min_delta -= 10000; 211 min_delta -= 10000;
212 sleep_measurement_overhead = min_delta; 212 sleep_measurement_overhead = min_delta;
213 213
214 printf("sleep measurement overhead: %Ld nsecs\n", min_delta); 214 printf("sleep measurement overhead: %" PRIu64 " nsecs\n", min_delta);
215} 215}
216 216
217static struct sched_atom * 217static struct sched_atom *
@@ -489,7 +489,8 @@ static void create_tasks(void)
489 489
490 err = pthread_attr_init(&attr); 490 err = pthread_attr_init(&attr);
491 BUG_ON(err); 491 BUG_ON(err);
492 err = pthread_attr_setstacksize(&attr, (size_t)(16*1024)); 492 err = pthread_attr_setstacksize(&attr,
493 (size_t) max(16 * 1024, PTHREAD_STACK_MIN));
493 BUG_ON(err); 494 BUG_ON(err);
494 err = pthread_mutex_lock(&start_work_mutex); 495 err = pthread_mutex_lock(&start_work_mutex);
495 BUG_ON(err); 496 BUG_ON(err);
@@ -616,13 +617,13 @@ static void test_calibrations(void)
616 burn_nsecs(1e6); 617 burn_nsecs(1e6);
617 T1 = get_nsecs(); 618 T1 = get_nsecs();
618 619
619 printf("the run test took %Ld nsecs\n", T1-T0); 620 printf("the run test took %" PRIu64 " nsecs\n", T1 - T0);
620 621
621 T0 = get_nsecs(); 622 T0 = get_nsecs();
622 sleep_nsecs(1e6); 623 sleep_nsecs(1e6);
623 T1 = get_nsecs(); 624 T1 = get_nsecs();
624 625
625 printf("the sleep test took %Ld nsecs\n", T1-T0); 626 printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0);
626} 627}
627 628
628#define FILL_FIELD(ptr, field, event, data) \ 629#define FILL_FIELD(ptr, field, event, data) \
@@ -815,10 +816,10 @@ replay_switch_event(struct trace_switch_event *switch_event,
815 delta = 0; 816 delta = 0;
816 817
817 if (delta < 0) 818 if (delta < 0)
818 die("hm, delta: %Ld < 0 ?\n", delta); 819 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
819 820
820 if (verbose) { 821 if (verbose) {
821 printf(" ... switch from %s/%d to %s/%d [ran %Ld nsecs]\n", 822 printf(" ... switch from %s/%d to %s/%d [ran %" PRIu64 " nsecs]\n",
822 switch_event->prev_comm, switch_event->prev_pid, 823 switch_event->prev_comm, switch_event->prev_pid,
823 switch_event->next_comm, switch_event->next_pid, 824 switch_event->next_comm, switch_event->next_pid,
824 delta); 825 delta);
@@ -1047,7 +1048,7 @@ latency_switch_event(struct trace_switch_event *switch_event,
1047 delta = 0; 1048 delta = 0;
1048 1049
1049 if (delta < 0) 1050 if (delta < 0)
1050 die("hm, delta: %Ld < 0 ?\n", delta); 1051 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
1051 1052
1052 1053
1053 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1054 sched_out = perf_session__findnew(session, switch_event->prev_pid);
@@ -1220,7 +1221,7 @@ static void output_lat_thread(struct work_atoms *work_list)
1220 1221
1221 avg = work_list->total_lat / work_list->nb_atoms; 1222 avg = work_list->total_lat / work_list->nb_atoms;
1222 1223
1223 printf("|%11.3f ms |%9llu | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n", 1224 printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n",
1224 (double)work_list->total_runtime / 1e6, 1225 (double)work_list->total_runtime / 1e6,
1225 work_list->nb_atoms, (double)avg / 1e6, 1226 work_list->nb_atoms, (double)avg / 1e6,
1226 (double)work_list->max_lat / 1e6, 1227 (double)work_list->max_lat / 1e6,
@@ -1422,7 +1423,7 @@ map_switch_event(struct trace_switch_event *switch_event,
1422 delta = 0; 1423 delta = 0;
1423 1424
1424 if (delta < 0) 1425 if (delta < 0)
1425 die("hm, delta: %Ld < 0 ?\n", delta); 1426 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
1426 1427
1427 1428
1428 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1429 sched_out = perf_session__findnew(session, switch_event->prev_pid);
@@ -1606,25 +1607,15 @@ process_raw_event(event_t *raw_event __used, struct perf_session *session,
1606 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread); 1607 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
1607} 1608}
1608 1609
1609static int process_sample_event(event_t *event, struct perf_session *session) 1610static int process_sample_event(event_t *event, struct sample_data *sample,
1611 struct perf_session *session)
1610{ 1612{
1611 struct sample_data data;
1612 struct thread *thread; 1613 struct thread *thread;
1613 1614
1614 if (!(session->sample_type & PERF_SAMPLE_RAW)) 1615 if (!(session->sample_type & PERF_SAMPLE_RAW))
1615 return 0; 1616 return 0;
1616 1617
1617 memset(&data, 0, sizeof(data)); 1618 thread = perf_session__findnew(session, sample->pid);
1618 data.time = -1;
1619 data.cpu = -1;
1620 data.period = -1;
1621
1622 event__parse_sample(event, session->sample_type, &data);
1623
1624 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
1625 data.pid, data.tid, data.ip, data.period);
1626
1627 thread = perf_session__findnew(session, data.pid);
1628 if (thread == NULL) { 1619 if (thread == NULL) {
1629 pr_debug("problem processing %d event, skipping it.\n", 1620 pr_debug("problem processing %d event, skipping it.\n",
1630 event->header.type); 1621 event->header.type);
@@ -1633,10 +1624,11 @@ static int process_sample_event(event_t *event, struct perf_session *session)
1633 1624
1634 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1625 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1635 1626
1636 if (profile_cpu != -1 && profile_cpu != (int)data.cpu) 1627 if (profile_cpu != -1 && profile_cpu != (int)sample->cpu)
1637 return 0; 1628 return 0;
1638 1629
1639 process_raw_event(event, session, data.raw_data, data.cpu, data.time, thread); 1630 process_raw_event(event, session, sample->raw_data, sample->cpu,
1631 sample->time, thread);
1640 1632
1641 return 0; 1633 return 0;
1642} 1634}
@@ -1652,7 +1644,8 @@ static struct perf_event_ops event_ops = {
1652static int read_events(void) 1644static int read_events(void)
1653{ 1645{
1654 int err = -EINVAL; 1646 int err = -EINVAL;
1655 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 1647 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1648 0, false, &event_ops);
1656 if (session == NULL) 1649 if (session == NULL)
1657 return -ENOMEM; 1650 return -ENOMEM;
1658 1651
@@ -1720,7 +1713,7 @@ static void __cmd_lat(void)
1720 } 1713 }
1721 1714
1722 printf(" -----------------------------------------------------------------------------------------\n"); 1715 printf(" -----------------------------------------------------------------------------------------\n");
1723 printf(" TOTAL: |%11.3f ms |%9Ld |\n", 1716 printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n",
1724 (double)all_runtime/1e6, all_count); 1717 (double)all_runtime/1e6, all_count);
1725 1718
1726 printf(" ---------------------------------------------------\n"); 1719 printf(" ---------------------------------------------------\n");
@@ -1850,15 +1843,15 @@ static const char *record_args[] = {
1850 "-f", 1843 "-f",
1851 "-m", "1024", 1844 "-m", "1024",
1852 "-c", "1", 1845 "-c", "1",
1853 "-e", "sched:sched_switch:r", 1846 "-e", "sched:sched_switch",
1854 "-e", "sched:sched_stat_wait:r", 1847 "-e", "sched:sched_stat_wait",
1855 "-e", "sched:sched_stat_sleep:r", 1848 "-e", "sched:sched_stat_sleep",
1856 "-e", "sched:sched_stat_iowait:r", 1849 "-e", "sched:sched_stat_iowait",
1857 "-e", "sched:sched_stat_runtime:r", 1850 "-e", "sched:sched_stat_runtime",
1858 "-e", "sched:sched_process_exit:r", 1851 "-e", "sched:sched_process_exit",
1859 "-e", "sched:sched_process_fork:r", 1852 "-e", "sched:sched_process_fork",
1860 "-e", "sched:sched_wakeup:r", 1853 "-e", "sched:sched_wakeup",
1861 "-e", "sched:sched_migrate_task:r", 1854 "-e", "sched:sched_migrate_task",
1862}; 1855};
1863 1856
1864static int __cmd_record(int argc, const char **argv) 1857static int __cmd_record(int argc, const char **argv)
@@ -1869,6 +1862,9 @@ static int __cmd_record(int argc, const char **argv)
1869 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 1862 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
1870 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1863 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1871 1864
1865 if (rec_argv == NULL)
1866 return -ENOMEM;
1867
1872 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1868 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1873 rec_argv[i] = strdup(record_args[i]); 1869 rec_argv[i] = strdup(record_args[i]);
1874 1870
@@ -1888,10 +1884,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __used)
1888 usage_with_options(sched_usage, sched_options); 1884 usage_with_options(sched_usage, sched_options);
1889 1885
1890 /* 1886 /*
1891 * Aliased to 'perf trace' for now: 1887 * Aliased to 'perf script' for now:
1892 */ 1888 */
1893 if (!strcmp(argv[0], "trace")) 1889 if (!strcmp(argv[0], "script"))
1894 return cmd_trace(argc, argv, prefix); 1890 return cmd_script(argc, argv, prefix);
1895 1891
1896 symbol__init(); 1892 symbol__init();
1897 if (!strncmp(argv[0], "rec", 3)) { 1893 if (!strncmp(argv[0], "rec", 3)) {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-script.c
index 2f8df45c4dcb..b766c2a9ac97 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-script.c
@@ -10,6 +10,7 @@
10#include "util/symbol.h" 10#include "util/symbol.h"
11#include "util/thread.h" 11#include "util/thread.h"
12#include "util/trace-event.h" 12#include "util/trace-event.h"
13#include "util/parse-options.h"
13#include "util/util.h" 14#include "util/util.h"
14 15
15static char const *script_name; 16static char const *script_name;
@@ -17,6 +18,7 @@ static char const *generate_script_lang;
17static bool debug_mode; 18static bool debug_mode;
18static u64 last_timestamp; 19static u64 last_timestamp;
19static u64 nr_unordered; 20static u64 nr_unordered;
21extern const struct option record_options[];
20 22
21static int default_start_script(const char *script __unused, 23static int default_start_script(const char *script __unused,
22 int argc __unused, 24 int argc __unused,
@@ -54,29 +56,18 @@ static void setup_scripting(void)
54 56
55static int cleanup_scripting(void) 57static int cleanup_scripting(void)
56{ 58{
57 pr_debug("\nperf trace script stopped\n"); 59 pr_debug("\nperf script stopped\n");
58 60
59 return scripting_ops->stop_script(); 61 return scripting_ops->stop_script();
60} 62}
61 63
62static char const *input_name = "perf.data"; 64static char const *input_name = "perf.data";
63 65
64static int process_sample_event(event_t *event, struct perf_session *session) 66static int process_sample_event(event_t *event, struct sample_data *sample,
67 struct perf_session *session)
65{ 68{
66 struct sample_data data; 69 struct thread *thread = perf_session__findnew(session, event->ip.pid);
67 struct thread *thread;
68
69 memset(&data, 0, sizeof(data));
70 data.time = -1;
71 data.cpu = -1;
72 data.period = 1;
73
74 event__parse_sample(event, session->sample_type, &data);
75
76 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
77 data.pid, data.tid, data.ip, data.period);
78 70
79 thread = perf_session__findnew(session, event->ip.pid);
80 if (thread == NULL) { 71 if (thread == NULL) {
81 pr_debug("problem processing %d event, skipping it.\n", 72 pr_debug("problem processing %d event, skipping it.\n",
82 event->header.type); 73 event->header.type);
@@ -85,13 +76,13 @@ static int process_sample_event(event_t *event, struct perf_session *session)
85 76
86 if (session->sample_type & PERF_SAMPLE_RAW) { 77 if (session->sample_type & PERF_SAMPLE_RAW) {
87 if (debug_mode) { 78 if (debug_mode) {
88 if (data.time < last_timestamp) { 79 if (sample->time < last_timestamp) {
89 pr_err("Samples misordered, previous: %llu " 80 pr_err("Samples misordered, previous: %" PRIu64
90 "this: %llu\n", last_timestamp, 81 " this: %" PRIu64 "\n", last_timestamp,
91 data.time); 82 sample->time);
92 nr_unordered++; 83 nr_unordered++;
93 } 84 }
94 last_timestamp = data.time; 85 last_timestamp = sample->time;
95 return 0; 86 return 0;
96 } 87 }
97 /* 88 /*
@@ -99,21 +90,12 @@ static int process_sample_event(event_t *event, struct perf_session *session)
99 * field, although it should be the same than this perf 90 * field, although it should be the same than this perf
100 * event pid 91 * event pid
101 */ 92 */
102 scripting_ops->process_event(data.cpu, data.raw_data, 93 scripting_ops->process_event(sample->cpu, sample->raw_data,
103 data.raw_size, 94 sample->raw_size,
104 data.time, thread->comm); 95 sample->time, thread->comm);
105 } 96 }
106 97
107 session->hists.stats.total_period += data.period; 98 session->hists.stats.total_period += sample->period;
108 return 0;
109}
110
111static u64 nr_lost;
112
113static int process_lost_event(event_t *event, struct perf_session *session __used)
114{
115 nr_lost += event->lost.lost;
116
117 return 0; 99 return 0;
118} 100}
119 101
@@ -124,7 +106,7 @@ static struct perf_event_ops event_ops = {
124 .event_type = event__process_event_type, 106 .event_type = event__process_event_type,
125 .tracing_data = event__process_tracing_data, 107 .tracing_data = event__process_tracing_data,
126 .build_id = event__process_build_id, 108 .build_id = event__process_build_id,
127 .lost = process_lost_event, 109 .ordering_requires_timestamps = true,
128 .ordered_samples = true, 110 .ordered_samples = true,
129}; 111};
130 112
@@ -135,7 +117,7 @@ static void sig_handler(int sig __unused)
135 session_done = 1; 117 session_done = 1;
136} 118}
137 119
138static int __cmd_trace(struct perf_session *session) 120static int __cmd_script(struct perf_session *session)
139{ 121{
140 int ret; 122 int ret;
141 123
@@ -143,10 +125,8 @@ static int __cmd_trace(struct perf_session *session)
143 125
144 ret = perf_session__process_events(session, &event_ops); 126 ret = perf_session__process_events(session, &event_ops);
145 127
146 if (debug_mode) { 128 if (debug_mode)
147 pr_err("Misordered timestamps: %llu\n", nr_unordered); 129 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
148 pr_err("Lost events: %llu\n", nr_lost);
149 }
150 130
151 return ret; 131 return ret;
152} 132}
@@ -157,7 +137,7 @@ struct script_spec {
157 char spec[0]; 137 char spec[0];
158}; 138};
159 139
160LIST_HEAD(script_specs); 140static LIST_HEAD(script_specs);
161 141
162static struct script_spec *script_spec__new(const char *spec, 142static struct script_spec *script_spec__new(const char *spec,
163 struct scripting_ops *ops) 143 struct scripting_ops *ops)
@@ -245,7 +225,7 @@ static void list_available_languages(void)
245 225
246 fprintf(stderr, "\n"); 226 fprintf(stderr, "\n");
247 fprintf(stderr, "Scripting language extensions (used in " 227 fprintf(stderr, "Scripting language extensions (used in "
248 "perf trace -s [spec:]script.[spec]):\n\n"); 228 "perf script -s [spec:]script.[spec]):\n\n");
249 229
250 list_for_each_entry(s, &script_specs, node) 230 list_for_each_entry(s, &script_specs, node)
251 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name); 231 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name);
@@ -299,17 +279,34 @@ static int parse_scriptname(const struct option *opt __used,
299 return 0; 279 return 0;
300} 280}
301 281
302#define for_each_lang(scripts_dir, lang_dirent, lang_next) \ 282/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */
283static int is_directory(const char *base_path, const struct dirent *dent)
284{
285 char path[PATH_MAX];
286 struct stat st;
287
288 sprintf(path, "%s/%s", base_path, dent->d_name);
289 if (stat(path, &st))
290 return 0;
291
292 return S_ISDIR(st.st_mode);
293}
294
295#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\
303 while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \ 296 while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \
304 lang_next) \ 297 lang_next) \
305 if (lang_dirent.d_type == DT_DIR && \ 298 if ((lang_dirent.d_type == DT_DIR || \
299 (lang_dirent.d_type == DT_UNKNOWN && \
300 is_directory(scripts_path, &lang_dirent))) && \
306 (strcmp(lang_dirent.d_name, ".")) && \ 301 (strcmp(lang_dirent.d_name, ".")) && \
307 (strcmp(lang_dirent.d_name, ".."))) 302 (strcmp(lang_dirent.d_name, "..")))
308 303
309#define for_each_script(lang_dir, script_dirent, script_next) \ 304#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\
310 while (!readdir_r(lang_dir, &script_dirent, &script_next) && \ 305 while (!readdir_r(lang_dir, &script_dirent, &script_next) && \
311 script_next) \ 306 script_next) \
312 if (script_dirent.d_type != DT_DIR) 307 if (script_dirent.d_type != DT_DIR && \
308 (script_dirent.d_type != DT_UNKNOWN || \
309 !is_directory(lang_path, &script_dirent)))
313 310
314 311
315#define RECORD_SUFFIX "-record" 312#define RECORD_SUFFIX "-record"
@@ -322,13 +319,13 @@ struct script_desc {
322 char *args; 319 char *args;
323}; 320};
324 321
325LIST_HEAD(script_descs); 322static LIST_HEAD(script_descs);
326 323
327static struct script_desc *script_desc__new(const char *name) 324static struct script_desc *script_desc__new(const char *name)
328{ 325{
329 struct script_desc *s = zalloc(sizeof(*s)); 326 struct script_desc *s = zalloc(sizeof(*s));
330 327
331 if (s != NULL) 328 if (s != NULL && name)
332 s->name = strdup(name); 329 s->name = strdup(name);
333 330
334 return s; 331 return s;
@@ -337,6 +334,8 @@ static struct script_desc *script_desc__new(const char *name)
337static void script_desc__delete(struct script_desc *s) 334static void script_desc__delete(struct script_desc *s)
338{ 335{
339 free(s->name); 336 free(s->name);
337 free(s->half_liner);
338 free(s->args);
340 free(s); 339 free(s);
341} 340}
342 341
@@ -376,10 +375,10 @@ out_delete_desc:
376 return NULL; 375 return NULL;
377} 376}
378 377
379static char *ends_with(char *str, const char *suffix) 378static const char *ends_with(const char *str, const char *suffix)
380{ 379{
381 size_t suffix_len = strlen(suffix); 380 size_t suffix_len = strlen(suffix);
382 char *p = str; 381 const char *p = str;
383 382
384 if (strlen(str) > suffix_len) { 383 if (strlen(str) > suffix_len) {
385 p = str + strlen(str) - suffix_len; 384 p = str + strlen(str) - suffix_len;
@@ -462,16 +461,16 @@ static int list_available_scripts(const struct option *opt __used,
462 if (!scripts_dir) 461 if (!scripts_dir)
463 return -1; 462 return -1;
464 463
465 for_each_lang(scripts_dir, lang_dirent, lang_next) { 464 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
466 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 465 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
467 lang_dirent.d_name); 466 lang_dirent.d_name);
468 lang_dir = opendir(lang_path); 467 lang_dir = opendir(lang_path);
469 if (!lang_dir) 468 if (!lang_dir)
470 continue; 469 continue;
471 470
472 for_each_script(lang_dir, script_dirent, script_next) { 471 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
473 script_root = strdup(script_dirent.d_name); 472 script_root = strdup(script_dirent.d_name);
474 str = ends_with(script_root, REPORT_SUFFIX); 473 str = (char *)ends_with(script_root, REPORT_SUFFIX);
475 if (str) { 474 if (str) {
476 *str = '\0'; 475 *str = '\0';
477 desc = script_desc__findnew(script_root); 476 desc = script_desc__findnew(script_root);
@@ -510,16 +509,16 @@ static char *get_script_path(const char *script_root, const char *suffix)
510 if (!scripts_dir) 509 if (!scripts_dir)
511 return NULL; 510 return NULL;
512 511
513 for_each_lang(scripts_dir, lang_dirent, lang_next) { 512 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
514 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 513 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
515 lang_dirent.d_name); 514 lang_dirent.d_name);
516 lang_dir = opendir(lang_path); 515 lang_dir = opendir(lang_path);
517 if (!lang_dir) 516 if (!lang_dir)
518 continue; 517 continue;
519 518
520 for_each_script(lang_dir, script_dirent, script_next) { 519 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
521 __script_root = strdup(script_dirent.d_name); 520 __script_root = strdup(script_dirent.d_name);
522 str = ends_with(__script_root, suffix); 521 str = (char *)ends_with(__script_root, suffix);
523 if (str) { 522 if (str) {
524 *str = '\0'; 523 *str = '\0';
525 if (strcmp(__script_root, script_root)) 524 if (strcmp(__script_root, script_root))
@@ -537,8 +536,40 @@ static char *get_script_path(const char *script_root, const char *suffix)
537 return path; 536 return path;
538} 537}
539 538
540static const char * const trace_usage[] = { 539static bool is_top_script(const char *script_path)
541 "perf trace [<options>] <command>", 540{
541 return ends_with(script_path, "top") == NULL ? false : true;
542}
543
544static int has_required_arg(char *script_path)
545{
546 struct script_desc *desc;
547 int n_args = 0;
548 char *p;
549
550 desc = script_desc__new(NULL);
551
552 if (read_script_info(desc, script_path))
553 goto out;
554
555 if (!desc->args)
556 goto out;
557
558 for (p = desc->args; *p; p++)
559 if (*p == '<')
560 n_args++;
561out:
562 script_desc__delete(desc);
563
564 return n_args;
565}
566
567static const char * const script_usage[] = {
568 "perf script [<options>]",
569 "perf script [<options>] record <script> [<record-options>] <command>",
570 "perf script [<options>] report <script> [script-args]",
571 "perf script [<options>] <script> [<record-options>] <command>",
572 "perf script [<options>] <top-script> [script-args]",
542 NULL 573 NULL
543}; 574};
544 575
@@ -555,7 +586,7 @@ static const struct option options[] = {
555 "script file name (lang:script name, script name, or *)", 586 "script file name (lang:script name, script name, or *)",
556 parse_scriptname), 587 parse_scriptname),
557 OPT_STRING('g', "gen-script", &generate_script_lang, "lang", 588 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
558 "generate perf-trace.xx script in specified language"), 589 "generate perf-script.xx script in specified language"),
559 OPT_STRING('i', "input", &input_name, "file", 590 OPT_STRING('i', "input", &input_name, "file",
560 "input file name"), 591 "input file name"),
561 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 592 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
@@ -564,50 +595,81 @@ static const struct option options[] = {
564 OPT_END() 595 OPT_END()
565}; 596};
566 597
567int cmd_trace(int argc, const char **argv, const char *prefix __used) 598static bool have_cmd(int argc, const char **argv)
599{
600 char **__argv = malloc(sizeof(const char *) * argc);
601
602 if (!__argv)
603 die("malloc");
604 memcpy(__argv, argv, sizeof(const char *) * argc);
605 argc = parse_options(argc, (const char **)__argv, record_options,
606 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
607 free(__argv);
608
609 return argc != 0;
610}
611
612int cmd_script(int argc, const char **argv, const char *prefix __used)
568{ 613{
614 char *rec_script_path = NULL;
615 char *rep_script_path = NULL;
569 struct perf_session *session; 616 struct perf_session *session;
570 const char *suffix = NULL; 617 char *script_path = NULL;
571 const char **__argv; 618 const char **__argv;
572 char *script_path; 619 bool system_wide;
573 int i, err; 620 int i, j, err;
574 621
575 if (argc >= 2 && strncmp(argv[1], "rec", strlen("rec")) == 0) { 622 setup_scripting();
576 if (argc < 3) { 623
577 fprintf(stderr, 624 argc = parse_options(argc, argv, options, script_usage,
578 "Please specify a record script\n"); 625 PARSE_OPT_STOP_AT_NON_OPTION);
579 return -1; 626
580 } 627 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
581 suffix = RECORD_SUFFIX; 628 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
629 if (!rec_script_path)
630 return cmd_record(argc, argv, NULL);
582 } 631 }
583 632
584 if (argc >= 2 && strncmp(argv[1], "rep", strlen("rep")) == 0) { 633 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
585 if (argc < 3) { 634 rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
635 if (!rep_script_path) {
586 fprintf(stderr, 636 fprintf(stderr,
587 "Please specify a report script\n"); 637 "Please specify a valid report script"
638 "(see 'perf script -l' for listing)\n");
588 return -1; 639 return -1;
589 } 640 }
590 suffix = REPORT_SUFFIX;
591 } 641 }
592 642
593 /* make sure PERF_EXEC_PATH is set for scripts */ 643 /* make sure PERF_EXEC_PATH is set for scripts */
594 perf_set_argv_exec_path(perf_exec_path()); 644 perf_set_argv_exec_path(perf_exec_path());
595 645
596 if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) { 646 if (argc && !script_name && !rec_script_path && !rep_script_path) {
597 char *record_script_path, *report_script_path;
598 int live_pipe[2]; 647 int live_pipe[2];
648 int rep_args;
599 pid_t pid; 649 pid_t pid;
600 650
601 record_script_path = get_script_path(argv[1], RECORD_SUFFIX); 651 rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
602 if (!record_script_path) { 652 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
603 fprintf(stderr, "record script not found\n"); 653
604 return -1; 654 if (!rec_script_path && !rep_script_path) {
655 fprintf(stderr, " Couldn't find script %s\n\n See perf"
656 " script -l for available scripts.\n", argv[0]);
657 usage_with_options(script_usage, options);
605 } 658 }
606 659
607 report_script_path = get_script_path(argv[1], REPORT_SUFFIX); 660 if (is_top_script(argv[0])) {
608 if (!report_script_path) { 661 rep_args = argc - 1;
609 fprintf(stderr, "report script not found\n"); 662 } else {
610 return -1; 663 int rec_args;
664
665 rep_args = has_required_arg(rep_script_path);
666 rec_args = (argc - 1) - rep_args;
667 if (rec_args < 0) {
668 fprintf(stderr, " %s script requires options."
669 "\n\n See perf script -l for available "
670 "scripts and options.\n", argv[0]);
671 usage_with_options(script_usage, options);
672 }
611 } 673 }
612 674
613 if (pipe(live_pipe) < 0) { 675 if (pipe(live_pipe) < 0) {
@@ -622,66 +684,90 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
622 } 684 }
623 685
624 if (!pid) { 686 if (!pid) {
687 system_wide = true;
688 j = 0;
689
625 dup2(live_pipe[1], 1); 690 dup2(live_pipe[1], 1);
626 close(live_pipe[0]); 691 close(live_pipe[0]);
627 692
628 __argv = malloc(6 * sizeof(const char *)); 693 if (!is_top_script(argv[0]))
629 __argv[0] = "/bin/sh"; 694 system_wide = !have_cmd(argc - rep_args,
630 __argv[1] = record_script_path; 695 &argv[rep_args]);
631 __argv[2] = "-q"; 696
632 __argv[3] = "-o"; 697 __argv = malloc((argc + 6) * sizeof(const char *));
633 __argv[4] = "-"; 698 if (!__argv)
634 __argv[5] = NULL; 699 die("malloc");
700
701 __argv[j++] = "/bin/sh";
702 __argv[j++] = rec_script_path;
703 if (system_wide)
704 __argv[j++] = "-a";
705 __argv[j++] = "-q";
706 __argv[j++] = "-o";
707 __argv[j++] = "-";
708 for (i = rep_args + 1; i < argc; i++)
709 __argv[j++] = argv[i];
710 __argv[j++] = NULL;
635 711
636 execvp("/bin/sh", (char **)__argv); 712 execvp("/bin/sh", (char **)__argv);
713 free(__argv);
637 exit(-1); 714 exit(-1);
638 } 715 }
639 716
640 dup2(live_pipe[0], 0); 717 dup2(live_pipe[0], 0);
641 close(live_pipe[1]); 718 close(live_pipe[1]);
642 719
643 __argv = malloc((argc + 3) * sizeof(const char *)); 720 __argv = malloc((argc + 4) * sizeof(const char *));
644 __argv[0] = "/bin/sh"; 721 if (!__argv)
645 __argv[1] = report_script_path; 722 die("malloc");
646 for (i = 2; i < argc; i++) 723 j = 0;
647 __argv[i] = argv[i]; 724 __argv[j++] = "/bin/sh";
648 __argv[i++] = "-i"; 725 __argv[j++] = rep_script_path;
649 __argv[i++] = "-"; 726 for (i = 1; i < rep_args + 1; i++)
650 __argv[i++] = NULL; 727 __argv[j++] = argv[i];
728 __argv[j++] = "-i";
729 __argv[j++] = "-";
730 __argv[j++] = NULL;
651 731
652 execvp("/bin/sh", (char **)__argv); 732 execvp("/bin/sh", (char **)__argv);
733 free(__argv);
653 exit(-1); 734 exit(-1);
654 } 735 }
655 736
656 if (suffix) { 737 if (rec_script_path)
657 script_path = get_script_path(argv[2], suffix); 738 script_path = rec_script_path;
658 if (!script_path) { 739 if (rep_script_path)
659 fprintf(stderr, "script not found\n"); 740 script_path = rep_script_path;
660 return -1; 741
661 } 742 if (script_path) {
662 743 system_wide = false;
663 __argv = malloc((argc + 1) * sizeof(const char *)); 744 j = 0;
664 __argv[0] = "/bin/sh"; 745
665 __argv[1] = script_path; 746 if (rec_script_path)
666 for (i = 3; i < argc; i++) 747 system_wide = !have_cmd(argc - 1, &argv[1]);
667 __argv[i - 1] = argv[i]; 748
668 __argv[argc - 1] = NULL; 749 __argv = malloc((argc + 2) * sizeof(const char *));
750 if (!__argv)
751 die("malloc");
752 __argv[j++] = "/bin/sh";
753 __argv[j++] = script_path;
754 if (system_wide)
755 __argv[j++] = "-a";
756 for (i = 2; i < argc; i++)
757 __argv[j++] = argv[i];
758 __argv[j++] = NULL;
669 759
670 execvp("/bin/sh", (char **)__argv); 760 execvp("/bin/sh", (char **)__argv);
761 free(__argv);
671 exit(-1); 762 exit(-1);
672 } 763 }
673 764
674 setup_scripting();
675
676 argc = parse_options(argc, argv, options, trace_usage,
677 PARSE_OPT_STOP_AT_NON_OPTION);
678
679 if (symbol__init() < 0) 765 if (symbol__init() < 0)
680 return -1; 766 return -1;
681 if (!script_name) 767 if (!script_name)
682 setup_pager(); 768 setup_pager();
683 769
684 session = perf_session__new(input_name, O_RDONLY, 0, false); 770 session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
685 if (session == NULL) 771 if (session == NULL)
686 return -ENOMEM; 772 return -ENOMEM;
687 773
@@ -715,7 +801,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
715 return -1; 801 return -1;
716 } 802 }
717 803
718 err = scripting_ops->generate_script("perf-trace"); 804 err = scripting_ops->generate_script("perf-script");
719 goto out; 805 goto out;
720 } 806 }
721 807
@@ -723,10 +809,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
723 err = scripting_ops->start_script(script_name, argc, argv); 809 err = scripting_ops->start_script(script_name, argc, argv);
724 if (err) 810 if (err)
725 goto out; 811 goto out;
726 pr_debug("perf trace started with script %s\n\n", script_name); 812 pr_debug("perf script started with script %s\n\n", script_name);
727 } 813 }
728 814
729 err = __cmd_trace(session); 815 err = __cmd_script(session);
730 816
731 perf_session__delete(session); 817 perf_session__delete(session);
732 cleanup_scripting(); 818 cleanup_scripting();
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a6b4d44f9502..a482a191a0ca 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,6 +43,7 @@
43#include "util/parse-options.h" 43#include "util/parse-options.h"
44#include "util/parse-events.h" 44#include "util/parse-events.h"
45#include "util/event.h" 45#include "util/event.h"
46#include "util/evsel.h"
46#include "util/debug.h" 47#include "util/debug.h"
47#include "util/header.h" 48#include "util/header.h"
48#include "util/cpumap.h" 49#include "util/cpumap.h"
@@ -52,6 +53,8 @@
52#include <math.h> 53#include <math.h>
53#include <locale.h> 54#include <locale.h>
54 55
56#define DEFAULT_SEPARATOR " "
57
55static struct perf_event_attr default_attrs[] = { 58static struct perf_event_attr default_attrs[] = {
56 59
57 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 60 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
@@ -69,25 +72,23 @@ static struct perf_event_attr default_attrs[] = {
69}; 72};
70 73
71static bool system_wide = false; 74static bool system_wide = false;
72static int nr_cpus = 0; 75static struct cpu_map *cpus;
73static int run_idx = 0; 76static int run_idx = 0;
74 77
75static int run_count = 1; 78static int run_count = 1;
76static bool no_inherit = false; 79static bool no_inherit = false;
77static bool scale = true; 80static bool scale = true;
81static bool no_aggr = false;
78static pid_t target_pid = -1; 82static pid_t target_pid = -1;
79static pid_t target_tid = -1; 83static pid_t target_tid = -1;
80static pid_t *all_tids = NULL; 84static struct thread_map *threads;
81static int thread_num = 0;
82static pid_t child_pid = -1; 85static pid_t child_pid = -1;
83static bool null_run = false; 86static bool null_run = false;
84static bool big_num = false; 87static bool big_num = true;
88static int big_num_opt = -1;
85static const char *cpu_list; 89static const char *cpu_list;
86 90static const char *csv_sep = NULL;
87 91static bool csv_output = false;
88static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
89
90static int event_scaled[MAX_COUNTERS];
91 92
92static volatile int done = 0; 93static volatile int done = 0;
93 94
@@ -96,6 +97,22 @@ struct stats
96 double n, mean, M2; 97 double n, mean, M2;
97}; 98};
98 99
100struct perf_stat {
101 struct stats res_stats[3];
102};
103
104static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
105{
106 evsel->priv = zalloc(sizeof(struct perf_stat));
107 return evsel->priv == NULL ? -ENOMEM : 0;
108}
109
110static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
111{
112 free(evsel->priv);
113 evsel->priv = NULL;
114}
115
99static void update_stats(struct stats *stats, u64 val) 116static void update_stats(struct stats *stats, u64 val)
100{ 117{
101 double delta; 118 double delta;
@@ -135,69 +152,38 @@ static double stddev_stats(struct stats *stats)
135 return sqrt(variance_mean); 152 return sqrt(variance_mean);
136} 153}
137 154
138struct stats event_res_stats[MAX_COUNTERS][3]; 155struct stats runtime_nsecs_stats[MAX_NR_CPUS];
139struct stats runtime_nsecs_stats; 156struct stats runtime_cycles_stats[MAX_NR_CPUS];
157struct stats runtime_branches_stats[MAX_NR_CPUS];
140struct stats walltime_nsecs_stats; 158struct stats walltime_nsecs_stats;
141struct stats runtime_cycles_stats;
142struct stats runtime_branches_stats;
143 159
144#define MATCH_EVENT(t, c, counter) \ 160static int create_perf_stat_counter(struct perf_evsel *evsel)
145 (attrs[counter].type == PERF_TYPE_##t && \
146 attrs[counter].config == PERF_COUNT_##c)
147
148#define ERR_PERF_OPEN \
149"Error: counter %d, sys_perf_event_open() syscall returned with %d (%s)\n"
150
151static int create_perf_stat_counter(int counter)
152{ 161{
153 struct perf_event_attr *attr = attrs + counter; 162 struct perf_event_attr *attr = &evsel->attr;
154 int thread;
155 int ncreated = 0;
156 163
157 if (scale) 164 if (scale)
158 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 165 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
159 PERF_FORMAT_TOTAL_TIME_RUNNING; 166 PERF_FORMAT_TOTAL_TIME_RUNNING;
160 167
161 if (system_wide) { 168 if (system_wide)
162 int cpu; 169 return perf_evsel__open_per_cpu(evsel, cpus);
163 170
164 for (cpu = 0; cpu < nr_cpus; cpu++) { 171 attr->inherit = !no_inherit;
165 fd[cpu][counter][0] = sys_perf_event_open(attr, 172 if (target_pid == -1 && target_tid == -1) {
166 -1, cpumap[cpu], -1, 0); 173 attr->disabled = 1;
167 if (fd[cpu][counter][0] < 0) 174 attr->enable_on_exec = 1;
168 pr_debug(ERR_PERF_OPEN, counter,
169 fd[cpu][counter][0], strerror(errno));
170 else
171 ++ncreated;
172 }
173 } else {
174 attr->inherit = !no_inherit;
175 if (target_pid == -1 && target_tid == -1) {
176 attr->disabled = 1;
177 attr->enable_on_exec = 1;
178 }
179 for (thread = 0; thread < thread_num; thread++) {
180 fd[0][counter][thread] = sys_perf_event_open(attr,
181 all_tids[thread], -1, -1, 0);
182 if (fd[0][counter][thread] < 0)
183 pr_debug(ERR_PERF_OPEN, counter,
184 fd[0][counter][thread],
185 strerror(errno));
186 else
187 ++ncreated;
188 }
189 } 175 }
190 176
191 return ncreated; 177 return perf_evsel__open_per_thread(evsel, threads);
192} 178}
193 179
194/* 180/*
195 * Does the counter have nsecs as a unit? 181 * Does the counter have nsecs as a unit?
196 */ 182 */
197static inline int nsec_counter(int counter) 183static inline int nsec_counter(struct perf_evsel *evsel)
198{ 184{
199 if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) || 185 if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
200 MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) 186 perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
201 return 1; 187 return 1;
202 188
203 return 0; 189 return 0;
@@ -205,84 +191,73 @@ static inline int nsec_counter(int counter)
205 191
206/* 192/*
207 * Read out the results of a single counter: 193 * Read out the results of a single counter:
194 * aggregate counts across CPUs in system-wide mode
208 */ 195 */
209static void read_counter(int counter) 196static int read_counter_aggr(struct perf_evsel *counter)
210{ 197{
211 u64 count[3], single_count[3]; 198 struct perf_stat *ps = counter->priv;
212 int cpu; 199 u64 *count = counter->counts->aggr.values;
213 size_t res, nv; 200 int i;
214 int scaled;
215 int i, thread;
216 201
217 count[0] = count[1] = count[2] = 0; 202 if (__perf_evsel__read(counter, cpus->nr, threads->nr, scale) < 0)
203 return -1;
218 204
219 nv = scale ? 3 : 1; 205 for (i = 0; i < 3; i++)
220 for (cpu = 0; cpu < nr_cpus; cpu++) { 206 update_stats(&ps->res_stats[i], count[i]);
221 for (thread = 0; thread < thread_num; thread++) {
222 if (fd[cpu][counter][thread] < 0)
223 continue;
224 207
225 res = read(fd[cpu][counter][thread], 208 if (verbose) {
226 single_count, nv * sizeof(u64)); 209 fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
227 assert(res == nv * sizeof(u64)); 210 event_name(counter), count[0], count[1], count[2]);
211 }
228 212
229 close(fd[cpu][counter][thread]); 213 /*
230 fd[cpu][counter][thread] = -1; 214 * Save the full runtime - to allow normalization during printout:
215 */
216 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
217 update_stats(&runtime_nsecs_stats[0], count[0]);
218 if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
219 update_stats(&runtime_cycles_stats[0], count[0]);
220 if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
221 update_stats(&runtime_branches_stats[0], count[0]);
231 222
232 count[0] += single_count[0]; 223 return 0;
233 if (scale) { 224}
234 count[1] += single_count[1];
235 count[2] += single_count[2];
236 }
237 }
238 }
239 225
240 scaled = 0; 226/*
241 if (scale) { 227 * Read out the results of a single counter:
242 if (count[2] == 0) { 228 * do not aggregate counts across CPUs in system-wide mode
243 event_scaled[counter] = -1; 229 */
244 count[0] = 0; 230static int read_counter(struct perf_evsel *counter)
245 return; 231{
246 } 232 u64 *count;
233 int cpu;
247 234
248 if (count[2] < count[1]) { 235 for (cpu = 0; cpu < cpus->nr; cpu++) {
249 event_scaled[counter] = 1; 236 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
250 count[0] = (unsigned long long) 237 return -1;
251 ((double)count[0] * count[1] / count[2] + 0.5);
252 }
253 }
254 238
255 for (i = 0; i < 3; i++) 239 count = counter->counts->cpu[cpu].values;
256 update_stats(&event_res_stats[counter][i], count[i]);
257 240
258 if (verbose) { 241 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
259 fprintf(stderr, "%s: %Ld %Ld %Ld\n", event_name(counter), 242 update_stats(&runtime_nsecs_stats[cpu], count[0]);
260 count[0], count[1], count[2]); 243 if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
244 update_stats(&runtime_cycles_stats[cpu], count[0]);
245 if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
246 update_stats(&runtime_branches_stats[cpu], count[0]);
261 } 247 }
262 248
263 /* 249 return 0;
264 * Save the full runtime - to allow normalization during printout:
265 */
266 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
267 update_stats(&runtime_nsecs_stats, count[0]);
268 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
269 update_stats(&runtime_cycles_stats, count[0]);
270 if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter))
271 update_stats(&runtime_branches_stats, count[0]);
272} 250}
273 251
274static int run_perf_stat(int argc __used, const char **argv) 252static int run_perf_stat(int argc __used, const char **argv)
275{ 253{
276 unsigned long long t0, t1; 254 unsigned long long t0, t1;
255 struct perf_evsel *counter;
277 int status = 0; 256 int status = 0;
278 int counter, ncreated = 0;
279 int child_ready_pipe[2], go_pipe[2]; 257 int child_ready_pipe[2], go_pipe[2];
280 const bool forks = (argc > 0); 258 const bool forks = (argc > 0);
281 char buf; 259 char buf;
282 260
283 if (!system_wide)
284 nr_cpus = 1;
285
286 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 261 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
287 perror("failed to create pipes"); 262 perror("failed to create pipes");
288 exit(1); 263 exit(1);
@@ -322,7 +297,7 @@ static int run_perf_stat(int argc __used, const char **argv)
322 } 297 }
323 298
324 if (target_tid == -1 && target_pid == -1 && !system_wide) 299 if (target_tid == -1 && target_pid == -1 && !system_wide)
325 all_tids[0] = child_pid; 300 threads->map[0] = child_pid;
326 301
327 /* 302 /*
328 * Wait for the child to be ready to exec. 303 * Wait for the child to be ready to exec.
@@ -334,16 +309,25 @@ static int run_perf_stat(int argc __used, const char **argv)
334 close(child_ready_pipe[0]); 309 close(child_ready_pipe[0]);
335 } 310 }
336 311
337 for (counter = 0; counter < nr_counters; counter++) 312 list_for_each_entry(counter, &evsel_list, node) {
338 ncreated += create_perf_stat_counter(counter); 313 if (create_perf_stat_counter(counter) < 0) {
339 314 if (errno == -EPERM || errno == -EACCES) {
340 if (ncreated == 0) { 315 error("You may not have permission to collect %sstats.\n"
341 pr_err("No permission to collect %sstats.\n" 316 "\t Consider tweaking"
342 "Consider tweaking /proc/sys/kernel/perf_event_paranoid.\n", 317 " /proc/sys/kernel/perf_event_paranoid or running as root.",
343 system_wide ? "system-wide " : ""); 318 system_wide ? "system-wide " : "");
344 if (child_pid != -1) 319 } else if (errno == ENOENT) {
345 kill(child_pid, SIGTERM); 320 error("%s event is not supported. ", event_name(counter));
346 return -1; 321 } else {
322 error("open_counter returned with %d (%s). "
323 "/bin/dmesg may provide additional information.\n",
324 errno, strerror(errno));
325 }
326 if (child_pid != -1)
327 kill(child_pid, SIGTERM);
328 die("Not all events could be opened.\n");
329 return -1;
330 }
347 } 331 }
348 332
349 /* 333 /*
@@ -362,60 +346,97 @@ static int run_perf_stat(int argc __used, const char **argv)
362 346
363 update_stats(&walltime_nsecs_stats, t1 - t0); 347 update_stats(&walltime_nsecs_stats, t1 - t0);
364 348
365 for (counter = 0; counter < nr_counters; counter++) 349 if (no_aggr) {
366 read_counter(counter); 350 list_for_each_entry(counter, &evsel_list, node) {
351 read_counter(counter);
352 perf_evsel__close_fd(counter, cpus->nr, 1);
353 }
354 } else {
355 list_for_each_entry(counter, &evsel_list, node) {
356 read_counter_aggr(counter);
357 perf_evsel__close_fd(counter, cpus->nr, threads->nr);
358 }
359 }
367 360
368 return WEXITSTATUS(status); 361 return WEXITSTATUS(status);
369} 362}
370 363
371static void print_noise(int counter, double avg) 364static void print_noise(struct perf_evsel *evsel, double avg)
372{ 365{
366 struct perf_stat *ps;
367
373 if (run_count == 1) 368 if (run_count == 1)
374 return; 369 return;
375 370
371 ps = evsel->priv;
376 fprintf(stderr, " ( +- %7.3f%% )", 372 fprintf(stderr, " ( +- %7.3f%% )",
377 100 * stddev_stats(&event_res_stats[counter][0]) / avg); 373 100 * stddev_stats(&ps->res_stats[0]) / avg);
378} 374}
379 375
380static void nsec_printout(int counter, double avg) 376static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
381{ 377{
382 double msecs = avg / 1e6; 378 double msecs = avg / 1e6;
379 char cpustr[16] = { '\0', };
380 const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s";
381
382 if (no_aggr)
383 sprintf(cpustr, "CPU%*d%s",
384 csv_output ? 0 : -4,
385 cpus->map[cpu], csv_sep);
383 386
384 fprintf(stderr, " %18.6f %-24s", msecs, event_name(counter)); 387 fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
385 388
386 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { 389 if (csv_output)
390 return;
391
392 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
387 fprintf(stderr, " # %10.3f CPUs ", 393 fprintf(stderr, " # %10.3f CPUs ",
388 avg / avg_stats(&walltime_nsecs_stats)); 394 avg / avg_stats(&walltime_nsecs_stats));
389 }
390} 395}
391 396
392static void abs_printout(int counter, double avg) 397static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
393{ 398{
394 double total, ratio = 0.0; 399 double total, ratio = 0.0;
400 char cpustr[16] = { '\0', };
401 const char *fmt;
395 402
396 if (big_num) 403 if (csv_output)
397 fprintf(stderr, " %'18.0f %-24s", avg, event_name(counter)); 404 fmt = "%s%.0f%s%s";
405 else if (big_num)
406 fmt = "%s%'18.0f%s%-24s";
398 else 407 else
399 fprintf(stderr, " %18.0f %-24s", avg, event_name(counter)); 408 fmt = "%s%18.0f%s%-24s";
400 409
401 if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { 410 if (no_aggr)
402 total = avg_stats(&runtime_cycles_stats); 411 sprintf(cpustr, "CPU%*d%s",
412 csv_output ? 0 : -4,
413 cpus->map[cpu], csv_sep);
414 else
415 cpu = 0;
416
417 fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
418
419 if (csv_output)
420 return;
421
422 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
423 total = avg_stats(&runtime_cycles_stats[cpu]);
403 424
404 if (total) 425 if (total)
405 ratio = avg / total; 426 ratio = avg / total;
406 427
407 fprintf(stderr, " # %10.3f IPC ", ratio); 428 fprintf(stderr, " # %10.3f IPC ", ratio);
408 } else if (MATCH_EVENT(HARDWARE, HW_BRANCH_MISSES, counter) && 429 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
409 runtime_branches_stats.n != 0) { 430 runtime_branches_stats[cpu].n != 0) {
410 total = avg_stats(&runtime_branches_stats); 431 total = avg_stats(&runtime_branches_stats[cpu]);
411 432
412 if (total) 433 if (total)
413 ratio = avg * 100 / total; 434 ratio = avg * 100 / total;
414 435
415 fprintf(stderr, " # %10.3f %% ", ratio); 436 fprintf(stderr, " # %10.3f %% ", ratio);
416 437
417 } else if (runtime_nsecs_stats.n != 0) { 438 } else if (runtime_nsecs_stats[cpu].n != 0) {
418 total = avg_stats(&runtime_nsecs_stats); 439 total = avg_stats(&runtime_nsecs_stats[cpu]);
419 440
420 if (total) 441 if (total)
421 ratio = 1000.0 * avg / total; 442 ratio = 1000.0 * avg / total;
@@ -426,30 +447,38 @@ static void abs_printout(int counter, double avg)
426 447
427/* 448/*
428 * Print out the results of a single counter: 449 * Print out the results of a single counter:
450 * aggregated counts in system-wide mode
429 */ 451 */
430static void print_counter(int counter) 452static void print_counter_aggr(struct perf_evsel *counter)
431{ 453{
432 double avg = avg_stats(&event_res_stats[counter][0]); 454 struct perf_stat *ps = counter->priv;
433 int scaled = event_scaled[counter]; 455 double avg = avg_stats(&ps->res_stats[0]);
456 int scaled = counter->counts->scaled;
434 457
435 if (scaled == -1) { 458 if (scaled == -1) {
436 fprintf(stderr, " %18s %-24s\n", 459 fprintf(stderr, "%*s%s%-24s\n",
437 "<not counted>", event_name(counter)); 460 csv_output ? 0 : 18,
461 "<not counted>", csv_sep, event_name(counter));
438 return; 462 return;
439 } 463 }
440 464
441 if (nsec_counter(counter)) 465 if (nsec_counter(counter))
442 nsec_printout(counter, avg); 466 nsec_printout(-1, counter, avg);
443 else 467 else
444 abs_printout(counter, avg); 468 abs_printout(-1, counter, avg);
469
470 if (csv_output) {
471 fputc('\n', stderr);
472 return;
473 }
445 474
446 print_noise(counter, avg); 475 print_noise(counter, avg);
447 476
448 if (scaled) { 477 if (scaled) {
449 double avg_enabled, avg_running; 478 double avg_enabled, avg_running;
450 479
451 avg_enabled = avg_stats(&event_res_stats[counter][1]); 480 avg_enabled = avg_stats(&ps->res_stats[1]);
452 avg_running = avg_stats(&event_res_stats[counter][2]); 481 avg_running = avg_stats(&ps->res_stats[2]);
453 482
454 fprintf(stderr, " (scaled from %.2f%%)", 483 fprintf(stderr, " (scaled from %.2f%%)",
455 100 * avg_running / avg_enabled); 484 100 * avg_running / avg_enabled);
@@ -458,40 +487,92 @@ static void print_counter(int counter)
458 fprintf(stderr, "\n"); 487 fprintf(stderr, "\n");
459} 488}
460 489
490/*
491 * Print out the results of a single counter:
492 * does not use aggregated count in system-wide
493 */
494static void print_counter(struct perf_evsel *counter)
495{
496 u64 ena, run, val;
497 int cpu;
498
499 for (cpu = 0; cpu < cpus->nr; cpu++) {
500 val = counter->counts->cpu[cpu].val;
501 ena = counter->counts->cpu[cpu].ena;
502 run = counter->counts->cpu[cpu].run;
503 if (run == 0 || ena == 0) {
504 fprintf(stderr, "CPU%*d%s%*s%s%-24s",
505 csv_output ? 0 : -4,
506 cpus->map[cpu], csv_sep,
507 csv_output ? 0 : 18,
508 "<not counted>", csv_sep,
509 event_name(counter));
510
511 fprintf(stderr, "\n");
512 continue;
513 }
514
515 if (nsec_counter(counter))
516 nsec_printout(cpu, counter, val);
517 else
518 abs_printout(cpu, counter, val);
519
520 if (!csv_output) {
521 print_noise(counter, 1.0);
522
523 if (run != ena) {
524 fprintf(stderr, " (scaled from %.2f%%)",
525 100.0 * run / ena);
526 }
527 }
528 fprintf(stderr, "\n");
529 }
530}
531
461static void print_stat(int argc, const char **argv) 532static void print_stat(int argc, const char **argv)
462{ 533{
463 int i, counter; 534 struct perf_evsel *counter;
535 int i;
464 536
465 fflush(stdout); 537 fflush(stdout);
466 538
467 fprintf(stderr, "\n"); 539 if (!csv_output) {
468 fprintf(stderr, " Performance counter stats for "); 540 fprintf(stderr, "\n");
469 if(target_pid == -1 && target_tid == -1) { 541 fprintf(stderr, " Performance counter stats for ");
470 fprintf(stderr, "\'%s", argv[0]); 542 if(target_pid == -1 && target_tid == -1) {
471 for (i = 1; i < argc; i++) 543 fprintf(stderr, "\'%s", argv[0]);
472 fprintf(stderr, " %s", argv[i]); 544 for (i = 1; i < argc; i++)
473 } else if (target_pid != -1) 545 fprintf(stderr, " %s", argv[i]);
474 fprintf(stderr, "process id \'%d", target_pid); 546 } else if (target_pid != -1)
475 else 547 fprintf(stderr, "process id \'%d", target_pid);
476 fprintf(stderr, "thread id \'%d", target_tid); 548 else
477 549 fprintf(stderr, "thread id \'%d", target_tid);
478 fprintf(stderr, "\'"); 550
479 if (run_count > 1) 551 fprintf(stderr, "\'");
480 fprintf(stderr, " (%d runs)", run_count); 552 if (run_count > 1)
481 fprintf(stderr, ":\n\n"); 553 fprintf(stderr, " (%d runs)", run_count);
554 fprintf(stderr, ":\n\n");
555 }
482 556
483 for (counter = 0; counter < nr_counters; counter++) 557 if (no_aggr) {
484 print_counter(counter); 558 list_for_each_entry(counter, &evsel_list, node)
559 print_counter(counter);
560 } else {
561 list_for_each_entry(counter, &evsel_list, node)
562 print_counter_aggr(counter);
563 }
485 564
486 fprintf(stderr, "\n"); 565 if (!csv_output) {
487 fprintf(stderr, " %18.9f seconds time elapsed", 566 fprintf(stderr, "\n");
488 avg_stats(&walltime_nsecs_stats)/1e9); 567 fprintf(stderr, " %18.9f seconds time elapsed",
489 if (run_count > 1) { 568 avg_stats(&walltime_nsecs_stats)/1e9);
490 fprintf(stderr, " ( +- %7.3f%% )", 569 if (run_count > 1) {
570 fprintf(stderr, " ( +- %7.3f%% )",
491 100*stddev_stats(&walltime_nsecs_stats) / 571 100*stddev_stats(&walltime_nsecs_stats) /
492 avg_stats(&walltime_nsecs_stats)); 572 avg_stats(&walltime_nsecs_stats));
573 }
574 fprintf(stderr, "\n\n");
493 } 575 }
494 fprintf(stderr, "\n\n");
495} 576}
496 577
497static volatile int signr = -1; 578static volatile int signr = -1;
@@ -521,6 +602,13 @@ static const char * const stat_usage[] = {
521 NULL 602 NULL
522}; 603};
523 604
605static int stat__set_big_num(const struct option *opt __used,
606 const char *s __used, int unset)
607{
608 big_num_opt = unset ? 0 : 1;
609 return 0;
610}
611
524static const struct option options[] = { 612static const struct option options[] = {
525 OPT_CALLBACK('e', "event", NULL, "event", 613 OPT_CALLBACK('e', "event", NULL, "event",
526 "event selector. use 'perf list' to list available events", 614 "event selector. use 'perf list' to list available events",
@@ -541,64 +629,95 @@ static const struct option options[] = {
541 "repeat command and print average + stddev (max: 100)"), 629 "repeat command and print average + stddev (max: 100)"),
542 OPT_BOOLEAN('n', "null", &null_run, 630 OPT_BOOLEAN('n', "null", &null_run,
543 "null run - dont start any counters"), 631 "null run - dont start any counters"),
544 OPT_BOOLEAN('B', "big-num", &big_num, 632 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
545 "print large numbers with thousands\' separators"), 633 "print large numbers with thousands\' separators",
634 stat__set_big_num),
546 OPT_STRING('C', "cpu", &cpu_list, "cpu", 635 OPT_STRING('C', "cpu", &cpu_list, "cpu",
547 "list of cpus to monitor in system-wide"), 636 "list of cpus to monitor in system-wide"),
637 OPT_BOOLEAN('A', "no-aggr", &no_aggr,
638 "disable CPU count aggregation"),
639 OPT_STRING('x', "field-separator", &csv_sep, "separator",
640 "print counts with custom separator"),
548 OPT_END() 641 OPT_END()
549}; 642};
550 643
551int cmd_stat(int argc, const char **argv, const char *prefix __used) 644int cmd_stat(int argc, const char **argv, const char *prefix __used)
552{ 645{
553 int status; 646 struct perf_evsel *pos;
554 int i,j; 647 int status = -ENOMEM;
555 648
556 setlocale(LC_ALL, ""); 649 setlocale(LC_ALL, "");
557 650
558 argc = parse_options(argc, argv, options, stat_usage, 651 argc = parse_options(argc, argv, options, stat_usage,
559 PARSE_OPT_STOP_AT_NON_OPTION); 652 PARSE_OPT_STOP_AT_NON_OPTION);
653
654 if (csv_sep)
655 csv_output = true;
656 else
657 csv_sep = DEFAULT_SEPARATOR;
658
659 /*
660 * let the spreadsheet do the pretty-printing
661 */
662 if (csv_output) {
663 /* User explicitely passed -B? */
664 if (big_num_opt == 1) {
665 fprintf(stderr, "-B option not supported with -x\n");
666 usage_with_options(stat_usage, options);
667 } else /* Nope, so disable big number formatting */
668 big_num = false;
669 } else if (big_num_opt == 0) /* User passed --no-big-num */
670 big_num = false;
671
560 if (!argc && target_pid == -1 && target_tid == -1) 672 if (!argc && target_pid == -1 && target_tid == -1)
561 usage_with_options(stat_usage, options); 673 usage_with_options(stat_usage, options);
562 if (run_count <= 0) 674 if (run_count <= 0)
563 usage_with_options(stat_usage, options); 675 usage_with_options(stat_usage, options);
564 676
677 /* no_aggr is for system-wide only */
678 if (no_aggr && !system_wide)
679 usage_with_options(stat_usage, options);
680
565 /* Set attrs and nr_counters if no event is selected and !null_run */ 681 /* Set attrs and nr_counters if no event is selected and !null_run */
566 if (!null_run && !nr_counters) { 682 if (!null_run && !nr_counters) {
567 memcpy(attrs, default_attrs, sizeof(default_attrs)); 683 size_t c;
684
568 nr_counters = ARRAY_SIZE(default_attrs); 685 nr_counters = ARRAY_SIZE(default_attrs);
686
687 for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
688 pos = perf_evsel__new(&default_attrs[c],
689 nr_counters);
690 if (pos == NULL)
691 goto out;
692 list_add(&pos->node, &evsel_list);
693 }
569 } 694 }
570 695
571 if (system_wide) 696 if (target_pid != -1)
572 nr_cpus = read_cpu_map(cpu_list); 697 target_tid = target_pid;
573 else
574 nr_cpus = 1;
575 698
576 if (nr_cpus < 1) 699 threads = thread_map__new(target_pid, target_tid);
700 if (threads == NULL) {
701 pr_err("Problems finding threads of monitor\n");
577 usage_with_options(stat_usage, options); 702 usage_with_options(stat_usage, options);
703 }
578 704
579 if (target_pid != -1) { 705 if (system_wide)
580 target_tid = target_pid; 706 cpus = cpu_map__new(cpu_list);
581 thread_num = find_all_tid(target_pid, &all_tids); 707 else
582 if (thread_num <= 0) { 708 cpus = cpu_map__dummy_new();
583 fprintf(stderr, "Can't find all threads of pid %d\n",
584 target_pid);
585 usage_with_options(stat_usage, options);
586 }
587 } else {
588 all_tids=malloc(sizeof(pid_t));
589 if (!all_tids)
590 return -ENOMEM;
591 709
592 all_tids[0] = target_tid; 710 if (cpus == NULL) {
593 thread_num = 1; 711 perror("failed to parse CPUs map");
712 usage_with_options(stat_usage, options);
713 return -1;
594 } 714 }
595 715
596 for (i = 0; i < MAX_NR_CPUS; i++) { 716 list_for_each_entry(pos, &evsel_list, node) {
597 for (j = 0; j < MAX_COUNTERS; j++) { 717 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
598 fd[i][j] = malloc(sizeof(int)*thread_num); 718 perf_evsel__alloc_counts(pos, cpus->nr) < 0 ||
599 if (!fd[i][j]) 719 perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
600 return -ENOMEM; 720 goto out_free_fd;
601 }
602 } 721 }
603 722
604 /* 723 /*
@@ -621,6 +740,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
621 740
622 if (status != -1) 741 if (status != -1)
623 print_stat(argc, argv); 742 print_stat(argc, argv);
624 743out_free_fd:
744 list_for_each_entry(pos, &evsel_list, node)
745 perf_evsel__free_stat_priv(pos);
746 perf_evsel_list__delete();
747out:
748 thread_map__delete(threads);
749 threads = NULL;
625 return status; 750 return status;
626} 751}
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 035b9fa063a9..5dcdba653d70 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -119,10 +119,16 @@ static int test__vmlinux_matches_kallsyms(void)
119 * end addresses too. 119 * end addresses too.
120 */ 120 */
121 for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { 121 for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
122 struct symbol *pair; 122 struct symbol *pair, *first_pair;
123 bool backwards = true;
123 124
124 sym = rb_entry(nd, struct symbol, rb_node); 125 sym = rb_entry(nd, struct symbol, rb_node);
125 pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); 126
127 if (sym->start == sym->end)
128 continue;
129
130 first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
131 pair = first_pair;
126 132
127 if (pair && pair->start == sym->start) { 133 if (pair && pair->start == sym->start) {
128next_pair: 134next_pair:
@@ -140,11 +146,13 @@ next_pair:
140 if (llabs(skew) < page_size) 146 if (llabs(skew) < page_size)
141 continue; 147 continue;
142 148
143 pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\n", 149 pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
144 sym->start, sym->name, sym->end, pair->end); 150 sym->start, sym->name, sym->end, pair->end);
145 } else { 151 } else {
146 struct rb_node *nnd = rb_prev(&pair->rb_node); 152 struct rb_node *nnd;
147 153detour:
154 nnd = backwards ? rb_prev(&pair->rb_node) :
155 rb_next(&pair->rb_node);
148 if (nnd) { 156 if (nnd) {
149 struct symbol *next = rb_entry(nnd, struct symbol, rb_node); 157 struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
150 158
@@ -153,11 +161,18 @@ next_pair:
153 goto next_pair; 161 goto next_pair;
154 } 162 }
155 } 163 }
156 pr_debug("%#Lx: diff name v: %s k: %s\n", 164
165 if (backwards) {
166 backwards = false;
167 pair = first_pair;
168 goto detour;
169 }
170
171 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
157 sym->start, sym->name, pair->name); 172 sym->start, sym->name, pair->name);
158 } 173 }
159 } else 174 } else
160 pr_debug("%#Lx: %s not on kallsyms\n", sym->start, sym->name); 175 pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name);
161 176
162 err = -1; 177 err = -1;
163 } 178 }
@@ -196,10 +211,10 @@ next_pair:
196 211
197 if (pair->start == pos->start) { 212 if (pair->start == pos->start) {
198 pair->priv = 1; 213 pair->priv = 1;
199 pr_info(" %Lx-%Lx %Lx %s in kallsyms as", 214 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
200 pos->start, pos->end, pos->pgoff, pos->dso->name); 215 pos->start, pos->end, pos->pgoff, pos->dso->name);
201 if (pos->pgoff != pair->pgoff || pos->end != pair->end) 216 if (pos->pgoff != pair->pgoff || pos->end != pair->end)
202 pr_info(": \n*%Lx-%Lx %Lx", 217 pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "",
203 pair->start, pair->end, pair->pgoff); 218 pair->start, pair->end, pair->pgoff);
204 pr_info(" %s\n", pair->dso->name); 219 pr_info(" %s\n", pair->dso->name);
205 pair->priv = 1; 220 pair->priv = 1;
@@ -219,6 +234,209 @@ out:
219 return err; 234 return err;
220} 235}
221 236
237#include "util/cpumap.h"
238#include "util/evsel.h"
239#include <sys/types.h>
240
241static int trace_event__id(const char *event_name)
242{
243 char *filename;
244 int err = -1, fd;
245
246 if (asprintf(&filename,
247 "/sys/kernel/debug/tracing/events/syscalls/%s/id",
248 event_name) < 0)
249 return -1;
250
251 fd = open(filename, O_RDONLY);
252 if (fd >= 0) {
253 char id[16];
254 if (read(fd, id, sizeof(id)) > 0)
255 err = atoi(id);
256 close(fd);
257 }
258
259 free(filename);
260 return err;
261}
262
263static int test__open_syscall_event(void)
264{
265 int err = -1, fd;
266 struct thread_map *threads;
267 struct perf_evsel *evsel;
268 struct perf_event_attr attr;
269 unsigned int nr_open_calls = 111, i;
270 int id = trace_event__id("sys_enter_open");
271
272 if (id < 0) {
273 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
274 return -1;
275 }
276
277 threads = thread_map__new(-1, getpid());
278 if (threads == NULL) {
279 pr_debug("thread_map__new\n");
280 return -1;
281 }
282
283 memset(&attr, 0, sizeof(attr));
284 attr.type = PERF_TYPE_TRACEPOINT;
285 attr.config = id;
286 evsel = perf_evsel__new(&attr, 0);
287 if (evsel == NULL) {
288 pr_debug("perf_evsel__new\n");
289 goto out_thread_map_delete;
290 }
291
292 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
293 pr_debug("failed to open counter: %s, "
294 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
295 strerror(errno));
296 goto out_evsel_delete;
297 }
298
299 for (i = 0; i < nr_open_calls; ++i) {
300 fd = open("/etc/passwd", O_RDONLY);
301 close(fd);
302 }
303
304 if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
305 pr_debug("perf_evsel__open_read_on_cpu\n");
306 goto out_close_fd;
307 }
308
309 if (evsel->counts->cpu[0].val != nr_open_calls) {
310 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
311 nr_open_calls, evsel->counts->cpu[0].val);
312 goto out_close_fd;
313 }
314
315 err = 0;
316out_close_fd:
317 perf_evsel__close_fd(evsel, 1, threads->nr);
318out_evsel_delete:
319 perf_evsel__delete(evsel);
320out_thread_map_delete:
321 thread_map__delete(threads);
322 return err;
323}
324
325#include <sched.h>
326
327static int test__open_syscall_event_on_all_cpus(void)
328{
329 int err = -1, fd, cpu;
330 struct thread_map *threads;
331 struct cpu_map *cpus;
332 struct perf_evsel *evsel;
333 struct perf_event_attr attr;
334 unsigned int nr_open_calls = 111, i;
335 cpu_set_t cpu_set;
336 int id = trace_event__id("sys_enter_open");
337
338 if (id < 0) {
339 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
340 return -1;
341 }
342
343 threads = thread_map__new(-1, getpid());
344 if (threads == NULL) {
345 pr_debug("thread_map__new\n");
346 return -1;
347 }
348
349 cpus = cpu_map__new(NULL);
350 if (threads == NULL) {
351 pr_debug("thread_map__new\n");
352 return -1;
353 }
354
355
356 CPU_ZERO(&cpu_set);
357
358 memset(&attr, 0, sizeof(attr));
359 attr.type = PERF_TYPE_TRACEPOINT;
360 attr.config = id;
361 evsel = perf_evsel__new(&attr, 0);
362 if (evsel == NULL) {
363 pr_debug("perf_evsel__new\n");
364 goto out_thread_map_delete;
365 }
366
367 if (perf_evsel__open(evsel, cpus, threads) < 0) {
368 pr_debug("failed to open counter: %s, "
369 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
370 strerror(errno));
371 goto out_evsel_delete;
372 }
373
374 for (cpu = 0; cpu < cpus->nr; ++cpu) {
375 unsigned int ncalls = nr_open_calls + cpu;
376 /*
377 * XXX eventually lift this restriction in a way that
378 * keeps perf building on older glibc installations
379 * without CPU_ALLOC. 1024 cpus in 2010 still seems
380 * a reasonable upper limit tho :-)
381 */
382 if (cpus->map[cpu] >= CPU_SETSIZE) {
383 pr_debug("Ignoring CPU %d\n", cpus->map[cpu]);
384 continue;
385 }
386
387 CPU_SET(cpus->map[cpu], &cpu_set);
388 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
389 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
390 cpus->map[cpu],
391 strerror(errno));
392 goto out_close_fd;
393 }
394 for (i = 0; i < ncalls; ++i) {
395 fd = open("/etc/passwd", O_RDONLY);
396 close(fd);
397 }
398 CPU_CLR(cpus->map[cpu], &cpu_set);
399 }
400
401 /*
402 * Here we need to explicitely preallocate the counts, as if
403 * we use the auto allocation it will allocate just for 1 cpu,
404 * as we start by cpu 0.
405 */
406 if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) {
407 pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
408 goto out_close_fd;
409 }
410
411 for (cpu = 0; cpu < cpus->nr; ++cpu) {
412 unsigned int expected;
413
414 if (cpus->map[cpu] >= CPU_SETSIZE)
415 continue;
416
417 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
418 pr_debug("perf_evsel__open_read_on_cpu\n");
419 goto out_close_fd;
420 }
421
422 expected = nr_open_calls + cpu;
423 if (evsel->counts->cpu[cpu].val != expected) {
424 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
425 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
426 goto out_close_fd;
427 }
428 }
429
430 err = 0;
431out_close_fd:
432 perf_evsel__close_fd(evsel, 1, threads->nr);
433out_evsel_delete:
434 perf_evsel__delete(evsel);
435out_thread_map_delete:
436 thread_map__delete(threads);
437 return err;
438}
439
222static struct test { 440static struct test {
223 const char *desc; 441 const char *desc;
224 int (*func)(void); 442 int (*func)(void);
@@ -228,6 +446,14 @@ static struct test {
228 .func = test__vmlinux_matches_kallsyms, 446 .func = test__vmlinux_matches_kallsyms,
229 }, 447 },
230 { 448 {
449 .desc = "detect open syscall event",
450 .func = test__open_syscall_event,
451 },
452 {
453 .desc = "detect open syscall event on all cpus",
454 .func = test__open_syscall_event_on_all_cpus,
455 },
456 {
231 .func = NULL, 457 .func = NULL,
232 }, 458 },
233}; 459};
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 9bcc38f0b706..746cf03cb05d 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -32,6 +32,10 @@
32#include "util/session.h" 32#include "util/session.h"
33#include "util/svghelper.h" 33#include "util/svghelper.h"
34 34
35#define SUPPORT_OLD_POWER_EVENTS 1
36#define PWR_EVENT_EXIT -1
37
38
35static char const *input_name = "perf.data"; 39static char const *input_name = "perf.data";
36static char const *output_name = "output.svg"; 40static char const *output_name = "output.svg";
37 41
@@ -272,19 +276,22 @@ static int cpus_cstate_state[MAX_CPUS];
272static u64 cpus_pstate_start_times[MAX_CPUS]; 276static u64 cpus_pstate_start_times[MAX_CPUS];
273static u64 cpus_pstate_state[MAX_CPUS]; 277static u64 cpus_pstate_state[MAX_CPUS];
274 278
275static int process_comm_event(event_t *event, struct perf_session *session __used) 279static int process_comm_event(event_t *event, struct sample_data *sample __used,
280 struct perf_session *session __used)
276{ 281{
277 pid_set_comm(event->comm.tid, event->comm.comm); 282 pid_set_comm(event->comm.tid, event->comm.comm);
278 return 0; 283 return 0;
279} 284}
280 285
281static int process_fork_event(event_t *event, struct perf_session *session __used) 286static int process_fork_event(event_t *event, struct sample_data *sample __used,
287 struct perf_session *session __used)
282{ 288{
283 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); 289 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
284 return 0; 290 return 0;
285} 291}
286 292
287static int process_exit_event(event_t *event, struct perf_session *session __used) 293static int process_exit_event(event_t *event, struct sample_data *sample __used,
294 struct perf_session *session __used)
288{ 295{
289 pid_exit(event->fork.pid, event->fork.time); 296 pid_exit(event->fork.pid, event->fork.time);
290 return 0; 297 return 0;
@@ -298,12 +305,21 @@ struct trace_entry {
298 int lock_depth; 305 int lock_depth;
299}; 306};
300 307
301struct power_entry { 308#ifdef SUPPORT_OLD_POWER_EVENTS
309static int use_old_power_events;
310struct power_entry_old {
302 struct trace_entry te; 311 struct trace_entry te;
303 u64 type; 312 u64 type;
304 u64 value; 313 u64 value;
305 u64 cpu_id; 314 u64 cpu_id;
306}; 315};
316#endif
317
318struct power_processor_entry {
319 struct trace_entry te;
320 u32 state;
321 u32 cpu_id;
322};
307 323
308#define TASK_COMM_LEN 16 324#define TASK_COMM_LEN 16
309struct wakeup_entry { 325struct wakeup_entry {
@@ -470,48 +486,65 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
470} 486}
471 487
472 488
473static int process_sample_event(event_t *event, struct perf_session *session) 489static int process_sample_event(event_t *event __used,
490 struct sample_data *sample,
491 struct perf_session *session)
474{ 492{
475 struct sample_data data;
476 struct trace_entry *te; 493 struct trace_entry *te;
477 494
478 memset(&data, 0, sizeof(data));
479
480 event__parse_sample(event, session->sample_type, &data);
481
482 if (session->sample_type & PERF_SAMPLE_TIME) { 495 if (session->sample_type & PERF_SAMPLE_TIME) {
483 if (!first_time || first_time > data.time) 496 if (!first_time || first_time > sample->time)
484 first_time = data.time; 497 first_time = sample->time;
485 if (last_time < data.time) 498 if (last_time < sample->time)
486 last_time = data.time; 499 last_time = sample->time;
487 } 500 }
488 501
489 te = (void *)data.raw_data; 502 te = (void *)sample->raw_data;
490 if (session->sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) { 503 if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) {
491 char *event_str; 504 char *event_str;
492 struct power_entry *pe; 505#ifdef SUPPORT_OLD_POWER_EVENTS
493 506 struct power_entry_old *peo;
494 pe = (void *)te; 507 peo = (void *)te;
495 508#endif
496 event_str = perf_header__find_event(te->type); 509 event_str = perf_header__find_event(te->type);
497 510
498 if (!event_str) 511 if (!event_str)
499 return 0; 512 return 0;
500 513
501 if (strcmp(event_str, "power:power_start") == 0) 514 if (strcmp(event_str, "power:cpu_idle") == 0) {
502 c_state_start(pe->cpu_id, data.time, pe->value); 515 struct power_processor_entry *ppe = (void *)te;
516 if (ppe->state == (u32)PWR_EVENT_EXIT)
517 c_state_end(ppe->cpu_id, sample->time);
518 else
519 c_state_start(ppe->cpu_id, sample->time,
520 ppe->state);
521 }
522 else if (strcmp(event_str, "power:cpu_frequency") == 0) {
523 struct power_processor_entry *ppe = (void *)te;
524 p_state_change(ppe->cpu_id, sample->time, ppe->state);
525 }
526
527 else if (strcmp(event_str, "sched:sched_wakeup") == 0)
528 sched_wakeup(sample->cpu, sample->time, sample->pid, te);
503 529
504 if (strcmp(event_str, "power:power_end") == 0) 530 else if (strcmp(event_str, "sched:sched_switch") == 0)
505 c_state_end(pe->cpu_id, data.time); 531 sched_switch(sample->cpu, sample->time, te);
506 532
507 if (strcmp(event_str, "power:power_frequency") == 0) 533#ifdef SUPPORT_OLD_POWER_EVENTS
508 p_state_change(pe->cpu_id, data.time, pe->value); 534 if (use_old_power_events) {
535 if (strcmp(event_str, "power:power_start") == 0)
536 c_state_start(peo->cpu_id, sample->time,
537 peo->value);
509 538
510 if (strcmp(event_str, "sched:sched_wakeup") == 0) 539 else if (strcmp(event_str, "power:power_end") == 0)
511 sched_wakeup(data.cpu, data.time, data.pid, te); 540 c_state_end(sample->cpu, sample->time);
512 541
513 if (strcmp(event_str, "sched:sched_switch") == 0) 542 else if (strcmp(event_str,
514 sched_switch(data.cpu, data.time, te); 543 "power:power_frequency") == 0)
544 p_state_change(peo->cpu_id, sample->time,
545 peo->value);
546 }
547#endif
515 } 548 }
516 return 0; 549 return 0;
517} 550}
@@ -937,7 +970,8 @@ static struct perf_event_ops event_ops = {
937 970
938static int __cmd_timechart(void) 971static int __cmd_timechart(void)
939{ 972{
940 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 973 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
974 0, false, &event_ops);
941 int ret = -EINVAL; 975 int ret = -EINVAL;
942 976
943 if (session == NULL) 977 if (session == NULL)
@@ -968,7 +1002,8 @@ static const char * const timechart_usage[] = {
968 NULL 1002 NULL
969}; 1003};
970 1004
971static const char *record_args[] = { 1005#ifdef SUPPORT_OLD_POWER_EVENTS
1006static const char * const record_old_args[] = {
972 "record", 1007 "record",
973 "-a", 1008 "-a",
974 "-R", 1009 "-R",
@@ -980,16 +1015,43 @@ static const char *record_args[] = {
980 "-e", "sched:sched_wakeup", 1015 "-e", "sched:sched_wakeup",
981 "-e", "sched:sched_switch", 1016 "-e", "sched:sched_switch",
982}; 1017};
1018#endif
1019
1020static const char * const record_new_args[] = {
1021 "record",
1022 "-a",
1023 "-R",
1024 "-f",
1025 "-c", "1",
1026 "-e", "power:cpu_frequency",
1027 "-e", "power:cpu_idle",
1028 "-e", "sched:sched_wakeup",
1029 "-e", "sched:sched_switch",
1030};
983 1031
984static int __cmd_record(int argc, const char **argv) 1032static int __cmd_record(int argc, const char **argv)
985{ 1033{
986 unsigned int rec_argc, i, j; 1034 unsigned int rec_argc, i, j;
987 const char **rec_argv; 1035 const char **rec_argv;
1036 const char * const *record_args = record_new_args;
1037 unsigned int record_elems = ARRAY_SIZE(record_new_args);
1038
1039#ifdef SUPPORT_OLD_POWER_EVENTS
1040 if (!is_valid_tracepoint("power:cpu_idle") &&
1041 is_valid_tracepoint("power:power_start")) {
1042 use_old_power_events = 1;
1043 record_args = record_old_args;
1044 record_elems = ARRAY_SIZE(record_old_args);
1045 }
1046#endif
988 1047
989 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 1048 rec_argc = record_elems + argc - 1;
990 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1049 rec_argv = calloc(rec_argc + 1, sizeof(char *));
991 1050
992 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1051 if (rec_argv == NULL)
1052 return -ENOMEM;
1053
1054 for (i = 0; i < record_elems; i++)
993 rec_argv[i] = strdup(record_args[i]); 1055 rec_argv[i] = strdup(record_args[i]);
994 1056
995 for (j = 1; j < (unsigned int)argc; j++, i++) 1057 for (j = 1; j < (unsigned int)argc; j++, i++)
@@ -1018,6 +1080,8 @@ static const struct option options[] = {
1018 OPT_CALLBACK('p', "process", NULL, "process", 1080 OPT_CALLBACK('p', "process", NULL, "process",
1019 "process selector. Pass a pid or process name.", 1081 "process selector. Pass a pid or process name.",
1020 parse_process), 1082 parse_process),
1083 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1084 "Look for files with symbols relative to this directory"),
1021 OPT_END() 1085 OPT_END()
1022}; 1086};
1023 1087
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index b513e40974f4..b6998e055767 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -21,6 +21,7 @@
21#include "perf.h" 21#include "perf.h"
22 22
23#include "util/color.h" 23#include "util/color.h"
24#include "util/evsel.h"
24#include "util/session.h" 25#include "util/session.h"
25#include "util/symbol.h" 26#include "util/symbol.h"
26#include "util/thread.h" 27#include "util/thread.h"
@@ -29,6 +30,7 @@
29#include "util/parse-options.h" 30#include "util/parse-options.h"
30#include "util/parse-events.h" 31#include "util/parse-events.h"
31#include "util/cpumap.h" 32#include "util/cpumap.h"
33#include "util/xyarray.h"
32 34
33#include "util/debug.h" 35#include "util/debug.h"
34 36
@@ -38,6 +40,7 @@
38#include <stdio.h> 40#include <stdio.h>
39#include <termios.h> 41#include <termios.h>
40#include <unistd.h> 42#include <unistd.h>
43#include <inttypes.h>
41 44
42#include <errno.h> 45#include <errno.h>
43#include <time.h> 46#include <time.h>
@@ -55,7 +58,7 @@
55#include <linux/unistd.h> 58#include <linux/unistd.h>
56#include <linux/types.h> 59#include <linux/types.h>
57 60
58static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; 61#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
59 62
60static bool system_wide = false; 63static bool system_wide = false;
61 64
@@ -66,11 +69,9 @@ static int print_entries;
66 69
67static int target_pid = -1; 70static int target_pid = -1;
68static int target_tid = -1; 71static int target_tid = -1;
69static pid_t *all_tids = NULL; 72static struct thread_map *threads;
70static int thread_num = 0;
71static bool inherit = false; 73static bool inherit = false;
72static int profile_cpu = -1; 74static struct cpu_map *cpus;
73static int nr_cpus = 0;
74static int realtime_prio = 0; 75static int realtime_prio = 0;
75static bool group = false; 76static bool group = false;
76static unsigned int page_size; 77static unsigned int page_size;
@@ -101,6 +102,7 @@ struct sym_entry *sym_filter_entry = NULL;
101struct sym_entry *sym_filter_entry_sched = NULL; 102struct sym_entry *sym_filter_entry_sched = NULL;
102static int sym_pcnt_filter = 5; 103static int sym_pcnt_filter = 5;
103static int sym_counter = 0; 104static int sym_counter = 0;
105static struct perf_evsel *sym_evsel = NULL;
104static int display_weighted = -1; 106static int display_weighted = -1;
105static const char *cpu_list; 107static const char *cpu_list;
106 108
@@ -213,7 +215,7 @@ static int parse_source(struct sym_entry *syme)
213 len = sym->end - sym->start; 215 len = sym->end - sym->start;
214 216
215 sprintf(command, 217 sprintf(command,
216 "objdump --start-address=%#0*Lx --stop-address=%#0*Lx -dS %s", 218 "objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s",
217 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start), 219 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start),
218 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path); 220 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path);
219 221
@@ -307,7 +309,7 @@ static void lookup_sym_source(struct sym_entry *syme)
307 struct source_line *line; 309 struct source_line *line;
308 char pattern[PATTERN_LEN + 1]; 310 char pattern[PATTERN_LEN + 1];
309 311
310 sprintf(pattern, "%0*Lx <", BITS_PER_LONG / 4, 312 sprintf(pattern, "%0*" PRIx64 " <", BITS_PER_LONG / 4,
311 map__rip_2objdump(syme->map, symbol->start)); 313 map__rip_2objdump(syme->map, symbol->start));
312 314
313 pthread_mutex_lock(&syme->src->lock); 315 pthread_mutex_lock(&syme->src->lock);
@@ -354,7 +356,7 @@ static void show_details(struct sym_entry *syme)
354 return; 356 return;
355 357
356 symbol = sym_entry__symbol(syme); 358 symbol = sym_entry__symbol(syme);
357 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name); 359 printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name);
358 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 360 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
359 361
360 pthread_mutex_lock(&syme->src->lock); 362 pthread_mutex_lock(&syme->src->lock);
@@ -461,7 +463,8 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
461static void print_sym_table(void) 463static void print_sym_table(void)
462{ 464{
463 int printed = 0, j; 465 int printed = 0, j;
464 int counter, snap = !display_weighted ? sym_counter : 0; 466 struct perf_evsel *counter;
467 int snap = !display_weighted ? sym_counter : 0;
465 float samples_per_sec = samples/delay_secs; 468 float samples_per_sec = samples/delay_secs;
466 float ksamples_per_sec = kernel_samples/delay_secs; 469 float ksamples_per_sec = kernel_samples/delay_secs;
467 float us_samples_per_sec = (us_samples)/delay_secs; 470 float us_samples_per_sec = (us_samples)/delay_secs;
@@ -533,7 +536,9 @@ static void print_sym_table(void)
533 } 536 }
534 537
535 if (nr_counters == 1 || !display_weighted) { 538 if (nr_counters == 1 || !display_weighted) {
536 printf("%Ld", (u64)attrs[0].sample_period); 539 struct perf_evsel *first;
540 first = list_entry(evsel_list.next, struct perf_evsel, node);
541 printf("%" PRIu64, (uint64_t)first->attr.sample_period);
537 if (freq) 542 if (freq)
538 printf("Hz "); 543 printf("Hz ");
539 else 544 else
@@ -541,9 +546,9 @@ static void print_sym_table(void)
541 } 546 }
542 547
543 if (!display_weighted) 548 if (!display_weighted)
544 printf("%s", event_name(sym_counter)); 549 printf("%s", event_name(sym_evsel));
545 else for (counter = 0; counter < nr_counters; counter++) { 550 else list_for_each_entry(counter, &evsel_list, node) {
546 if (counter) 551 if (counter->idx)
547 printf("/"); 552 printf("/");
548 553
549 printf("%s", event_name(counter)); 554 printf("%s", event_name(counter));
@@ -558,13 +563,13 @@ static void print_sym_table(void)
558 else 563 else
559 printf(" (all"); 564 printf(" (all");
560 565
561 if (profile_cpu != -1) 566 if (cpu_list)
562 printf(", cpu: %d)\n", profile_cpu); 567 printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
563 else { 568 else {
564 if (target_tid != -1) 569 if (target_tid != -1)
565 printf(")\n"); 570 printf(")\n");
566 else 571 else
567 printf(", %d CPUs)\n", nr_cpus); 572 printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
568 } 573 }
569 574
570 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 575 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
@@ -636,7 +641,7 @@ static void print_sym_table(void)
636 641
637 percent_color_fprintf(stdout, "%4.1f%%", pcnt); 642 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
638 if (verbose) 643 if (verbose)
639 printf(" %016llx", sym->start); 644 printf(" %016" PRIx64, sym->start);
640 printf(" %-*.*s", sym_width, sym_width, sym->name); 645 printf(" %-*.*s", sym_width, sym_width, sym->name);
641 printf(" %-*.*s\n", dso_width, dso_width, 646 printf(" %-*.*s\n", dso_width, dso_width,
642 dso_width >= syme->map->dso->long_name_len ? 647 dso_width >= syme->map->dso->long_name_len ?
@@ -740,7 +745,7 @@ static void print_mapped_keys(void)
740 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); 745 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
741 746
742 if (nr_counters > 1) 747 if (nr_counters > 1)
743 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter)); 748 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel));
744 749
745 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 750 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
746 751
@@ -827,19 +832,23 @@ static void handle_keypress(struct perf_session *session, int c)
827 break; 832 break;
828 case 'E': 833 case 'E':
829 if (nr_counters > 1) { 834 if (nr_counters > 1) {
830 int i;
831
832 fprintf(stderr, "\nAvailable events:"); 835 fprintf(stderr, "\nAvailable events:");
833 for (i = 0; i < nr_counters; i++) 836
834 fprintf(stderr, "\n\t%d %s", i, event_name(i)); 837 list_for_each_entry(sym_evsel, &evsel_list, node)
838 fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
835 839
836 prompt_integer(&sym_counter, "Enter details event counter"); 840 prompt_integer(&sym_counter, "Enter details event counter");
837 841
838 if (sym_counter >= nr_counters) { 842 if (sym_counter >= nr_counters) {
839 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(0)); 843 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
840 sym_counter = 0; 844 sym_counter = 0;
845 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
841 sleep(1); 846 sleep(1);
847 break;
842 } 848 }
849 list_for_each_entry(sym_evsel, &evsel_list, node)
850 if (sym_evsel->idx == sym_counter)
851 break;
843 } else sym_counter = 0; 852 } else sym_counter = 0;
844 break; 853 break;
845 case 'f': 854 case 'f':
@@ -978,12 +987,13 @@ static int symbol_filter(struct map *map, struct symbol *sym)
978} 987}
979 988
980static void event__process_sample(const event_t *self, 989static void event__process_sample(const event_t *self,
981 struct perf_session *session, int counter) 990 struct sample_data *sample,
991 struct perf_session *session,
992 struct perf_evsel *evsel)
982{ 993{
983 u64 ip = self->ip.ip; 994 u64 ip = self->ip.ip;
984 struct sym_entry *syme; 995 struct sym_entry *syme;
985 struct addr_location al; 996 struct addr_location al;
986 struct sample_data data;
987 struct machine *machine; 997 struct machine *machine;
988 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 998 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
989 999
@@ -1026,7 +1036,7 @@ static void event__process_sample(const event_t *self,
1026 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) 1036 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
1027 exact_samples++; 1037 exact_samples++;
1028 1038
1029 if (event__preprocess_sample(self, session, &al, &data, 1039 if (event__preprocess_sample(self, session, &al, sample,
1030 symbol_filter) < 0 || 1040 symbol_filter) < 0 ||
1031 al.filtered) 1041 al.filtered)
1032 return; 1042 return;
@@ -1072,9 +1082,9 @@ static void event__process_sample(const event_t *self,
1072 1082
1073 syme = symbol__priv(al.sym); 1083 syme = symbol__priv(al.sym);
1074 if (!syme->skip) { 1084 if (!syme->skip) {
1075 syme->count[counter]++; 1085 syme->count[evsel->idx]++;
1076 syme->origin = origin; 1086 syme->origin = origin;
1077 record_precise_ip(syme, counter, ip); 1087 record_precise_ip(syme, evsel->idx, ip);
1078 pthread_mutex_lock(&active_symbols_lock); 1088 pthread_mutex_lock(&active_symbols_lock);
1079 if (list_empty(&syme->node) || !syme->node.next) 1089 if (list_empty(&syme->node) || !syme->node.next)
1080 __list_insert_active_sym(syme); 1090 __list_insert_active_sym(syme);
@@ -1083,12 +1093,24 @@ static void event__process_sample(const event_t *self,
1083} 1093}
1084 1094
1085struct mmap_data { 1095struct mmap_data {
1086 int counter;
1087 void *base; 1096 void *base;
1088 int mask; 1097 int mask;
1089 unsigned int prev; 1098 unsigned int prev;
1090}; 1099};
1091 1100
1101static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel,
1102 int ncpus, int nthreads)
1103{
1104 evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data));
1105 return evsel->priv != NULL ? 0 : -ENOMEM;
1106}
1107
1108static void perf_evsel__free_mmap(struct perf_evsel *evsel)
1109{
1110 xyarray__delete(evsel->priv);
1111 evsel->priv = NULL;
1112}
1113
1092static unsigned int mmap_read_head(struct mmap_data *md) 1114static unsigned int mmap_read_head(struct mmap_data *md)
1093{ 1115{
1094 struct perf_event_mmap_page *pc = md->base; 1116 struct perf_event_mmap_page *pc = md->base;
@@ -1101,11 +1123,15 @@ static unsigned int mmap_read_head(struct mmap_data *md)
1101} 1123}
1102 1124
1103static void perf_session__mmap_read_counter(struct perf_session *self, 1125static void perf_session__mmap_read_counter(struct perf_session *self,
1104 struct mmap_data *md) 1126 struct perf_evsel *evsel,
1127 int cpu, int thread_idx)
1105{ 1128{
1129 struct xyarray *mmap_array = evsel->priv;
1130 struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx);
1106 unsigned int head = mmap_read_head(md); 1131 unsigned int head = mmap_read_head(md);
1107 unsigned int old = md->prev; 1132 unsigned int old = md->prev;
1108 unsigned char *data = md->base + page_size; 1133 unsigned char *data = md->base + page_size;
1134 struct sample_data sample;
1109 int diff; 1135 int diff;
1110 1136
1111 /* 1137 /*
@@ -1153,10 +1179,11 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1153 event = &event_copy; 1179 event = &event_copy;
1154 } 1180 }
1155 1181
1182 event__parse_sample(event, self, &sample);
1156 if (event->header.type == PERF_RECORD_SAMPLE) 1183 if (event->header.type == PERF_RECORD_SAMPLE)
1157 event__process_sample(event, self, md->counter); 1184 event__process_sample(event, &sample, self, evsel);
1158 else 1185 else
1159 event__process(event, self); 1186 event__process(event, &sample, self);
1160 old += size; 1187 old += size;
1161 } 1188 }
1162 1189
@@ -1164,37 +1191,39 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1164} 1191}
1165 1192
1166static struct pollfd *event_array; 1193static struct pollfd *event_array;
1167static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
1168 1194
1169static void perf_session__mmap_read(struct perf_session *self) 1195static void perf_session__mmap_read(struct perf_session *self)
1170{ 1196{
1171 int i, counter, thread_index; 1197 struct perf_evsel *counter;
1198 int i, thread_index;
1172 1199
1173 for (i = 0; i < nr_cpus; i++) { 1200 for (i = 0; i < cpus->nr; i++) {
1174 for (counter = 0; counter < nr_counters; counter++) 1201 list_for_each_entry(counter, &evsel_list, node) {
1175 for (thread_index = 0; 1202 for (thread_index = 0;
1176 thread_index < thread_num; 1203 thread_index < threads->nr;
1177 thread_index++) { 1204 thread_index++) {
1178 perf_session__mmap_read_counter(self, 1205 perf_session__mmap_read_counter(self,
1179 &mmap_array[i][counter][thread_index]); 1206 counter, i, thread_index);
1180 } 1207 }
1208 }
1181 } 1209 }
1182} 1210}
1183 1211
1184int nr_poll; 1212int nr_poll;
1185int group_fd; 1213int group_fd;
1186 1214
1187static void start_counter(int i, int counter) 1215static void start_counter(int i, struct perf_evsel *evsel)
1188{ 1216{
1217 struct xyarray *mmap_array = evsel->priv;
1218 struct mmap_data *mm;
1189 struct perf_event_attr *attr; 1219 struct perf_event_attr *attr;
1190 int cpu; 1220 int cpu = -1;
1191 int thread_index; 1221 int thread_index;
1192 1222
1193 cpu = profile_cpu; 1223 if (target_tid == -1)
1194 if (target_tid == -1 && profile_cpu == -1) 1224 cpu = cpus->map[i];
1195 cpu = cpumap[i];
1196 1225
1197 attr = attrs + counter; 1226 attr = &evsel->attr;
1198 1227
1199 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1228 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1200 1229
@@ -1207,16 +1236,18 @@ static void start_counter(int i, int counter)
1207 attr->inherit = (cpu < 0) && inherit; 1236 attr->inherit = (cpu < 0) && inherit;
1208 attr->mmap = 1; 1237 attr->mmap = 1;
1209 1238
1210 for (thread_index = 0; thread_index < thread_num; thread_index++) { 1239 for (thread_index = 0; thread_index < threads->nr; thread_index++) {
1211try_again: 1240try_again:
1212 fd[i][counter][thread_index] = sys_perf_event_open(attr, 1241 FD(evsel, i, thread_index) = sys_perf_event_open(attr,
1213 all_tids[thread_index], cpu, group_fd, 0); 1242 threads->map[thread_index], cpu, group_fd, 0);
1214 1243
1215 if (fd[i][counter][thread_index] < 0) { 1244 if (FD(evsel, i, thread_index) < 0) {
1216 int err = errno; 1245 int err = errno;
1217 1246
1218 if (err == EPERM || err == EACCES) 1247 if (err == EPERM || err == EACCES)
1219 die("No permission - are you root?\n"); 1248 die("Permission error - are you root?\n"
1249 "\t Consider tweaking"
1250 " /proc/sys/kernel/perf_event_paranoid.\n");
1220 /* 1251 /*
1221 * If it's cycles then fall back to hrtimer 1252 * If it's cycles then fall back to hrtimer
1222 * based cpu-clock-tick sw counter, which 1253 * based cpu-clock-tick sw counter, which
@@ -1233,30 +1264,30 @@ try_again:
1233 goto try_again; 1264 goto try_again;
1234 } 1265 }
1235 printf("\n"); 1266 printf("\n");
1236 error("perfcounter syscall returned with %d (%s)\n", 1267 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
1237 fd[i][counter][thread_index], strerror(err)); 1268 FD(evsel, i, thread_index), strerror(err));
1238 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 1269 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
1239 exit(-1); 1270 exit(-1);
1240 } 1271 }
1241 assert(fd[i][counter][thread_index] >= 0); 1272 assert(FD(evsel, i, thread_index) >= 0);
1242 fcntl(fd[i][counter][thread_index], F_SETFL, O_NONBLOCK); 1273 fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
1243 1274
1244 /* 1275 /*
1245 * First counter acts as the group leader: 1276 * First counter acts as the group leader:
1246 */ 1277 */
1247 if (group && group_fd == -1) 1278 if (group && group_fd == -1)
1248 group_fd = fd[i][counter][thread_index]; 1279 group_fd = FD(evsel, i, thread_index);
1249 1280
1250 event_array[nr_poll].fd = fd[i][counter][thread_index]; 1281 event_array[nr_poll].fd = FD(evsel, i, thread_index);
1251 event_array[nr_poll].events = POLLIN; 1282 event_array[nr_poll].events = POLLIN;
1252 nr_poll++; 1283 nr_poll++;
1253 1284
1254 mmap_array[i][counter][thread_index].counter = counter; 1285 mm = xyarray__entry(mmap_array, i, thread_index);
1255 mmap_array[i][counter][thread_index].prev = 0; 1286 mm->prev = 0;
1256 mmap_array[i][counter][thread_index].mask = mmap_pages*page_size - 1; 1287 mm->mask = mmap_pages*page_size - 1;
1257 mmap_array[i][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size, 1288 mm->base = mmap(NULL, (mmap_pages+1)*page_size,
1258 PROT_READ, MAP_SHARED, fd[i][counter][thread_index], 0); 1289 PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
1259 if (mmap_array[i][counter][thread_index].base == MAP_FAILED) 1290 if (mm->base == MAP_FAILED)
1260 die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 1291 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1261 } 1292 }
1262} 1293}
@@ -1264,13 +1295,13 @@ try_again:
1264static int __cmd_top(void) 1295static int __cmd_top(void)
1265{ 1296{
1266 pthread_t thread; 1297 pthread_t thread;
1267 int i, counter; 1298 struct perf_evsel *counter;
1268 int ret; 1299 int i, ret;
1269 /* 1300 /*
1270 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1301 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1271 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1302 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
1272 */ 1303 */
1273 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false); 1304 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
1274 if (session == NULL) 1305 if (session == NULL)
1275 return -ENOMEM; 1306 return -ENOMEM;
1276 1307
@@ -1279,9 +1310,9 @@ static int __cmd_top(void)
1279 else 1310 else
1280 event__synthesize_threads(event__process, session); 1311 event__synthesize_threads(event__process, session);
1281 1312
1282 for (i = 0; i < nr_cpus; i++) { 1313 for (i = 0; i < cpus->nr; i++) {
1283 group_fd = -1; 1314 group_fd = -1;
1284 for (counter = 0; counter < nr_counters; counter++) 1315 list_for_each_entry(counter, &evsel_list, node)
1285 start_counter(i, counter); 1316 start_counter(i, counter);
1286 } 1317 }
1287 1318
@@ -1370,8 +1401,8 @@ static const struct option options[] = {
1370 1401
1371int cmd_top(int argc, const char **argv, const char *prefix __used) 1402int cmd_top(int argc, const char **argv, const char *prefix __used)
1372{ 1403{
1373 int counter; 1404 struct perf_evsel *pos;
1374 int i,j; 1405 int status = -ENOMEM;
1375 1406
1376 page_size = sysconf(_SC_PAGE_SIZE); 1407 page_size = sysconf(_SC_PAGE_SIZE);
1377 1408
@@ -1379,34 +1410,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1379 if (argc) 1410 if (argc)
1380 usage_with_options(top_usage, options); 1411 usage_with_options(top_usage, options);
1381 1412
1382 if (target_pid != -1) { 1413 if (target_pid != -1)
1383 target_tid = target_pid; 1414 target_tid = target_pid;
1384 thread_num = find_all_tid(target_pid, &all_tids);
1385 if (thread_num <= 0) {
1386 fprintf(stderr, "Can't find all threads of pid %d\n",
1387 target_pid);
1388 usage_with_options(top_usage, options);
1389 }
1390 } else {
1391 all_tids=malloc(sizeof(pid_t));
1392 if (!all_tids)
1393 return -ENOMEM;
1394 1415
1395 all_tids[0] = target_tid; 1416 threads = thread_map__new(target_pid, target_tid);
1396 thread_num = 1; 1417 if (threads == NULL) {
1418 pr_err("Problems finding threads of monitor\n");
1419 usage_with_options(top_usage, options);
1397 } 1420 }
1398 1421
1399 for (i = 0; i < MAX_NR_CPUS; i++) { 1422 event_array = malloc((sizeof(struct pollfd) *
1400 for (j = 0; j < MAX_COUNTERS; j++) { 1423 MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
1401 fd[i][j] = malloc(sizeof(int)*thread_num);
1402 mmap_array[i][j] = zalloc(
1403 sizeof(struct mmap_data)*thread_num);
1404 if (!fd[i][j] || !mmap_array[i][j])
1405 return -ENOMEM;
1406 }
1407 }
1408 event_array = malloc(
1409 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
1410 if (!event_array) 1424 if (!event_array)
1411 return -ENOMEM; 1425 return -ENOMEM;
1412 1426
@@ -1417,15 +1431,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1417 cpu_list = NULL; 1431 cpu_list = NULL;
1418 } 1432 }
1419 1433
1420 if (!nr_counters) 1434 if (!nr_counters && perf_evsel_list__create_default() < 0) {
1421 nr_counters = 1; 1435 pr_err("Not enough memory for event selector list\n");
1422 1436 return -ENOMEM;
1423 symbol_conf.priv_size = (sizeof(struct sym_entry) + 1437 }
1424 (nr_counters + 1) * sizeof(unsigned long));
1425
1426 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1427 if (symbol__init() < 0)
1428 return -1;
1429 1438
1430 if (delay_secs < 1) 1439 if (delay_secs < 1)
1431 delay_secs = 1; 1440 delay_secs = 1;
@@ -1442,23 +1451,35 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1442 exit(EXIT_FAILURE); 1451 exit(EXIT_FAILURE);
1443 } 1452 }
1444 1453
1445 /* 1454 if (target_tid != -1)
1446 * Fill in the ones not specifically initialized via -c: 1455 cpus = cpu_map__dummy_new();
1447 */ 1456 else
1448 for (counter = 0; counter < nr_counters; counter++) { 1457 cpus = cpu_map__new(cpu_list);
1449 if (attrs[counter].sample_period) 1458
1459 if (cpus == NULL)
1460 usage_with_options(top_usage, options);
1461
1462 list_for_each_entry(pos, &evsel_list, node) {
1463 if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
1464 perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
1465 goto out_free_fd;
1466 /*
1467 * Fill in the ones not specifically initialized via -c:
1468 */
1469 if (pos->attr.sample_period)
1450 continue; 1470 continue;
1451 1471
1452 attrs[counter].sample_period = default_interval; 1472 pos->attr.sample_period = default_interval;
1453 } 1473 }
1454 1474
1455 if (target_tid != -1) 1475 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
1456 nr_cpus = 1;
1457 else
1458 nr_cpus = read_cpu_map(cpu_list);
1459 1476
1460 if (nr_cpus < 1) 1477 symbol_conf.priv_size = (sizeof(struct sym_entry) +
1461 usage_with_options(top_usage, options); 1478 (nr_counters + 1) * sizeof(unsigned long));
1479
1480 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1481 if (symbol__init() < 0)
1482 return -1;
1462 1483
1463 get_term_dimensions(&winsize); 1484 get_term_dimensions(&winsize);
1464 if (print_entries == 0) { 1485 if (print_entries == 0) {
@@ -1466,5 +1487,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1466 signal(SIGWINCH, sig_winch_handler); 1487 signal(SIGWINCH, sig_winch_handler);
1467 } 1488 }
1468 1489
1469 return __cmd_top(); 1490 status = __cmd_top();
1491out_free_fd:
1492 list_for_each_entry(pos, &evsel_list, node)
1493 perf_evsel__free_mmap(pos);
1494 perf_evsel_list__delete();
1495
1496 return status;
1470} 1497}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 921245b28583..c7798c7f24ed 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -27,7 +27,7 @@ extern int cmd_report(int argc, const char **argv, const char *prefix);
27extern int cmd_stat(int argc, const char **argv, const char *prefix); 27extern int cmd_stat(int argc, const char **argv, const char *prefix);
28extern int cmd_timechart(int argc, const char **argv, const char *prefix); 28extern int cmd_timechart(int argc, const char **argv, const char *prefix);
29extern int cmd_top(int argc, const char **argv, const char *prefix); 29extern int cmd_top(int argc, const char **argv, const char *prefix);
30extern int cmd_trace(int argc, const char **argv, const char *prefix); 30extern int cmd_script(int argc, const char **argv, const char *prefix);
31extern int cmd_version(int argc, const char **argv, const char *prefix); 31extern int cmd_version(int argc, const char **argv, const char *prefix);
32extern int cmd_probe(int argc, const char **argv, const char *prefix); 32extern int cmd_probe(int argc, const char **argv, const char *prefix);
33extern int cmd_kmem(int argc, const char **argv, const char *prefix); 33extern int cmd_kmem(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 949d77fc0b97..16b5088cf8f4 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -16,7 +16,7 @@ perf-report mainporcelain common
16perf-stat mainporcelain common 16perf-stat mainporcelain common
17perf-timechart mainporcelain common 17perf-timechart mainporcelain common
18perf-top mainporcelain common 18perf-top mainporcelain common
19perf-trace mainporcelain common 19perf-script mainporcelain common
20perf-probe mainporcelain common 20perf-probe mainporcelain common
21perf-kmem mainporcelain common 21perf-kmem mainporcelain common
22perf-lock mainporcelain common 22perf-lock mainporcelain common
diff --git a/tools/perf/feature-tests.mak b/tools/perf/feature-tests.mak
index b253db634f04..b041ca67a2cb 100644
--- a/tools/perf/feature-tests.mak
+++ b/tools/perf/feature-tests.mak
@@ -9,8 +9,8 @@ endef
9ifndef NO_DWARF 9ifndef NO_DWARF
10define SOURCE_DWARF 10define SOURCE_DWARF
11#include <dwarf.h> 11#include <dwarf.h>
12#include <libdw.h> 12#include <elfutils/libdw.h>
13#include <version.h> 13#include <elfutils/version.h>
14#ifndef _ELFUTILS_PREREQ 14#ifndef _ELFUTILS_PREREQ
15#error 15#error
16#endif 16#endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index cdd6c03f1e14..595d0f4a7103 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -323,7 +323,7 @@ static void handle_internal_command(int argc, const char **argv)
323 { "top", cmd_top, 0 }, 323 { "top", cmd_top, 0 },
324 { "annotate", cmd_annotate, 0 }, 324 { "annotate", cmd_annotate, 0 },
325 { "version", cmd_version, 0 }, 325 { "version", cmd_version, 0 },
326 { "trace", cmd_trace, 0 }, 326 { "script", cmd_script, 0 },
327 { "sched", cmd_sched, 0 }, 327 { "sched", cmd_sched, 0 },
328 { "probe", cmd_probe, 0 }, 328 { "probe", cmd_probe, 0 },
329 { "kmem", cmd_kmem, 0 }, 329 { "kmem", cmd_kmem, 0 },
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
index 01a64ad693f2..790ceba6ad3f 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
@@ -8,7 +8,7 @@
8 8
9#line 1 "Context.xs" 9#line 1 "Context.xs"
10/* 10/*
11 * Context.xs. XS interfaces for perf trace. 11 * Context.xs. XS interfaces for perf script.
12 * 12 *
13 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 13 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
14 * 14 *
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
index 549cf0467d30..c1e2ed1ed34e 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
@@ -1,5 +1,5 @@
1/* 1/*
2 * Context.xs. XS interfaces for perf trace. 2 * Context.xs. XS interfaces for perf script.
3 * 3 *
4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5 * 5 *
@@ -23,7 +23,7 @@
23#include "perl.h" 23#include "perl.h"
24#include "XSUB.h" 24#include "XSUB.h"
25#include "../../../perf.h" 25#include "../../../perf.h"
26#include "../../../util/trace-event.h" 26#include "../../../util/script-event.h"
27 27
28MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context 28MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context
29PROTOTYPES: ENABLE 29PROTOTYPES: ENABLE
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/README b/tools/perf/scripts/perl/Perf-Trace-Util/README
index 9a9707630791..2f0c7f3043ee 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/README
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/README
@@ -1,7 +1,7 @@
1Perf-Trace-Util version 0.01 1Perf-Trace-Util version 0.01
2============================ 2============================
3 3
4This module contains utility functions for use with perf trace. 4This module contains utility functions for use with perf script.
5 5
6Core.pm and Util.pm are pure Perl modules; Core.pm contains routines 6Core.pm and Util.pm are pure Perl modules; Core.pm contains routines
7that the core perf support for Perl calls on and should always be 7that the core perf support for Perl calls on and should always be
@@ -33,7 +33,7 @@ After you do that:
33 33
34INSTALLATION 34INSTALLATION
35 35
36Building perf with perf trace Perl scripting should install this 36Building perf with perf script Perl scripting should install this
37module in the right place. 37module in the right place.
38 38
39You should make sure libperl and ExtUtils/Embed.pm are installed first 39You should make sure libperl and ExtUtils/Embed.pm are installed first
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
index 6c7f3659cb17..4e2f6039ac92 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
@@ -34,7 +34,7 @@ Perf::Trace::Context - Perl extension for accessing functions in perf.
34 34
35=head1 SEE ALSO 35=head1 SEE ALSO
36 36
37Perf (trace) documentation 37Perf (script) documentation
38 38
39=head1 AUTHOR 39=head1 AUTHOR
40 40
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
index 9df376a9f629..9158458d3eeb 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
@@ -163,7 +163,7 @@ sub dump_symbolic_fields
163__END__ 163__END__
164=head1 NAME 164=head1 NAME
165 165
166Perf::Trace::Core - Perl extension for perf trace 166Perf::Trace::Core - Perl extension for perf script
167 167
168=head1 SYNOPSIS 168=head1 SYNOPSIS
169 169
@@ -171,7 +171,7 @@ Perf::Trace::Core - Perl extension for perf trace
171 171
172=head1 SEE ALSO 172=head1 SEE ALSO
173 173
174Perf (trace) documentation 174Perf (script) documentation
175 175
176=head1 AUTHOR 176=head1 AUTHOR
177 177
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
index d94b40c8ac85..053500114625 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
@@ -65,7 +65,7 @@ sub clear_term
65__END__ 65__END__
66=head1 NAME 66=head1 NAME
67 67
68Perf::Trace::Util - Perl extension for perf trace 68Perf::Trace::Util - Perl extension for perf script
69 69
70=head1 SYNOPSIS 70=head1 SYNOPSIS
71 71
@@ -73,7 +73,7 @@ Perf::Trace::Util - Perl extension for perf trace
73 73
74=head1 SEE ALSO 74=head1 SEE ALSO
75 75
76Perf (trace) documentation 76Perf (script) documentation
77 77
78=head1 AUTHOR 78=head1 AUTHOR
79 79
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record
index eb5846bcb565..8104895a7b67 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-record
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_exit $@ 2perf record -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-report b/tools/perf/scripts/perl/bin/failed-syscalls-report
index 4028d92dc4ae..9f83cc1ad8ba 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-report
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-report
@@ -7,4 +7,4 @@ if [ $# -gt 0 ] ; then
7 shift 7 shift
8 fi 8 fi
9fi 9fi
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/failed-syscalls.pl $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/failed-syscalls.pl $comm
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record
index 5bfaae5a6cba..33efc8673aae 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-record
+++ b/tools/perf/scripts/perl/bin/rw-by-file-record
@@ -1,3 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@ 2perf record -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@
3 3
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-report b/tools/perf/scripts/perl/bin/rw-by-file-report
index ba25f4d41fb0..77200b3f3100 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-report
+++ b/tools/perf/scripts/perl/bin/rw-by-file-report
@@ -7,7 +7,4 @@ if [ $# -lt 1 ] ; then
7fi 7fi
8comm=$1 8comm=$1
9shift 9shift
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-file.pl $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-file.pl $comm
11
12
13
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record
index 6e0b2f7755ac..7cb9db230448 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-record
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ 2perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-report b/tools/perf/scripts/perl/bin/rw-by-pid-report
index 641a3f5d085c..a27b9f311f95 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-report
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-report
@@ -1,6 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide r/w activity 2# description: system-wide r/w activity
3perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-pid.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-pid.pl
4
5
6
diff --git a/tools/perf/scripts/perl/bin/rwtop-record b/tools/perf/scripts/perl/bin/rwtop-record
index 6e0b2f7755ac..7cb9db230448 100644
--- a/tools/perf/scripts/perl/bin/rwtop-record
+++ b/tools/perf/scripts/perl/bin/rwtop-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ 2perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rwtop-report b/tools/perf/scripts/perl/bin/rwtop-report
index 4918dba77021..83e11ec2e190 100644
--- a/tools/perf/scripts/perl/bin/rwtop-report
+++ b/tools/perf/scripts/perl/bin/rwtop-report
@@ -17,7 +17,4 @@ if [ "$n_args" -gt 0 ] ; then
17 interval=$1 17 interval=$1
18 shift 18 shift
19fi 19fi
20perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rwtop.pl $interval 20perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rwtop.pl $interval
21
22
23
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record
index 9f2acaaae9f0..464251a1bd7e 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-record
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-record
@@ -1,5 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e sched:sched_switch -e sched:sched_wakeup $@ 2perf record -e sched:sched_switch -e sched:sched_wakeup $@
3 3
4 4
5 5
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-report b/tools/perf/scripts/perl/bin/wakeup-latency-report
index 49052ebcb632..889e8130cca5 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-report
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-report
@@ -1,6 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide min/max/avg wakeup latency 2# description: system-wide min/max/avg wakeup latency
3perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/wakeup-latency.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/wakeup-latency.pl
4
5
6
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record
index 85301f2471ff..8edda9078d5d 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-record
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@ 2perf record -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report
index df0c65f4ca93..6d91411d248c 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-report
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-report
@@ -1,7 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: workqueue stats (ins/exe/create/destroy) 2# description: workqueue stats (ins/exe/create/destroy)
3perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl
4
5
6
7
diff --git a/tools/perf/scripts/perl/check-perf-trace.pl b/tools/perf/scripts/perl/check-perf-trace.pl
index 4e7dc0a407a5..4e7076c20616 100644
--- a/tools/perf/scripts/perl/check-perf-trace.pl
+++ b/tools/perf/scripts/perl/check-perf-trace.pl
@@ -1,4 +1,4 @@
1# perf trace event handlers, generated by perf trace -g perl 1# perf script event handlers, generated by perf script -g perl
2# (c) 2009, Tom Zanussi <tzanussi@gmail.com> 2# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2 3# Licensed under the terms of the GNU GPL License version 2
4 4
diff --git a/tools/perf/scripts/perl/rw-by-file.pl b/tools/perf/scripts/perl/rw-by-file.pl
index 2a39097687b9..74844ee2be3e 100644
--- a/tools/perf/scripts/perl/rw-by-file.pl
+++ b/tools/perf/scripts/perl/rw-by-file.pl
@@ -18,7 +18,7 @@ use lib "./Perf-Trace-Util/lib";
18use Perf::Trace::Core; 18use Perf::Trace::Core;
19use Perf::Trace::Util; 19use Perf::Trace::Util;
20 20
21my $usage = "perf trace -s rw-by-file.pl <comm>\n"; 21my $usage = "perf script -s rw-by-file.pl <comm>\n";
22 22
23my $for_comm = shift or die $usage; 23my $for_comm = shift or die $usage;
24 24
diff --git a/tools/perf/scripts/perl/workqueue-stats.pl b/tools/perf/scripts/perl/workqueue-stats.pl
index b84b12699b70..a8eaff5119e0 100644
--- a/tools/perf/scripts/perl/workqueue-stats.pl
+++ b/tools/perf/scripts/perl/workqueue-stats.pl
@@ -10,7 +10,7 @@
10# workqueue:workqueue_destruction -e workqueue:workqueue_execution 10# workqueue:workqueue_destruction -e workqueue:workqueue_execution
11# -e workqueue:workqueue_insertion 11# -e workqueue:workqueue_insertion
12# 12#
13# perf trace -p -s tools/perf/scripts/perl/workqueue-stats.pl 13# perf script -p -s tools/perf/scripts/perl/workqueue-stats.pl
14 14
15use 5.010000; 15use 5.010000;
16use strict; 16use strict;
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index 957085dd5d8d..315067b8f552 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Context.c. Python interfaces for perf trace. 2 * Context.c. Python interfaces for perf script.
3 * 3 *
4 * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com> 4 * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
5 * 5 *
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index aad7525bca1d..de7211e4fa47 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -1,4 +1,4 @@
1# Core.py - Python extension for perf trace, core functions 1# Core.py - Python extension for perf script, core functions
2# 2#
3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com> 3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
4# 4#
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
index ae9a56e43e05..fdd92f699055 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
@@ -1,4 +1,4 @@
1# SchedGui.py - Python extension for perf trace, basic GUI code for 1# SchedGui.py - Python extension for perf script, basic GUI code for
2# traces drawing and overview. 2# traces drawing and overview.
3# 3#
4# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com> 4# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com>
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
index 13cc02b5893a..15c8400240fd 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
@@ -1,4 +1,4 @@
1# Util.py - Python extension for perf trace, miscellaneous utility code 1# Util.py - Python extension for perf script, miscellaneous utility code
2# 2#
3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com> 3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
4# 4#
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
index eb5846bcb565..8104895a7b67 100644
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_exit $@ 2perf record -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
index 03587021463d..fda5096d0cbf 100644
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
@@ -7,4 +7,4 @@ if [ $# -gt 0 ] ; then
7 shift 7 shift
8 fi 8 fi
9fi 9fi
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/failed-syscalls-by-pid.py $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/failed-syscalls-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/futex-contention-record b/tools/perf/scripts/python/bin/futex-contention-record
index 5ecbb433caf4..b1495c9a9b20 100644
--- a/tools/perf/scripts/python/bin/futex-contention-record
+++ b/tools/perf/scripts/python/bin/futex-contention-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@ 2perf record -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@
diff --git a/tools/perf/scripts/python/bin/futex-contention-report b/tools/perf/scripts/python/bin/futex-contention-report
index c8268138fb7e..6c44271091ab 100644
--- a/tools/perf/scripts/python/bin/futex-contention-report
+++ b/tools/perf/scripts/python/bin/futex-contention-report
@@ -1,4 +1,4 @@
1#!/bin/bash 1#!/bin/bash
2# description: futext contention measurement 2# description: futext contention measurement
3 3
4perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py 4perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py
diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record
index d931a828126b..558754b840a9 100644
--- a/tools/perf/scripts/python/bin/netdev-times-record
+++ b/tools/perf/scripts/python/bin/netdev-times-record
@@ -1,5 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e net:net_dev_xmit -e net:net_dev_queue \ 2perf record -e net:net_dev_xmit -e net:net_dev_queue \
3 -e net:netif_receive_skb -e net:netif_rx \ 3 -e net:netif_receive_skb -e net:netif_rx \
4 -e skb:consume_skb -e skb:kfree_skb \ 4 -e skb:consume_skb -e skb:kfree_skb \
5 -e skb:skb_copy_datagram_iovec -e napi:napi_poll \ 5 -e skb:skb_copy_datagram_iovec -e napi:napi_poll \
diff --git a/tools/perf/scripts/python/bin/netdev-times-report b/tools/perf/scripts/python/bin/netdev-times-report
index 4ad361b31249..8f759291da86 100644
--- a/tools/perf/scripts/python/bin/netdev-times-report
+++ b/tools/perf/scripts/python/bin/netdev-times-report
@@ -2,4 +2,4 @@
2# description: display a process of packet and processing time 2# description: display a process of packet and processing time
3# args: [tx] [rx] [dev=] [debug] 3# args: [tx] [rx] [dev=] [debug]
4 4
5perf trace -s "$PERF_EXEC_PATH"/scripts/python/netdev-times.py $@ 5perf script -s "$PERF_EXEC_PATH"/scripts/python/netdev-times.py $@
diff --git a/tools/perf/scripts/python/bin/sched-migration-record b/tools/perf/scripts/python/bin/sched-migration-record
index 17a3e9bd9e8f..7493fddbe995 100644
--- a/tools/perf/scripts/python/bin/sched-migration-record
+++ b/tools/perf/scripts/python/bin/sched-migration-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -m 16384 -a -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@ 2perf record -m 16384 -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@
diff --git a/tools/perf/scripts/python/bin/sched-migration-report b/tools/perf/scripts/python/bin/sched-migration-report
index df1791f07c24..68b037a1849b 100644
--- a/tools/perf/scripts/python/bin/sched-migration-report
+++ b/tools/perf/scripts/python/bin/sched-migration-report
@@ -1,3 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: sched migration overview 2# description: sched migration overview
3perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/sched-migration.py 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sched-migration.py
diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record
index 1fc5998b721d..4efbfaa7f6a5 100644
--- a/tools/perf/scripts/python/bin/sctop-record
+++ b/tools/perf/scripts/python/bin/sctop-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_enter $@ 2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/sctop-report b/tools/perf/scripts/python/bin/sctop-report
index 36b409c05e50..c32db294124d 100644
--- a/tools/perf/scripts/python/bin/sctop-report
+++ b/tools/perf/scripts/python/bin/sctop-report
@@ -21,4 +21,4 @@ elif [ "$n_args" -gt 0 ] ; then
21 interval=$1 21 interval=$1
22 shift 22 shift
23fi 23fi
24perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/sctop.py $comm $interval 24perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sctop.py $comm $interval
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
index 1fc5998b721d..4efbfaa7f6a5 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_enter $@ 2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
index 4eb88c9fc83c..16eb8d65c543 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
@@ -7,4 +7,4 @@ if [ $# -gt 0 ] ; then
7 shift 7 shift
8 fi 8 fi
9fi 9fi
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts-by-pid.py $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record
index 1fc5998b721d..4efbfaa7f6a5 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_enter $@ 2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-report b/tools/perf/scripts/python/bin/syscall-counts-report
index cb2f9c5cf17e..0f0e9d453bb4 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-report
+++ b/tools/perf/scripts/python/bin/syscall-counts-report
@@ -7,4 +7,4 @@ if [ $# -gt 0 ] ; then
7 shift 7 shift
8 fi 8 fi
9fi 9fi
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts.py $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts.py $comm
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index d9f7893e315c..4647a7694cf6 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -1,4 +1,4 @@
1# perf trace event handlers, generated by perf trace -g python 1# perf script event handlers, generated by perf script -g python
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com> 2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2 3# Licensed under the terms of the GNU GPL License version 2
4# 4#
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index acd7848717b3..85805fac4116 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -15,7 +15,7 @@ from perf_trace_context import *
15from Core import * 15from Core import *
16from Util import * 16from Util import *
17 17
18usage = "perf trace -s syscall-counts-by-pid.py [comm|pid]\n"; 18usage = "perf script -s syscall-counts-by-pid.py [comm|pid]\n";
19 19
20for_comm = None 20for_comm = None
21for_pid = None 21for_pid = None
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index b934383c3364..74d55ec08aed 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -4,7 +4,7 @@
4# 4#
5# Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com> 5# Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com>
6# 6#
7# perf trace event handlers have been generated by perf trace -g python 7# perf script event handlers have been generated by perf script -g python
8# 8#
9# This software is distributed under the terms of the GNU General 9# This software is distributed under the terms of the GNU General
10# Public License ("GPL") version 2 as published by the Free Software 10# Public License ("GPL") version 2 as published by the Free Software
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index 7a6ec2c7d8ab..42c267e292fa 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -17,7 +17,7 @@ from perf_trace_context import *
17from Core import * 17from Core import *
18from Util import * 18from Util import *
19 19
20usage = "perf trace -s sctop.py [comm] [interval]\n"; 20usage = "perf script -s sctop.py [comm] [interval]\n";
21 21
22for_comm = None 22for_comm = None
23default_interval = 3 23default_interval = 3
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index d1ee3ec10cf2..c64d1c55d745 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -14,7 +14,7 @@ from perf_trace_context import *
14from Core import * 14from Core import *
15from Util import syscall_name 15from Util import syscall_name
16 16
17usage = "perf trace -s syscall-counts-by-pid.py [comm]\n"; 17usage = "perf script -s syscall-counts-by-pid.py [comm]\n";
18 18
19for_comm = None 19for_comm = None
20for_pid = None 20for_pid = None
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index ea183dc82d29..b435d3f188e8 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -15,7 +15,7 @@ from perf_trace_context import *
15from Core import * 15from Core import *
16from Util import syscall_name 16from Util import syscall_name
17 17
18usage = "perf trace -s syscall-counts.py [comm]\n"; 18usage = "perf script -s syscall-counts.py [comm]\n";
19 19
20for_comm = None 20for_comm = None
21 21
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e437edb72417..deffb8c96071 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -14,7 +14,9 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include "debug.h" 15#include "debug.h"
16 16
17static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) 17static int build_id__mark_dso_hit(event_t *event,
18 struct sample_data *sample __used,
19 struct perf_session *session)
18{ 20{
19 struct addr_location al; 21 struct addr_location al;
20 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 22 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
@@ -35,7 +37,8 @@ static int build_id__mark_dso_hit(event_t *event, struct perf_session *session)
35 return 0; 37 return 0;
36} 38}
37 39
38static int event__exit_del_thread(event_t *self, struct perf_session *session) 40static int event__exit_del_thread(event_t *self, struct sample_data *sample __used,
41 struct perf_session *session)
39{ 42{
40 struct thread *thread = perf_session__findnew(session, self->fork.tid); 43 struct thread *thread = perf_session__findnew(session, self->fork.tid);
41 44
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 0f9b8d7a7d7e..3ccaa1043383 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -4,32 +4,53 @@
4#include <assert.h> 4#include <assert.h>
5#include <stdio.h> 5#include <stdio.h>
6 6
7int cpumap[MAX_NR_CPUS]; 7static struct cpu_map *cpu_map__default_new(void)
8
9static int default_cpu_map(void)
10{ 8{
11 int nr_cpus, i; 9 struct cpu_map *cpus;
10 int nr_cpus;
12 11
13 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 12 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
14 assert(nr_cpus <= MAX_NR_CPUS); 13 if (nr_cpus < 0)
15 assert((int)nr_cpus >= 0); 14 return NULL;
15
16 cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
17 if (cpus != NULL) {
18 int i;
19 for (i = 0; i < nr_cpus; ++i)
20 cpus->map[i] = i;
16 21
17 for (i = 0; i < nr_cpus; ++i) 22 cpus->nr = nr_cpus;
18 cpumap[i] = i; 23 }
19 24
20 return nr_cpus; 25 return cpus;
21} 26}
22 27
23static int read_all_cpu_map(void) 28static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
24{ 29{
30 size_t payload_size = nr_cpus * sizeof(int);
31 struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
32
33 if (cpus != NULL) {
34 cpus->nr = nr_cpus;
35 memcpy(cpus->map, tmp_cpus, payload_size);
36 }
37
38 return cpus;
39}
40
41static struct cpu_map *cpu_map__read_all_cpu_map(void)
42{
43 struct cpu_map *cpus = NULL;
25 FILE *onlnf; 44 FILE *onlnf;
26 int nr_cpus = 0; 45 int nr_cpus = 0;
46 int *tmp_cpus = NULL, *tmp;
47 int max_entries = 0;
27 int n, cpu, prev; 48 int n, cpu, prev;
28 char sep; 49 char sep;
29 50
30 onlnf = fopen("/sys/devices/system/cpu/online", "r"); 51 onlnf = fopen("/sys/devices/system/cpu/online", "r");
31 if (!onlnf) 52 if (!onlnf)
32 return default_cpu_map(); 53 return cpu_map__default_new();
33 54
34 sep = 0; 55 sep = 0;
35 prev = -1; 56 prev = -1;
@@ -38,12 +59,28 @@ static int read_all_cpu_map(void)
38 if (n <= 0) 59 if (n <= 0)
39 break; 60 break;
40 if (prev >= 0) { 61 if (prev >= 0) {
41 assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS); 62 int new_max = nr_cpus + cpu - prev - 1;
63
64 if (new_max >= max_entries) {
65 max_entries = new_max + MAX_NR_CPUS / 2;
66 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
67 if (tmp == NULL)
68 goto out_free_tmp;
69 tmp_cpus = tmp;
70 }
71
42 while (++prev < cpu) 72 while (++prev < cpu)
43 cpumap[nr_cpus++] = prev; 73 tmp_cpus[nr_cpus++] = prev;
74 }
75 if (nr_cpus == max_entries) {
76 max_entries += MAX_NR_CPUS;
77 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
78 if (tmp == NULL)
79 goto out_free_tmp;
80 tmp_cpus = tmp;
44 } 81 }
45 assert (nr_cpus < MAX_NR_CPUS); 82
46 cpumap[nr_cpus++] = cpu; 83 tmp_cpus[nr_cpus++] = cpu;
47 if (n == 2 && sep == '-') 84 if (n == 2 && sep == '-')
48 prev = cpu; 85 prev = cpu;
49 else 86 else
@@ -51,24 +88,31 @@ static int read_all_cpu_map(void)
51 if (n == 1 || sep == '\n') 88 if (n == 1 || sep == '\n')
52 break; 89 break;
53 } 90 }
54 fclose(onlnf);
55 if (nr_cpus > 0)
56 return nr_cpus;
57 91
58 return default_cpu_map(); 92 if (nr_cpus > 0)
93 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
94 else
95 cpus = cpu_map__default_new();
96out_free_tmp:
97 free(tmp_cpus);
98 fclose(onlnf);
99 return cpus;
59} 100}
60 101
61int read_cpu_map(const char *cpu_list) 102struct cpu_map *cpu_map__new(const char *cpu_list)
62{ 103{
104 struct cpu_map *cpus = NULL;
63 unsigned long start_cpu, end_cpu = 0; 105 unsigned long start_cpu, end_cpu = 0;
64 char *p = NULL; 106 char *p = NULL;
65 int i, nr_cpus = 0; 107 int i, nr_cpus = 0;
108 int *tmp_cpus = NULL, *tmp;
109 int max_entries = 0;
66 110
67 if (!cpu_list) 111 if (!cpu_list)
68 return read_all_cpu_map(); 112 return cpu_map__read_all_cpu_map();
69 113
70 if (!isdigit(*cpu_list)) 114 if (!isdigit(*cpu_list))
71 goto invalid; 115 goto out;
72 116
73 while (isdigit(*cpu_list)) { 117 while (isdigit(*cpu_list)) {
74 p = NULL; 118 p = NULL;
@@ -94,21 +138,42 @@ int read_cpu_map(const char *cpu_list)
94 for (; start_cpu <= end_cpu; start_cpu++) { 138 for (; start_cpu <= end_cpu; start_cpu++) {
95 /* check for duplicates */ 139 /* check for duplicates */
96 for (i = 0; i < nr_cpus; i++) 140 for (i = 0; i < nr_cpus; i++)
97 if (cpumap[i] == (int)start_cpu) 141 if (tmp_cpus[i] == (int)start_cpu)
98 goto invalid; 142 goto invalid;
99 143
100 assert(nr_cpus < MAX_NR_CPUS); 144 if (nr_cpus == max_entries) {
101 cpumap[nr_cpus++] = (int)start_cpu; 145 max_entries += MAX_NR_CPUS;
146 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
147 if (tmp == NULL)
148 goto invalid;
149 tmp_cpus = tmp;
150 }
151 tmp_cpus[nr_cpus++] = (int)start_cpu;
102 } 152 }
103 if (*p) 153 if (*p)
104 ++p; 154 ++p;
105 155
106 cpu_list = p; 156 cpu_list = p;
107 } 157 }
108 if (nr_cpus > 0)
109 return nr_cpus;
110 158
111 return default_cpu_map(); 159 if (nr_cpus > 0)
160 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
161 else
162 cpus = cpu_map__default_new();
112invalid: 163invalid:
113 return -1; 164 free(tmp_cpus);
165out:
166 return cpus;
167}
168
169struct cpu_map *cpu_map__dummy_new(void)
170{
171 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
172
173 if (cpus != NULL) {
174 cpus->nr = 1;
175 cpus->map[0] = -1;
176 }
177
178 return cpus;
114} 179}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 3e60f56e490e..f7a4f42f6307 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -1,7 +1,13 @@
1#ifndef __PERF_CPUMAP_H 1#ifndef __PERF_CPUMAP_H
2#define __PERF_CPUMAP_H 2#define __PERF_CPUMAP_H
3 3
4extern int read_cpu_map(const char *cpu_list); 4struct cpu_map {
5extern int cpumap[]; 5 int nr;
6 int map[];
7};
8
9struct cpu_map *cpu_map__new(const char *cpu_list);
10struct cpu_map *cpu_map__dummy_new(void);
11void *cpu_map__delete(struct cpu_map *map);
6 12
7#endif /* __PERF_CPUMAP_H */ 13#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index c8d81b00089d..01bbe8ecec3f 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -46,20 +46,16 @@ int dump_printf(const char *fmt, ...)
46 return ret; 46 return ret;
47} 47}
48 48
49static int dump_printf_color(const char *fmt, const char *color, ...) 49#ifdef NO_NEWT_SUPPORT
50void ui__warning(const char *format, ...)
50{ 51{
51 va_list args; 52 va_list args;
52 int ret = 0;
53 53
54 if (dump_trace) { 54 va_start(args, format);
55 va_start(args, color); 55 vfprintf(stderr, format, args);
56 ret = color_vfprintf(stdout, color, fmt, args); 56 va_end(args);
57 va_end(args);
58 }
59
60 return ret;
61} 57}
62 58#endif
63 59
64void trace_event(event_t *event) 60void trace_event(event_t *event)
65{ 61{
@@ -70,29 +66,29 @@ void trace_event(event_t *event)
70 if (!dump_trace) 66 if (!dump_trace)
71 return; 67 return;
72 68
73 dump_printf("."); 69 printf(".");
74 dump_printf_color("\n. ... raw event: size %d bytes\n", color, 70 color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n",
75 event->header.size); 71 event->header.size);
76 72
77 for (i = 0; i < event->header.size; i++) { 73 for (i = 0; i < event->header.size; i++) {
78 if ((i & 15) == 0) { 74 if ((i & 15) == 0) {
79 dump_printf("."); 75 printf(".");
80 dump_printf_color(" %04x: ", color, i); 76 color_fprintf(stdout, color, " %04x: ", i);
81 } 77 }
82 78
83 dump_printf_color(" %02x", color, raw_event[i]); 79 color_fprintf(stdout, color, " %02x", raw_event[i]);
84 80
85 if (((i & 15) == 15) || i == event->header.size-1) { 81 if (((i & 15) == 15) || i == event->header.size-1) {
86 dump_printf_color(" ", color); 82 color_fprintf(stdout, color, " ");
87 for (j = 0; j < 15-(i & 15); j++) 83 for (j = 0; j < 15-(i & 15); j++)
88 dump_printf_color(" ", color); 84 color_fprintf(stdout, color, " ");
89 for (j = i & ~15; j <= i; j++) { 85 for (j = i & ~15; j <= i; j++) {
90 dump_printf_color("%c", color, 86 color_fprintf(stdout, color, "%c",
91 isprint(raw_event[j]) ? 87 isprint(raw_event[j]) ?
92 raw_event[j] : '.'); 88 raw_event[j] : '.');
93 } 89 }
94 dump_printf_color("\n", color); 90 color_fprintf(stdout, color, "\n");
95 } 91 }
96 } 92 }
97 dump_printf(".\n"); 93 printf(".\n");
98} 94}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 7b514082bbaf..ca35fd66b5df 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -35,4 +35,6 @@ int ui_helpline__show_help(const char *format, va_list ap);
35#include "ui/progress.h" 35#include "ui/progress.h"
36#endif 36#endif
37 37
38void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
39
38#endif /* __PERF_DEBUG_H */ 40#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index dab9e754a281..1478ab4ee222 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -7,7 +7,7 @@
7#include "strlist.h" 7#include "strlist.h"
8#include "thread.h" 8#include "thread.h"
9 9
10const char *event__name[] = { 10static const char *event__name[] = {
11 [0] = "TOTAL", 11 [0] = "TOTAL",
12 [PERF_RECORD_MMAP] = "MMAP", 12 [PERF_RECORD_MMAP] = "MMAP",
13 [PERF_RECORD_LOST] = "LOST", 13 [PERF_RECORD_LOST] = "LOST",
@@ -22,13 +22,31 @@ const char *event__name[] = {
22 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 22 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
23 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 23 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
24 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 24 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
25 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND",
25}; 26};
26 27
27static pid_t event__synthesize_comm(pid_t pid, int full, 28const char *event__get_event_name(unsigned int id)
29{
30 if (id >= ARRAY_SIZE(event__name))
31 return "INVALID";
32 if (!event__name[id])
33 return "UNKNOWN";
34 return event__name[id];
35}
36
37static struct sample_data synth_sample = {
38 .pid = -1,
39 .tid = -1,
40 .time = -1,
41 .stream_id = -1,
42 .cpu = -1,
43 .period = 1,
44};
45
46static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
28 event__handler_t process, 47 event__handler_t process,
29 struct perf_session *session) 48 struct perf_session *session)
30{ 49{
31 event_t ev;
32 char filename[PATH_MAX]; 50 char filename[PATH_MAX];
33 char bf[BUFSIZ]; 51 char bf[BUFSIZ];
34 FILE *fp; 52 FILE *fp;
@@ -49,34 +67,39 @@ out_race:
49 return 0; 67 return 0;
50 } 68 }
51 69
52 memset(&ev.comm, 0, sizeof(ev.comm)); 70 memset(&event->comm, 0, sizeof(event->comm));
53 while (!ev.comm.comm[0] || !ev.comm.pid) { 71
54 if (fgets(bf, sizeof(bf), fp) == NULL) 72 while (!event->comm.comm[0] || !event->comm.pid) {
55 goto out_failure; 73 if (fgets(bf, sizeof(bf), fp) == NULL) {
74 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
75 goto out;
76 }
56 77
57 if (memcmp(bf, "Name:", 5) == 0) { 78 if (memcmp(bf, "Name:", 5) == 0) {
58 char *name = bf + 5; 79 char *name = bf + 5;
59 while (*name && isspace(*name)) 80 while (*name && isspace(*name))
60 ++name; 81 ++name;
61 size = strlen(name) - 1; 82 size = strlen(name) - 1;
62 memcpy(ev.comm.comm, name, size++); 83 memcpy(event->comm.comm, name, size++);
63 } else if (memcmp(bf, "Tgid:", 5) == 0) { 84 } else if (memcmp(bf, "Tgid:", 5) == 0) {
64 char *tgids = bf + 5; 85 char *tgids = bf + 5;
65 while (*tgids && isspace(*tgids)) 86 while (*tgids && isspace(*tgids))
66 ++tgids; 87 ++tgids;
67 tgid = ev.comm.pid = atoi(tgids); 88 tgid = event->comm.pid = atoi(tgids);
68 } 89 }
69 } 90 }
70 91
71 ev.comm.header.type = PERF_RECORD_COMM; 92 event->comm.header.type = PERF_RECORD_COMM;
72 size = ALIGN(size, sizeof(u64)); 93 size = ALIGN(size, sizeof(u64));
73 ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size); 94 memset(event->comm.comm + size, 0, session->id_hdr_size);
74 95 event->comm.header.size = (sizeof(event->comm) -
96 (sizeof(event->comm.comm) - size) +
97 session->id_hdr_size);
75 if (!full) { 98 if (!full) {
76 ev.comm.tid = pid; 99 event->comm.tid = pid;
77 100
78 process(&ev, session); 101 process(event, &synth_sample, session);
79 goto out_fclose; 102 goto out;
80 } 103 }
81 104
82 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 105 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -91,22 +114,19 @@ out_race:
91 if (*end) 114 if (*end)
92 continue; 115 continue;
93 116
94 ev.comm.tid = pid; 117 event->comm.tid = pid;
95 118
96 process(&ev, session); 119 process(event, &synth_sample, session);
97 } 120 }
98 closedir(tasks);
99 121
100out_fclose: 122 closedir(tasks);
123out:
101 fclose(fp); 124 fclose(fp);
102 return tgid;
103 125
104out_failure: 126 return tgid;
105 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
106 return -1;
107} 127}
108 128
109static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, 129static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
110 event__handler_t process, 130 event__handler_t process,
111 struct perf_session *session) 131 struct perf_session *session)
112{ 132{
@@ -124,29 +144,25 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
124 return -1; 144 return -1;
125 } 145 }
126 146
147 event->header.type = PERF_RECORD_MMAP;
148 /*
149 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
150 */
151 event->header.misc = PERF_RECORD_MISC_USER;
152
127 while (1) { 153 while (1) {
128 char bf[BUFSIZ], *pbf = bf; 154 char bf[BUFSIZ], *pbf = bf;
129 event_t ev = {
130 .header = {
131 .type = PERF_RECORD_MMAP,
132 /*
133 * Just like the kernel, see __perf_event_mmap
134 * in kernel/perf_event.c
135 */
136 .misc = PERF_RECORD_MISC_USER,
137 },
138 };
139 int n; 155 int n;
140 size_t size; 156 size_t size;
141 if (fgets(bf, sizeof(bf), fp) == NULL) 157 if (fgets(bf, sizeof(bf), fp) == NULL)
142 break; 158 break;
143 159
144 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 160 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
145 n = hex2u64(pbf, &ev.mmap.start); 161 n = hex2u64(pbf, &event->mmap.start);
146 if (n < 0) 162 if (n < 0)
147 continue; 163 continue;
148 pbf += n + 1; 164 pbf += n + 1;
149 n = hex2u64(pbf, &ev.mmap.len); 165 n = hex2u64(pbf, &event->mmap.len);
150 if (n < 0) 166 if (n < 0)
151 continue; 167 continue;
152 pbf += n + 3; 168 pbf += n + 3;
@@ -161,19 +177,21 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
161 continue; 177 continue;
162 178
163 pbf += 3; 179 pbf += 3;
164 n = hex2u64(pbf, &ev.mmap.pgoff); 180 n = hex2u64(pbf, &event->mmap.pgoff);
165 181
166 size = strlen(execname); 182 size = strlen(execname);
167 execname[size - 1] = '\0'; /* Remove \n */ 183 execname[size - 1] = '\0'; /* Remove \n */
168 memcpy(ev.mmap.filename, execname, size); 184 memcpy(event->mmap.filename, execname, size);
169 size = ALIGN(size, sizeof(u64)); 185 size = ALIGN(size, sizeof(u64));
170 ev.mmap.len -= ev.mmap.start; 186 event->mmap.len -= event->mmap.start;
171 ev.mmap.header.size = (sizeof(ev.mmap) - 187 event->mmap.header.size = (sizeof(event->mmap) -
172 (sizeof(ev.mmap.filename) - size)); 188 (sizeof(event->mmap.filename) - size));
173 ev.mmap.pid = tgid; 189 memset(event->mmap.filename + size, 0, session->id_hdr_size);
174 ev.mmap.tid = pid; 190 event->mmap.header.size += session->id_hdr_size;
175 191 event->mmap.pid = tgid;
176 process(&ev, session); 192 event->mmap.tid = pid;
193
194 process(event, &synth_sample, session);
177 } 195 }
178 } 196 }
179 197
@@ -187,20 +205,27 @@ int event__synthesize_modules(event__handler_t process,
187{ 205{
188 struct rb_node *nd; 206 struct rb_node *nd;
189 struct map_groups *kmaps = &machine->kmaps; 207 struct map_groups *kmaps = &machine->kmaps;
190 u16 misc; 208 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
209
210 if (event == NULL) {
211 pr_debug("Not enough memory synthesizing mmap event "
212 "for kernel modules\n");
213 return -1;
214 }
215
216 event->header.type = PERF_RECORD_MMAP;
191 217
192 /* 218 /*
193 * kernel uses 0 for user space maps, see kernel/perf_event.c 219 * kernel uses 0 for user space maps, see kernel/perf_event.c
194 * __perf_event_mmap 220 * __perf_event_mmap
195 */ 221 */
196 if (machine__is_host(machine)) 222 if (machine__is_host(machine))
197 misc = PERF_RECORD_MISC_KERNEL; 223 event->header.misc = PERF_RECORD_MISC_KERNEL;
198 else 224 else
199 misc = PERF_RECORD_MISC_GUEST_KERNEL; 225 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
200 226
201 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 227 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
202 nd; nd = rb_next(nd)) { 228 nd; nd = rb_next(nd)) {
203 event_t ev;
204 size_t size; 229 size_t size;
205 struct map *pos = rb_entry(nd, struct map, rb_node); 230 struct map *pos = rb_entry(nd, struct map, rb_node);
206 231
@@ -208,39 +233,78 @@ int event__synthesize_modules(event__handler_t process,
208 continue; 233 continue;
209 234
210 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 235 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
211 memset(&ev, 0, sizeof(ev)); 236 event->mmap.header.type = PERF_RECORD_MMAP;
212 ev.mmap.header.misc = misc; 237 event->mmap.header.size = (sizeof(event->mmap) -
213 ev.mmap.header.type = PERF_RECORD_MMAP; 238 (sizeof(event->mmap.filename) - size));
214 ev.mmap.header.size = (sizeof(ev.mmap) - 239 memset(event->mmap.filename + size, 0, session->id_hdr_size);
215 (sizeof(ev.mmap.filename) - size)); 240 event->mmap.header.size += session->id_hdr_size;
216 ev.mmap.start = pos->start; 241 event->mmap.start = pos->start;
217 ev.mmap.len = pos->end - pos->start; 242 event->mmap.len = pos->end - pos->start;
218 ev.mmap.pid = machine->pid; 243 event->mmap.pid = machine->pid;
219 244
220 memcpy(ev.mmap.filename, pos->dso->long_name, 245 memcpy(event->mmap.filename, pos->dso->long_name,
221 pos->dso->long_name_len + 1); 246 pos->dso->long_name_len + 1);
222 process(&ev, session); 247 process(event, &synth_sample, session);
223 } 248 }
224 249
250 free(event);
225 return 0; 251 return 0;
226} 252}
227 253
228int event__synthesize_thread(pid_t pid, event__handler_t process, 254static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
229 struct perf_session *session) 255 pid_t pid, event__handler_t process,
256 struct perf_session *session)
230{ 257{
231 pid_t tgid = event__synthesize_comm(pid, 1, process, session); 258 pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
259 session);
232 if (tgid == -1) 260 if (tgid == -1)
233 return -1; 261 return -1;
234 return event__synthesize_mmap_events(pid, tgid, process, session); 262 return event__synthesize_mmap_events(mmap_event, pid, tgid,
263 process, session);
264}
265
266int event__synthesize_thread(pid_t pid, event__handler_t process,
267 struct perf_session *session)
268{
269 event_t *comm_event, *mmap_event;
270 int err = -1;
271
272 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
273 if (comm_event == NULL)
274 goto out;
275
276 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
277 if (mmap_event == NULL)
278 goto out_free_comm;
279
280 err = __event__synthesize_thread(comm_event, mmap_event, pid,
281 process, session);
282 free(mmap_event);
283out_free_comm:
284 free(comm_event);
285out:
286 return err;
235} 287}
236 288
237void event__synthesize_threads(event__handler_t process, 289int event__synthesize_threads(event__handler_t process,
238 struct perf_session *session) 290 struct perf_session *session)
239{ 291{
240 DIR *proc; 292 DIR *proc;
241 struct dirent dirent, *next; 293 struct dirent dirent, *next;
294 event_t *comm_event, *mmap_event;
295 int err = -1;
296
297 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
298 if (comm_event == NULL)
299 goto out;
300
301 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
302 if (mmap_event == NULL)
303 goto out_free_comm;
242 304
243 proc = opendir("/proc"); 305 proc = opendir("/proc");
306 if (proc == NULL)
307 goto out_free_mmap;
244 308
245 while (!readdir_r(proc, &dirent, &next) && next) { 309 while (!readdir_r(proc, &dirent, &next) && next) {
246 char *end; 310 char *end;
@@ -249,10 +313,18 @@ void event__synthesize_threads(event__handler_t process,
249 if (*end) /* only interested in proper numerical dirents */ 313 if (*end) /* only interested in proper numerical dirents */
250 continue; 314 continue;
251 315
252 event__synthesize_thread(pid, process, session); 316 __event__synthesize_thread(comm_event, mmap_event, pid,
317 process, session);
253 } 318 }
254 319
255 closedir(proc); 320 closedir(proc);
321 err = 0;
322out_free_mmap:
323 free(mmap_event);
324out_free_comm:
325 free(comm_event);
326out:
327 return err;
256} 328}
257 329
258struct process_symbol_args { 330struct process_symbol_args {
@@ -260,7 +332,8 @@ struct process_symbol_args {
260 u64 start; 332 u64 start;
261}; 333};
262 334
263static int find_symbol_cb(void *arg, const char *name, char type, u64 start) 335static int find_symbol_cb(void *arg, const char *name, char type,
336 u64 start, u64 end __used)
264{ 337{
265 struct process_symbol_args *args = arg; 338 struct process_symbol_args *args = arg;
266 339
@@ -286,18 +359,20 @@ int event__synthesize_kernel_mmap(event__handler_t process,
286 char path[PATH_MAX]; 359 char path[PATH_MAX];
287 char name_buff[PATH_MAX]; 360 char name_buff[PATH_MAX];
288 struct map *map; 361 struct map *map;
289 362 int err;
290 event_t ev = {
291 .header = {
292 .type = PERF_RECORD_MMAP,
293 },
294 };
295 /* 363 /*
296 * We should get this from /sys/kernel/sections/.text, but till that is 364 * We should get this from /sys/kernel/sections/.text, but till that is
297 * available use this, and after it is use this as a fallback for older 365 * available use this, and after it is use this as a fallback for older
298 * kernels. 366 * kernels.
299 */ 367 */
300 struct process_symbol_args args = { .name = symbol_name, }; 368 struct process_symbol_args args = { .name = symbol_name, };
369 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
370
371 if (event == NULL) {
372 pr_debug("Not enough memory synthesizing mmap event "
373 "for kernel modules\n");
374 return -1;
375 }
301 376
302 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); 377 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
303 if (machine__is_host(machine)) { 378 if (machine__is_host(machine)) {
@@ -305,10 +380,10 @@ int event__synthesize_kernel_mmap(event__handler_t process,
305 * kernel uses PERF_RECORD_MISC_USER for user space maps, 380 * kernel uses PERF_RECORD_MISC_USER for user space maps,
306 * see kernel/perf_event.c __perf_event_mmap 381 * see kernel/perf_event.c __perf_event_mmap
307 */ 382 */
308 ev.header.misc = PERF_RECORD_MISC_KERNEL; 383 event->header.misc = PERF_RECORD_MISC_KERNEL;
309 filename = "/proc/kallsyms"; 384 filename = "/proc/kallsyms";
310 } else { 385 } else {
311 ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 386 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
312 if (machine__is_default_guest(machine)) 387 if (machine__is_default_guest(machine))
313 filename = (char *) symbol_conf.default_guest_kallsyms; 388 filename = (char *) symbol_conf.default_guest_kallsyms;
314 else { 389 else {
@@ -321,17 +396,21 @@ int event__synthesize_kernel_mmap(event__handler_t process,
321 return -ENOENT; 396 return -ENOENT;
322 397
323 map = machine->vmlinux_maps[MAP__FUNCTION]; 398 map = machine->vmlinux_maps[MAP__FUNCTION];
324 size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), 399 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
325 "%s%s", mmap_name, symbol_name) + 1; 400 "%s%s", mmap_name, symbol_name) + 1;
326 size = ALIGN(size, sizeof(u64)); 401 size = ALIGN(size, sizeof(u64));
327 ev.mmap.header.size = (sizeof(ev.mmap) - 402 event->mmap.header.type = PERF_RECORD_MMAP;
328 (sizeof(ev.mmap.filename) - size)); 403 event->mmap.header.size = (sizeof(event->mmap) -
329 ev.mmap.pgoff = args.start; 404 (sizeof(event->mmap.filename) - size) + session->id_hdr_size);
330 ev.mmap.start = map->start; 405 event->mmap.pgoff = args.start;
331 ev.mmap.len = map->end - ev.mmap.start; 406 event->mmap.start = map->start;
332 ev.mmap.pid = machine->pid; 407 event->mmap.len = map->end - event->mmap.start;
333 408 event->mmap.pid = machine->pid;
334 return process(&ev, session); 409
410 err = process(event, &synth_sample, session);
411 free(event);
412
413 return err;
335} 414}
336 415
337static void thread__comm_adjust(struct thread *self, struct hists *hists) 416static void thread__comm_adjust(struct thread *self, struct hists *hists)
@@ -361,7 +440,8 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm,
361 return 0; 440 return 0;
362} 441}
363 442
364int event__process_comm(event_t *self, struct perf_session *session) 443int event__process_comm(event_t *self, struct sample_data *sample __used,
444 struct perf_session *session)
365{ 445{
366 struct thread *thread = perf_session__findnew(session, self->comm.tid); 446 struct thread *thread = perf_session__findnew(session, self->comm.tid);
367 447
@@ -376,9 +456,11 @@ int event__process_comm(event_t *self, struct perf_session *session)
376 return 0; 456 return 0;
377} 457}
378 458
379int event__process_lost(event_t *self, struct perf_session *session) 459int event__process_lost(event_t *self, struct sample_data *sample __used,
460 struct perf_session *session)
380{ 461{
381 dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); 462 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
463 self->lost.id, self->lost.lost);
382 session->hists.stats.total_lost += self->lost.lost; 464 session->hists.stats.total_lost += self->lost.lost;
383 return 0; 465 return 0;
384} 466}
@@ -392,7 +474,7 @@ static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
392 * a zero sized synthesized MMAP event for the kernel. 474 * a zero sized synthesized MMAP event for the kernel.
393 */ 475 */
394 if (maps[MAP__FUNCTION]->end == 0) 476 if (maps[MAP__FUNCTION]->end == 0)
395 maps[MAP__FUNCTION]->end = ~0UL; 477 maps[MAP__FUNCTION]->end = ~0ULL;
396} 478}
397 479
398static int event__process_kernel_mmap(event_t *self, 480static int event__process_kernel_mmap(event_t *self,
@@ -485,7 +567,8 @@ out_problem:
485 return -1; 567 return -1;
486} 568}
487 569
488int event__process_mmap(event_t *self, struct perf_session *session) 570int event__process_mmap(event_t *self, struct sample_data *sample __used,
571 struct perf_session *session)
489{ 572{
490 struct machine *machine; 573 struct machine *machine;
491 struct thread *thread; 574 struct thread *thread;
@@ -493,7 +576,7 @@ int event__process_mmap(event_t *self, struct perf_session *session)
493 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 576 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
494 int ret = 0; 577 int ret = 0;
495 578
496 dump_printf(" %d/%d: [%#Lx(%#Lx) @ %#Lx]: %s\n", 579 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
497 self->mmap.pid, self->mmap.tid, self->mmap.start, 580 self->mmap.pid, self->mmap.tid, self->mmap.start,
498 self->mmap.len, self->mmap.pgoff, self->mmap.filename); 581 self->mmap.len, self->mmap.pgoff, self->mmap.filename);
499 582
@@ -526,7 +609,8 @@ out_problem:
526 return 0; 609 return 0;
527} 610}
528 611
529int event__process_task(event_t *self, struct perf_session *session) 612int event__process_task(event_t *self, struct sample_data *sample __used,
613 struct perf_session *session)
530{ 614{
531 struct thread *thread = perf_session__findnew(session, self->fork.tid); 615 struct thread *thread = perf_session__findnew(session, self->fork.tid);
532 struct thread *parent = perf_session__findnew(session, self->fork.ptid); 616 struct thread *parent = perf_session__findnew(session, self->fork.ptid);
@@ -548,18 +632,19 @@ int event__process_task(event_t *self, struct perf_session *session)
548 return 0; 632 return 0;
549} 633}
550 634
551int event__process(event_t *event, struct perf_session *session) 635int event__process(event_t *event, struct sample_data *sample,
636 struct perf_session *session)
552{ 637{
553 switch (event->header.type) { 638 switch (event->header.type) {
554 case PERF_RECORD_COMM: 639 case PERF_RECORD_COMM:
555 event__process_comm(event, session); 640 event__process_comm(event, sample, session);
556 break; 641 break;
557 case PERF_RECORD_MMAP: 642 case PERF_RECORD_MMAP:
558 event__process_mmap(event, session); 643 event__process_mmap(event, sample, session);
559 break; 644 break;
560 case PERF_RECORD_FORK: 645 case PERF_RECORD_FORK:
561 case PERF_RECORD_EXIT: 646 case PERF_RECORD_EXIT:
562 event__process_task(event, session); 647 event__process_task(event, sample, session);
563 break; 648 break;
564 default: 649 default:
565 break; 650 break;
@@ -674,32 +759,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
674 symbol_filter_t filter) 759 symbol_filter_t filter)
675{ 760{
676 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 761 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
677 struct thread *thread; 762 struct thread *thread = perf_session__findnew(session, self->ip.pid);
678
679 event__parse_sample(self, session->sample_type, data);
680
681 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n",
682 self->header.misc, data->pid, data->tid, data->ip,
683 data->period, data->cpu);
684
685 if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
686 unsigned int i;
687
688 dump_printf("... chain: nr:%Lu\n", data->callchain->nr);
689 763
690 if (!ip_callchain__valid(data->callchain, self)) {
691 pr_debug("call-chain problem with event, "
692 "skipping it.\n");
693 goto out_filtered;
694 }
695
696 if (dump_trace) {
697 for (i = 0; i < data->callchain->nr; i++)
698 dump_printf("..... %2d: %016Lx\n",
699 i, data->callchain->ips[i]);
700 }
701 }
702 thread = perf_session__findnew(session, self->ip.pid);
703 if (thread == NULL) 764 if (thread == NULL)
704 return -1; 765 return -1;
705 766
@@ -766,9 +827,65 @@ out_filtered:
766 return 0; 827 return 0;
767} 828}
768 829
769int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) 830static int event__parse_id_sample(const event_t *event,
831 struct perf_session *session,
832 struct sample_data *sample)
770{ 833{
771 const u64 *array = event->sample.array; 834 const u64 *array;
835 u64 type;
836
837 sample->cpu = sample->pid = sample->tid = -1;
838 sample->stream_id = sample->id = sample->time = -1ULL;
839
840 if (!session->sample_id_all)
841 return 0;
842
843 array = event->sample.array;
844 array += ((event->header.size -
845 sizeof(event->header)) / sizeof(u64)) - 1;
846 type = session->sample_type;
847
848 if (type & PERF_SAMPLE_CPU) {
849 u32 *p = (u32 *)array;
850 sample->cpu = *p;
851 array--;
852 }
853
854 if (type & PERF_SAMPLE_STREAM_ID) {
855 sample->stream_id = *array;
856 array--;
857 }
858
859 if (type & PERF_SAMPLE_ID) {
860 sample->id = *array;
861 array--;
862 }
863
864 if (type & PERF_SAMPLE_TIME) {
865 sample->time = *array;
866 array--;
867 }
868
869 if (type & PERF_SAMPLE_TID) {
870 u32 *p = (u32 *)array;
871 sample->pid = p[0];
872 sample->tid = p[1];
873 }
874
875 return 0;
876}
877
878int event__parse_sample(const event_t *event, struct perf_session *session,
879 struct sample_data *data)
880{
881 const u64 *array;
882 u64 type;
883
884 if (event->header.type != PERF_RECORD_SAMPLE)
885 return event__parse_id_sample(event, session, data);
886
887 array = event->sample.array;
888 type = session->sample_type;
772 889
773 if (type & PERF_SAMPLE_IP) { 890 if (type & PERF_SAMPLE_IP) {
774 data->ip = event->ip.ip; 891 data->ip = event->ip.ip;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8e790dae7026..2b7e91902f10 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -85,6 +85,7 @@ struct build_id_event {
85}; 85};
86 86
87enum perf_user_event_type { /* above any possible kernel type */ 87enum perf_user_event_type { /* above any possible kernel type */
88 PERF_RECORD_USER_TYPE_START = 64,
88 PERF_RECORD_HEADER_ATTR = 64, 89 PERF_RECORD_HEADER_ATTR = 64,
89 PERF_RECORD_HEADER_EVENT_TYPE = 65, 90 PERF_RECORD_HEADER_EVENT_TYPE = 65,
90 PERF_RECORD_HEADER_TRACING_DATA = 66, 91 PERF_RECORD_HEADER_TRACING_DATA = 66,
@@ -135,12 +136,15 @@ void event__print_totals(void);
135 136
136struct perf_session; 137struct perf_session;
137 138
138typedef int (*event__handler_t)(event_t *event, struct perf_session *session); 139typedef int (*event__handler_synth_t)(event_t *event,
140 struct perf_session *session);
141typedef int (*event__handler_t)(event_t *event, struct sample_data *sample,
142 struct perf_session *session);
139 143
140int event__synthesize_thread(pid_t pid, event__handler_t process, 144int event__synthesize_thread(pid_t pid, event__handler_t process,
141 struct perf_session *session); 145 struct perf_session *session);
142void event__synthesize_threads(event__handler_t process, 146int event__synthesize_threads(event__handler_t process,
143 struct perf_session *session); 147 struct perf_session *session);
144int event__synthesize_kernel_mmap(event__handler_t process, 148int event__synthesize_kernel_mmap(event__handler_t process,
145 struct perf_session *session, 149 struct perf_session *session,
146 struct machine *machine, 150 struct machine *machine,
@@ -150,18 +154,24 @@ int event__synthesize_modules(event__handler_t process,
150 struct perf_session *session, 154 struct perf_session *session,
151 struct machine *machine); 155 struct machine *machine);
152 156
153int event__process_comm(event_t *self, struct perf_session *session); 157int event__process_comm(event_t *self, struct sample_data *sample,
154int event__process_lost(event_t *self, struct perf_session *session); 158 struct perf_session *session);
155int event__process_mmap(event_t *self, struct perf_session *session); 159int event__process_lost(event_t *self, struct sample_data *sample,
156int event__process_task(event_t *self, struct perf_session *session); 160 struct perf_session *session);
157int event__process(event_t *event, struct perf_session *session); 161int event__process_mmap(event_t *self, struct sample_data *sample,
162 struct perf_session *session);
163int event__process_task(event_t *self, struct sample_data *sample,
164 struct perf_session *session);
165int event__process(event_t *event, struct sample_data *sample,
166 struct perf_session *session);
158 167
159struct addr_location; 168struct addr_location;
160int event__preprocess_sample(const event_t *self, struct perf_session *session, 169int event__preprocess_sample(const event_t *self, struct perf_session *session,
161 struct addr_location *al, struct sample_data *data, 170 struct addr_location *al, struct sample_data *data,
162 symbol_filter_t filter); 171 symbol_filter_t filter);
163int event__parse_sample(const event_t *event, u64 type, struct sample_data *data); 172int event__parse_sample(const event_t *event, struct perf_session *session,
173 struct sample_data *sample);
164 174
165extern const char *event__name[]; 175const char *event__get_event_name(unsigned int id);
166 176
167#endif /* __PERF_RECORD_H */ 177#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
new file mode 100644
index 000000000000..f5cfed60af98
--- /dev/null
+++ b/tools/perf/util/evsel.c
@@ -0,0 +1,201 @@
1#include "evsel.h"
2#include "../perf.h"
3#include "util.h"
4#include "cpumap.h"
5#include "thread.h"
6
7#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
8
9struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
10{
11 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
12
13 if (evsel != NULL) {
14 evsel->idx = idx;
15 evsel->attr = *attr;
16 INIT_LIST_HEAD(&evsel->node);
17 }
18
19 return evsel;
20}
21
22int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
23{
24 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
25 return evsel->fd != NULL ? 0 : -ENOMEM;
26}
27
28int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
29{
30 evsel->counts = zalloc((sizeof(*evsel->counts) +
31 (ncpus * sizeof(struct perf_counts_values))));
32 return evsel->counts != NULL ? 0 : -ENOMEM;
33}
34
35void perf_evsel__free_fd(struct perf_evsel *evsel)
36{
37 xyarray__delete(evsel->fd);
38 evsel->fd = NULL;
39}
40
41void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
42{
43 int cpu, thread;
44
45 for (cpu = 0; cpu < ncpus; cpu++)
46 for (thread = 0; thread < nthreads; ++thread) {
47 close(FD(evsel, cpu, thread));
48 FD(evsel, cpu, thread) = -1;
49 }
50}
51
52void perf_evsel__delete(struct perf_evsel *evsel)
53{
54 assert(list_empty(&evsel->node));
55 xyarray__delete(evsel->fd);
56 free(evsel);
57}
58
59int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
60 int cpu, int thread, bool scale)
61{
62 struct perf_counts_values count;
63 size_t nv = scale ? 3 : 1;
64
65 if (FD(evsel, cpu, thread) < 0)
66 return -EINVAL;
67
68 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
69 return -ENOMEM;
70
71 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
72 return -errno;
73
74 if (scale) {
75 if (count.run == 0)
76 count.val = 0;
77 else if (count.run < count.ena)
78 count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
79 } else
80 count.ena = count.run = 0;
81
82 evsel->counts->cpu[cpu] = count;
83 return 0;
84}
85
86int __perf_evsel__read(struct perf_evsel *evsel,
87 int ncpus, int nthreads, bool scale)
88{
89 size_t nv = scale ? 3 : 1;
90 int cpu, thread;
91 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
92
93 aggr->val = 0;
94
95 for (cpu = 0; cpu < ncpus; cpu++) {
96 for (thread = 0; thread < nthreads; thread++) {
97 if (FD(evsel, cpu, thread) < 0)
98 continue;
99
100 if (readn(FD(evsel, cpu, thread),
101 &count, nv * sizeof(u64)) < 0)
102 return -errno;
103
104 aggr->val += count.val;
105 if (scale) {
106 aggr->ena += count.ena;
107 aggr->run += count.run;
108 }
109 }
110 }
111
112 evsel->counts->scaled = 0;
113 if (scale) {
114 if (aggr->run == 0) {
115 evsel->counts->scaled = -1;
116 aggr->val = 0;
117 return 0;
118 }
119
120 if (aggr->run < aggr->ena) {
121 evsel->counts->scaled = 1;
122 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
123 }
124 } else
125 aggr->ena = aggr->run = 0;
126
127 return 0;
128}
129
130static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
131 struct thread_map *threads)
132{
133 int cpu, thread;
134
135 if (evsel->fd == NULL &&
136 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
137 return -1;
138
139 for (cpu = 0; cpu < cpus->nr; cpu++) {
140 for (thread = 0; thread < threads->nr; thread++) {
141 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
142 threads->map[thread],
143 cpus->map[cpu], -1, 0);
144 if (FD(evsel, cpu, thread) < 0)
145 goto out_close;
146 }
147 }
148
149 return 0;
150
151out_close:
152 do {
153 while (--thread >= 0) {
154 close(FD(evsel, cpu, thread));
155 FD(evsel, cpu, thread) = -1;
156 }
157 thread = threads->nr;
158 } while (--cpu >= 0);
159 return -1;
160}
161
162static struct {
163 struct cpu_map map;
164 int cpus[1];
165} empty_cpu_map = {
166 .map.nr = 1,
167 .cpus = { -1, },
168};
169
170static struct {
171 struct thread_map map;
172 int threads[1];
173} empty_thread_map = {
174 .map.nr = 1,
175 .threads = { -1, },
176};
177
178int perf_evsel__open(struct perf_evsel *evsel,
179 struct cpu_map *cpus, struct thread_map *threads)
180{
181
182 if (cpus == NULL) {
183 /* Work around old compiler warnings about strict aliasing */
184 cpus = &empty_cpu_map.map;
185 }
186
187 if (threads == NULL)
188 threads = &empty_thread_map.map;
189
190 return __perf_evsel__open(evsel, cpus, threads);
191}
192
193int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus)
194{
195 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map);
196}
197
198int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads)
199{
200 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
201}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
new file mode 100644
index 000000000000..b2d755fe88a5
--- /dev/null
+++ b/tools/perf/util/evsel.h
@@ -0,0 +1,115 @@
1#ifndef __PERF_EVSEL_H
2#define __PERF_EVSEL_H 1
3
4#include <linux/list.h>
5#include <stdbool.h>
6#include "../../../include/linux/perf_event.h"
7#include "types.h"
8#include "xyarray.h"
9
10struct perf_counts_values {
11 union {
12 struct {
13 u64 val;
14 u64 ena;
15 u64 run;
16 };
17 u64 values[3];
18 };
19};
20
21struct perf_counts {
22 s8 scaled;
23 struct perf_counts_values aggr;
24 struct perf_counts_values cpu[];
25};
26
27struct perf_evsel {
28 struct list_head node;
29 struct perf_event_attr attr;
30 char *filter;
31 struct xyarray *fd;
32 struct perf_counts *counts;
33 int idx;
34 void *priv;
35};
36
37struct cpu_map;
38struct thread_map;
39
40struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
41void perf_evsel__delete(struct perf_evsel *evsel);
42
43int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
44int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
45void perf_evsel__free_fd(struct perf_evsel *evsel);
46void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
47
48int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus);
49int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads);
50int perf_evsel__open(struct perf_evsel *evsel,
51 struct cpu_map *cpus, struct thread_map *threads);
52
53#define perf_evsel__match(evsel, t, c) \
54 (evsel->attr.type == PERF_TYPE_##t && \
55 evsel->attr.config == PERF_COUNT_##c)
56
57int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
58 int cpu, int thread, bool scale);
59
60/**
61 * perf_evsel__read_on_cpu - Read out the results on a CPU and thread
62 *
63 * @evsel - event selector to read value
64 * @cpu - CPU of interest
65 * @thread - thread of interest
66 */
67static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel,
68 int cpu, int thread)
69{
70 return __perf_evsel__read_on_cpu(evsel, cpu, thread, false);
71}
72
73/**
74 * perf_evsel__read_on_cpu_scaled - Read out the results on a CPU and thread, scaled
75 *
76 * @evsel - event selector to read value
77 * @cpu - CPU of interest
78 * @thread - thread of interest
79 */
80static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
81 int cpu, int thread)
82{
83 return __perf_evsel__read_on_cpu(evsel, cpu, thread, true);
84}
85
86int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads,
87 bool scale);
88
89/**
90 * perf_evsel__read - Read the aggregate results on all CPUs
91 *
92 * @evsel - event selector to read value
93 * @ncpus - Number of cpus affected, from zero
94 * @nthreads - Number of threads affected, from zero
95 */
96static inline int perf_evsel__read(struct perf_evsel *evsel,
97 int ncpus, int nthreads)
98{
99 return __perf_evsel__read(evsel, ncpus, nthreads, false);
100}
101
102/**
103 * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled
104 *
105 * @evsel - event selector to read value
106 * @ncpus - Number of cpus affected, from zero
107 * @nthreads - Number of threads affected, from zero
108 */
109static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
110 int ncpus, int nthreads)
111{
112 return __perf_evsel__read(evsel, ncpus, nthreads, true);
113}
114
115#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index d7e67b167ea3..f6a929e74981 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -152,6 +152,11 @@ void perf_header__set_feat(struct perf_header *self, int feat)
152 set_bit(feat, self->adds_features); 152 set_bit(feat, self->adds_features);
153} 153}
154 154
155void perf_header__clear_feat(struct perf_header *self, int feat)
156{
157 clear_bit(feat, self->adds_features);
158}
159
155bool perf_header__has_feat(const struct perf_header *self, int feat) 160bool perf_header__has_feat(const struct perf_header *self, int feat)
156{ 161{
157 return test_bit(feat, self->adds_features); 162 return test_bit(feat, self->adds_features);
@@ -265,15 +270,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
265 const char *name, bool is_kallsyms) 270 const char *name, bool is_kallsyms)
266{ 271{
267 const size_t size = PATH_MAX; 272 const size_t size = PATH_MAX;
268 char *filename = malloc(size), 273 char *realname = realpath(name, NULL),
274 *filename = malloc(size),
269 *linkname = malloc(size), *targetname; 275 *linkname = malloc(size), *targetname;
270 int len, err = -1; 276 int len, err = -1;
271 277
272 if (filename == NULL || linkname == NULL) 278 if (realname == NULL || filename == NULL || linkname == NULL)
273 goto out_free; 279 goto out_free;
274 280
275 len = snprintf(filename, size, "%s%s%s", 281 len = snprintf(filename, size, "%s%s%s",
276 debugdir, is_kallsyms ? "/" : "", name); 282 debugdir, is_kallsyms ? "/" : "", realname);
277 if (mkdir_p(filename, 0755)) 283 if (mkdir_p(filename, 0755))
278 goto out_free; 284 goto out_free;
279 285
@@ -283,7 +289,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
283 if (is_kallsyms) { 289 if (is_kallsyms) {
284 if (copyfile("/proc/kallsyms", filename)) 290 if (copyfile("/proc/kallsyms", filename))
285 goto out_free; 291 goto out_free;
286 } else if (link(name, filename) && copyfile(name, filename)) 292 } else if (link(realname, filename) && copyfile(name, filename))
287 goto out_free; 293 goto out_free;
288 } 294 }
289 295
@@ -300,6 +306,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
300 if (symlink(targetname, linkname) == 0) 306 if (symlink(targetname, linkname) == 0)
301 err = 0; 307 err = 0;
302out_free: 308out_free:
309 free(realname);
303 free(filename); 310 free(filename);
304 free(linkname); 311 free(linkname);
305 return err; 312 return err;
@@ -431,8 +438,10 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
431 int idx = 0, err; 438 int idx = 0, err;
432 439
433 session = container_of(self, struct perf_session, header); 440 session = container_of(self, struct perf_session, header);
434 if (perf_session__read_build_ids(session, true)) 441
435 perf_header__set_feat(self, HEADER_BUILD_ID); 442 if (perf_header__has_feat(self, HEADER_BUILD_ID &&
443 !perf_session__read_build_ids(session, true)))
444 perf_header__clear_feat(self, HEADER_BUILD_ID);
436 445
437 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 446 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
438 if (!nr_sections) 447 if (!nr_sections)
@@ -454,7 +463,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
454 463
455 /* Write trace info */ 464 /* Write trace info */
456 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 465 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
457 read_tracing_data(fd, attrs, nr_counters); 466 read_tracing_data(fd, &evsel_list);
458 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 467 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
459 } 468 }
460 469
@@ -597,7 +606,7 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
597static int perf_header__getbuffer64(struct perf_header *self, 606static int perf_header__getbuffer64(struct perf_header *self,
598 int fd, void *buf, size_t size) 607 int fd, void *buf, size_t size)
599{ 608{
600 if (do_read(fd, buf, size) <= 0) 609 if (readn(fd, buf, size) <= 0)
601 return -1; 610 return -1;
602 611
603 if (self->needs_swap) 612 if (self->needs_swap)
@@ -653,7 +662,7 @@ int perf_file_header__read(struct perf_file_header *self,
653{ 662{
654 lseek(fd, 0, SEEK_SET); 663 lseek(fd, 0, SEEK_SET);
655 664
656 if (do_read(fd, self, sizeof(*self)) <= 0 || 665 if (readn(fd, self, sizeof(*self)) <= 0 ||
657 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 666 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
658 return -1; 667 return -1;
659 668
@@ -789,8 +798,8 @@ static int perf_file_section__process(struct perf_file_section *self,
789 int feat, int fd) 798 int feat, int fd)
790{ 799{
791 if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) { 800 if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) {
792 pr_debug("Failed to lseek to %Ld offset for feature %d, " 801 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
793 "continuing...\n", self->offset, feat); 802 "%d, continuing...\n", self->offset, feat);
794 return 0; 803 return 0;
795 } 804 }
796 805
@@ -814,7 +823,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
814 struct perf_header *ph, int fd, 823 struct perf_header *ph, int fd,
815 bool repipe) 824 bool repipe)
816{ 825{
817 if (do_read(fd, self, sizeof(*self)) <= 0 || 826 if (readn(fd, self, sizeof(*self)) <= 0 ||
818 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 827 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
819 return -1; 828 return -1;
820 829
@@ -939,6 +948,24 @@ u64 perf_header__sample_type(struct perf_header *header)
939 return type; 948 return type;
940} 949}
941 950
951bool perf_header__sample_id_all(const struct perf_header *header)
952{
953 bool value = false, first = true;
954 int i;
955
956 for (i = 0; i < header->attrs; i++) {
957 struct perf_header_attr *attr = header->attr[i];
958
959 if (first) {
960 value = attr->attr.sample_id_all;
961 first = false;
962 } else if (value != attr->attr.sample_id_all)
963 die("non matching sample_id_all");
964 }
965
966 return value;
967}
968
942struct perf_event_attr * 969struct perf_event_attr *
943perf_header__find_attr(u64 id, struct perf_header *header) 970perf_header__find_attr(u64 id, struct perf_header *header)
944{ 971{
@@ -946,11 +973,16 @@ perf_header__find_attr(u64 id, struct perf_header *header)
946 973
947 /* 974 /*
948 * We set id to -1 if the data file doesn't contain sample 975 * We set id to -1 if the data file doesn't contain sample
949 * ids. Check for this and avoid walking through the entire 976 * ids. This can happen when the data file contains one type
950 * list of ids which may be large. 977 * of event and in that case, the header can still store the
978 * event attribute information. Check for this and avoid
979 * walking through the entire list of ids which may be large.
951 */ 980 */
952 if (id == -1ULL) 981 if (id == -1ULL) {
982 if (header->attrs > 0)
983 return &header->attr[0]->attr;
953 return NULL; 984 return NULL;
985 }
954 986
955 for (i = 0; i < header->attrs; i++) { 987 for (i = 0; i < header->attrs; i++) {
956 struct perf_header_attr *attr = header->attr[i]; 988 struct perf_header_attr *attr = header->attr[i];
@@ -980,21 +1012,23 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
980 1012
981 ev = malloc(size); 1013 ev = malloc(size);
982 1014
1015 if (ev == NULL)
1016 return -ENOMEM;
1017
983 ev->attr.attr = *attr; 1018 ev->attr.attr = *attr;
984 memcpy(ev->attr.id, id, ids * sizeof(u64)); 1019 memcpy(ev->attr.id, id, ids * sizeof(u64));
985 1020
986 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 1021 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
987 ev->attr.header.size = size; 1022 ev->attr.header.size = size;
988 1023
989 err = process(ev, session); 1024 err = process(ev, NULL, session);
990 1025
991 free(ev); 1026 free(ev);
992 1027
993 return err; 1028 return err;
994} 1029}
995 1030
996int event__synthesize_attrs(struct perf_header *self, 1031int event__synthesize_attrs(struct perf_header *self, event__handler_t process,
997 event__handler_t process,
998 struct perf_session *session) 1032 struct perf_session *session)
999{ 1033{
1000 struct perf_header_attr *attr; 1034 struct perf_header_attr *attr;
@@ -1064,7 +1098,7 @@ int event__synthesize_event_type(u64 event_id, char *name,
1064 ev.event_type.header.size = sizeof(ev.event_type) - 1098 ev.event_type.header.size = sizeof(ev.event_type) -
1065 (sizeof(ev.event_type.event_type.name) - size); 1099 (sizeof(ev.event_type.event_type.name) - size);
1066 1100
1067 err = process(&ev, session); 1101 err = process(&ev, NULL, session);
1068 1102
1069 return err; 1103 return err;
1070} 1104}
@@ -1099,8 +1133,7 @@ int event__process_event_type(event_t *self,
1099 return 0; 1133 return 0;
1100} 1134}
1101 1135
1102int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, 1136int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
1103 int nb_events,
1104 event__handler_t process, 1137 event__handler_t process,
1105 struct perf_session *session __unused) 1138 struct perf_session *session __unused)
1106{ 1139{
@@ -1111,7 +1144,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1111 memset(&ev, 0, sizeof(ev)); 1144 memset(&ev, 0, sizeof(ev));
1112 1145
1113 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 1146 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
1114 size = read_tracing_data_size(fd, pattrs, nb_events); 1147 size = read_tracing_data_size(fd, pattrs);
1115 if (size <= 0) 1148 if (size <= 0)
1116 return size; 1149 return size;
1117 aligned_size = ALIGN(size, sizeof(u64)); 1150 aligned_size = ALIGN(size, sizeof(u64));
@@ -1119,9 +1152,9 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1119 ev.tracing_data.header.size = sizeof(ev.tracing_data); 1152 ev.tracing_data.header.size = sizeof(ev.tracing_data);
1120 ev.tracing_data.size = aligned_size; 1153 ev.tracing_data.size = aligned_size;
1121 1154
1122 process(&ev, session); 1155 process(&ev, NULL, session);
1123 1156
1124 err = read_tracing_data(fd, pattrs, nb_events); 1157 err = read_tracing_data(fd, pattrs);
1125 write_padded(fd, NULL, 0, padding); 1158 write_padded(fd, NULL, 0, padding);
1126 1159
1127 return aligned_size; 1160 return aligned_size;
@@ -1179,7 +1212,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
1179 ev.build_id.header.size = sizeof(ev.build_id) + len; 1212 ev.build_id.header.size = sizeof(ev.build_id) + len;
1180 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 1213 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
1181 1214
1182 err = process(&ev, session); 1215 err = process(&ev, NULL, session);
1183 1216
1184 return err; 1217 return err;
1185} 1218}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 402ac2454cf8..33f16be7b72f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -81,9 +81,11 @@ void perf_header_attr__delete(struct perf_header_attr *self);
81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id); 81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
82 82
83u64 perf_header__sample_type(struct perf_header *header); 83u64 perf_header__sample_type(struct perf_header *header);
84bool perf_header__sample_id_all(const struct perf_header *header);
84struct perf_event_attr * 85struct perf_event_attr *
85perf_header__find_attr(u64 id, struct perf_header *header); 86perf_header__find_attr(u64 id, struct perf_header *header);
86void perf_header__set_feat(struct perf_header *self, int feat); 87void perf_header__set_feat(struct perf_header *self, int feat);
88void perf_header__clear_feat(struct perf_header *self, int feat);
87bool perf_header__has_feat(const struct perf_header *self, int feat); 89bool perf_header__has_feat(const struct perf_header *self, int feat);
88 90
89int perf_header__process_sections(struct perf_header *self, int fd, 91int perf_header__process_sections(struct perf_header *self, int fd,
@@ -111,8 +113,7 @@ int event__synthesize_event_types(event__handler_t process,
111int event__process_event_type(event_t *self, 113int event__process_event_type(event_t *self,
112 struct perf_session *session); 114 struct perf_session *session);
113 115
114int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, 116int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
115 int nb_events,
116 event__handler_t process, 117 event__handler_t process,
117 struct perf_session *session); 118 struct perf_session *session);
118int event__process_tracing_data(event_t *self, 119int event__process_tracing_data(event_t *self,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 2022e8740994..32f4f1f2f6e4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -356,7 +356,7 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
356 356
357static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, 357static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
358 int depth, int depth_mask, int period, 358 int depth, int depth_mask, int period,
359 u64 total_samples, int hits, 359 u64 total_samples, u64 hits,
360 int left_margin) 360 int left_margin)
361{ 361{
362 int i; 362 int i;
@@ -636,13 +636,13 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
636 } 636 }
637 } 637 }
638 } else 638 } else
639 ret = snprintf(s, size, sep ? "%lld" : "%12lld ", period); 639 ret = snprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
640 640
641 if (symbol_conf.show_nr_samples) { 641 if (symbol_conf.show_nr_samples) {
642 if (sep) 642 if (sep)
643 ret += snprintf(s + ret, size - ret, "%c%lld", *sep, period); 643 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
644 else 644 else
645 ret += snprintf(s + ret, size - ret, "%11lld", period); 645 ret += snprintf(s + ret, size - ret, "%11" PRIu64, period);
646 } 646 }
647 647
648 if (pair_hists) { 648 if (pair_hists) {
@@ -971,7 +971,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
971 sym_size = sym->end - sym->start; 971 sym_size = sym->end - sym->start;
972 offset = ip - sym->start; 972 offset = ip - sym->start;
973 973
974 pr_debug3("%s: ip=%#Lx\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip)); 974 pr_debug3("%s: ip=%#" PRIx64 "\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip));
975 975
976 if (offset >= sym_size) 976 if (offset >= sym_size)
977 return 0; 977 return 0;
@@ -980,8 +980,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
980 h->sum++; 980 h->sum++;
981 h->ip[offset]++; 981 h->ip[offset]++;
982 982
983 pr_debug3("%#Lx %s: period++ [ip: %#Lx, %#Lx] => %Ld\n", self->ms.sym->start, 983 pr_debug3("%#" PRIx64 " %s: period++ [ip: %#" PRIx64 ", %#" PRIx64
984 self->ms.sym->name, ip, ip - self->ms.sym->start, h->ip[offset]); 984 "] => %" PRIu64 "\n", self->ms.sym->start, self->ms.sym->name,
985 ip, ip - self->ms.sym->start, h->ip[offset]);
985 return 0; 986 return 0;
986} 987}
987 988
@@ -1092,6 +1093,12 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1092 FILE *file; 1093 FILE *file;
1093 int err = 0; 1094 int err = 0;
1094 u64 len; 1095 u64 len;
1096 char symfs_filename[PATH_MAX];
1097
1098 if (filename) {
1099 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1100 symbol_conf.symfs, filename);
1101 }
1095 1102
1096 if (filename == NULL) { 1103 if (filename == NULL) {
1097 if (dso->has_build_id) { 1104 if (dso->has_build_id) {
@@ -1100,9 +1107,9 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1100 return -ENOMEM; 1107 return -ENOMEM;
1101 } 1108 }
1102 goto fallback; 1109 goto fallback;
1103 } else if (readlink(filename, command, sizeof(command)) < 0 || 1110 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
1104 strstr(command, "[kernel.kallsyms]") || 1111 strstr(command, "[kernel.kallsyms]") ||
1105 access(filename, R_OK)) { 1112 access(symfs_filename, R_OK)) {
1106 free(filename); 1113 free(filename);
1107fallback: 1114fallback:
1108 /* 1115 /*
@@ -1111,6 +1118,8 @@ fallback:
1111 * DSO is the same as when 'perf record' ran. 1118 * DSO is the same as when 'perf record' ran.
1112 */ 1119 */
1113 filename = dso->long_name; 1120 filename = dso->long_name;
1121 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1122 symbol_conf.symfs, filename);
1114 free_filename = false; 1123 free_filename = false;
1115 } 1124 }
1116 1125
@@ -1124,7 +1133,7 @@ fallback:
1124 goto out_free_filename; 1133 goto out_free_filename;
1125 } 1134 }
1126 1135
1127 pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, 1136 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1128 filename, sym->name, map->unmap_ip(map, sym->start), 1137 filename, sym->name, map->unmap_ip(map, sym->start),
1129 map->unmap_ip(map, sym->end)); 1138 map->unmap_ip(map, sym->end));
1130 1139
@@ -1134,10 +1143,10 @@ fallback:
1134 dso, dso->long_name, sym, sym->name); 1143 dso, dso->long_name, sym, sym->name);
1135 1144
1136 snprintf(command, sizeof(command), 1145 snprintf(command, sizeof(command),
1137 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand", 1146 "objdump --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand",
1138 map__rip_2objdump(map, sym->start), 1147 map__rip_2objdump(map, sym->start),
1139 map__rip_2objdump(map, sym->end), 1148 map__rip_2objdump(map, sym->end),
1140 filename, filename); 1149 symfs_filename, filename);
1141 1150
1142 pr_debug("Executing: %s\n", command); 1151 pr_debug("Executing: %s\n", command);
1143 1152
@@ -1168,10 +1177,13 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
1168 size_t ret = 0; 1177 size_t ret = 0;
1169 1178
1170 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 1179 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
1171 if (!event__name[i]) 1180 const char *name = event__get_event_name(i);
1181
1182 if (!strcmp(name, "UNKNOWN"))
1172 continue; 1183 continue;
1173 ret += fprintf(fp, "%10s events: %10d\n", 1184
1174 event__name[i], self->stats.nr_events[i]); 1185 ret += fprintf(fp, "%16s events: %10d\n", name,
1186 self->stats.nr_events[i]);
1175 } 1187 }
1176 1188
1177 return ret; 1189 return ret;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 587d375d3430..ee789856a8c9 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,8 +52,10 @@ struct sym_priv {
52struct events_stats { 52struct events_stats {
53 u64 total_period; 53 u64 total_period;
54 u64 total_lost; 54 u64 total_lost;
55 u64 total_invalid_chains;
55 u32 nr_events[PERF_RECORD_HEADER_MAX]; 56 u32 nr_events[PERF_RECORD_HEADER_MAX];
56 u32 nr_unknown_events; 57 u32 nr_unknown_events;
58 u32 nr_invalid_chains;
57}; 59};
58 60
59enum hist_column { 61enum hist_column {
diff --git a/tools/perf/util/include/asm/cpufeature.h b/tools/perf/util/include/asm/cpufeature.h
new file mode 100644
index 000000000000..acffd5e4d1d4
--- /dev/null
+++ b/tools/perf/util/include/asm/cpufeature.h
@@ -0,0 +1,9 @@
1
2#ifndef PERF_CPUFEATURE_H
3#define PERF_CPUFEATURE_H
4
5/* cpufeature.h ... dummy header file for including arch/x86/lib/memcpy_64.S */
6
7#define X86_FEATURE_REP_GOOD 0
8
9#endif /* PERF_CPUFEATURE_H */
diff --git a/tools/perf/util/include/asm/dwarf2.h b/tools/perf/util/include/asm/dwarf2.h
new file mode 100644
index 000000000000..bb4198e7837a
--- /dev/null
+++ b/tools/perf/util/include/asm/dwarf2.h
@@ -0,0 +1,11 @@
1
2#ifndef PERF_DWARF2_H
3#define PERF_DWARF2_H
4
5/* dwarf2.h ... dummy header file for including arch/x86/lib/memcpy_64.S */
6
7#define CFI_STARTPROC
8#define CFI_ENDPROC
9
10#endif /* PERF_DWARF2_H */
11
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index bb4ac2e05385..305c8484f200 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -2,6 +2,7 @@
2#define _PERF_LINUX_BITOPS_H_ 2#define _PERF_LINUX_BITOPS_H_
3 3
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <linux/compiler.h>
5#include <asm/hweight.h> 6#include <asm/hweight.h>
6 7
7#define BITS_PER_LONG __WORDSIZE 8#define BITS_PER_LONG __WORDSIZE
@@ -13,6 +14,11 @@ static inline void set_bit(int nr, unsigned long *addr)
13 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); 14 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
14} 15}
15 16
17static inline void clear_bit(int nr, unsigned long *addr)
18{
19 addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
20}
21
16static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) 22static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
17{ 23{
18 return ((1UL << (nr % BITS_PER_LONG)) & 24 return ((1UL << (nr % BITS_PER_LONG)) &
diff --git a/tools/perf/util/include/linux/linkage.h b/tools/perf/util/include/linux/linkage.h
new file mode 100644
index 000000000000..06387cffe125
--- /dev/null
+++ b/tools/perf/util/include/linux/linkage.h
@@ -0,0 +1,13 @@
1
2#ifndef PERF_LINUX_LINKAGE_H_
3#define PERF_LINUX_LINKAGE_H_
4
5/* linkage.h ... for including arch/x86/lib/memcpy_64.S */
6
7#define ENTRY(name) \
8 .globl name; \
9 name:
10
11#define ENDPROC(name)
12
13#endif /* PERF_LINUX_LINKAGE_H_ */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 3a7eb6ec0eec..a16ecab5229d 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -1,5 +1,6 @@
1#include "symbol.h" 1#include "symbol.h"
2#include <errno.h> 2#include <errno.h>
3#include <inttypes.h>
3#include <limits.h> 4#include <limits.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <string.h> 6#include <string.h>
@@ -195,7 +196,7 @@ int map__overlap(struct map *l, struct map *r)
195 196
196size_t map__fprintf(struct map *self, FILE *fp) 197size_t map__fprintf(struct map *self, FILE *fp)
197{ 198{
198 return fprintf(fp, " %Lx-%Lx %Lx %s\n", 199 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
199 self->start, self->end, self->pgoff, self->dso->name); 200 self->start, self->end, self->pgoff, self->dso->name);
200} 201}
201 202
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4af5bd59cfd1..135f69baf966 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,6 +1,7 @@
1#include "../../../include/linux/hw_breakpoint.h" 1#include "../../../include/linux/hw_breakpoint.h"
2#include "util.h" 2#include "util.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "evsel.h"
4#include "parse-options.h" 5#include "parse-options.h"
5#include "parse-events.h" 6#include "parse-events.h"
6#include "exec_cmd.h" 7#include "exec_cmd.h"
@@ -12,8 +13,7 @@
12 13
13int nr_counters; 14int nr_counters;
14 15
15struct perf_event_attr attrs[MAX_COUNTERS]; 16LIST_HEAD(evsel_list);
16char *filters[MAX_COUNTERS];
17 17
18struct event_symbol { 18struct event_symbol {
19 u8 type; 19 u8 type;
@@ -266,10 +266,10 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
266 return name; 266 return name;
267} 267}
268 268
269const char *event_name(int counter) 269const char *event_name(struct perf_evsel *evsel)
270{ 270{
271 u64 config = attrs[counter].config; 271 u64 config = evsel->attr.config;
272 int type = attrs[counter].type; 272 int type = evsel->attr.type;
273 273
274 return __event_name(type, config); 274 return __event_name(type, config);
275} 275}
@@ -279,7 +279,7 @@ const char *__event_name(int type, u64 config)
279 static char buf[32]; 279 static char buf[32];
280 280
281 if (type == PERF_TYPE_RAW) { 281 if (type == PERF_TYPE_RAW) {
282 sprintf(buf, "raw 0x%llx", config); 282 sprintf(buf, "raw 0x%" PRIx64, config);
283 return buf; 283 return buf;
284 } 284 }
285 285
@@ -434,7 +434,7 @@ parse_single_tracepoint_event(char *sys_name,
434 id = atoll(id_buf); 434 id = atoll(id_buf);
435 attr->config = id; 435 attr->config = id;
436 attr->type = PERF_TYPE_TRACEPOINT; 436 attr->type = PERF_TYPE_TRACEPOINT;
437 *strp = evt_name + evt_length; 437 *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
438 438
439 attr->sample_type |= PERF_SAMPLE_RAW; 439 attr->sample_type |= PERF_SAMPLE_RAW;
440 attr->sample_type |= PERF_SAMPLE_TIME; 440 attr->sample_type |= PERF_SAMPLE_TIME;
@@ -490,12 +490,11 @@ parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
490 return EVT_HANDLED_ALL; 490 return EVT_HANDLED_ALL;
491} 491}
492 492
493
494static enum event_result parse_tracepoint_event(const char **strp, 493static enum event_result parse_tracepoint_event(const char **strp,
495 struct perf_event_attr *attr) 494 struct perf_event_attr *attr)
496{ 495{
497 const char *evt_name; 496 const char *evt_name;
498 char *flags; 497 char *flags = NULL, *comma_loc;
499 char sys_name[MAX_EVENT_LENGTH]; 498 char sys_name[MAX_EVENT_LENGTH];
500 unsigned int sys_length, evt_length; 499 unsigned int sys_length, evt_length;
501 500
@@ -514,6 +513,11 @@ static enum event_result parse_tracepoint_event(const char **strp,
514 sys_name[sys_length] = '\0'; 513 sys_name[sys_length] = '\0';
515 evt_name = evt_name + 1; 514 evt_name = evt_name + 1;
516 515
516 comma_loc = strchr(evt_name, ',');
517 if (comma_loc) {
518 /* take the event name up to the comma */
519 evt_name = strndup(evt_name, comma_loc - evt_name);
520 }
517 flags = strchr(evt_name, ':'); 521 flags = strchr(evt_name, ':');
518 if (flags) { 522 if (flags) {
519 /* split it out: */ 523 /* split it out: */
@@ -524,14 +528,14 @@ static enum event_result parse_tracepoint_event(const char **strp,
524 evt_length = strlen(evt_name); 528 evt_length = strlen(evt_name);
525 if (evt_length >= MAX_EVENT_LENGTH) 529 if (evt_length >= MAX_EVENT_LENGTH)
526 return EVT_FAILED; 530 return EVT_FAILED;
527
528 if (strpbrk(evt_name, "*?")) { 531 if (strpbrk(evt_name, "*?")) {
529 *strp = evt_name + evt_length; 532 *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
530 return parse_multiple_tracepoint_event(sys_name, evt_name, 533 return parse_multiple_tracepoint_event(sys_name, evt_name,
531 flags); 534 flags);
532 } else 535 } else {
533 return parse_single_tracepoint_event(sys_name, evt_name, 536 return parse_single_tracepoint_event(sys_name, evt_name,
534 evt_length, attr, strp); 537 evt_length, attr, strp);
538 }
535} 539}
536 540
537static enum event_result 541static enum event_result
@@ -774,45 +778,12 @@ modifier:
774 return ret; 778 return ret;
775} 779}
776 780
777static int store_event_type(const char *orgname)
778{
779 char filename[PATH_MAX], *c;
780 FILE *file;
781 int id, n;
782
783 sprintf(filename, "%s/", debugfs_path);
784 strncat(filename, orgname, strlen(orgname));
785 strcat(filename, "/id");
786
787 c = strchr(filename, ':');
788 if (c)
789 *c = '/';
790
791 file = fopen(filename, "r");
792 if (!file)
793 return 0;
794 n = fscanf(file, "%i", &id);
795 fclose(file);
796 if (n < 1) {
797 pr_err("cannot store event ID\n");
798 return -EINVAL;
799 }
800 return perf_header__push_event(id, orgname);
801}
802
803int parse_events(const struct option *opt __used, const char *str, int unset __used) 781int parse_events(const struct option *opt __used, const char *str, int unset __used)
804{ 782{
805 struct perf_event_attr attr; 783 struct perf_event_attr attr;
806 enum event_result ret; 784 enum event_result ret;
807 785
808 if (strchr(str, ':'))
809 if (store_event_type(str) < 0)
810 return -1;
811
812 for (;;) { 786 for (;;) {
813 if (nr_counters == MAX_COUNTERS)
814 return -1;
815
816 memset(&attr, 0, sizeof(attr)); 787 memset(&attr, 0, sizeof(attr));
817 ret = parse_event_symbols(&str, &attr); 788 ret = parse_event_symbols(&str, &attr);
818 if (ret == EVT_FAILED) 789 if (ret == EVT_FAILED)
@@ -822,8 +793,13 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
822 return -1; 793 return -1;
823 794
824 if (ret != EVT_HANDLED_ALL) { 795 if (ret != EVT_HANDLED_ALL) {
825 attrs[nr_counters] = attr; 796 struct perf_evsel *evsel;
826 nr_counters++; 797 evsel = perf_evsel__new(&attr,
798 nr_counters);
799 if (evsel == NULL)
800 return -1;
801 list_add_tail(&evsel->node, &evsel_list);
802 ++nr_counters;
827 } 803 }
828 804
829 if (*str == 0) 805 if (*str == 0)
@@ -840,21 +816,22 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
840int parse_filter(const struct option *opt __used, const char *str, 816int parse_filter(const struct option *opt __used, const char *str,
841 int unset __used) 817 int unset __used)
842{ 818{
843 int i = nr_counters - 1; 819 struct perf_evsel *last = NULL;
844 int len = strlen(str); 820
821 if (!list_empty(&evsel_list))
822 last = list_entry(evsel_list.prev, struct perf_evsel, node);
845 823
846 if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) { 824 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
847 fprintf(stderr, 825 fprintf(stderr,
848 "-F option should follow a -e tracepoint option\n"); 826 "-F option should follow a -e tracepoint option\n");
849 return -1; 827 return -1;
850 } 828 }
851 829
852 filters[i] = malloc(len + 1); 830 last->filter = strdup(str);
853 if (!filters[i]) { 831 if (last->filter == NULL) {
854 fprintf(stderr, "not enough memory to hold filter string\n"); 832 fprintf(stderr, "not enough memory to hold filter string\n");
855 return -1; 833 return -1;
856 } 834 }
857 strcpy(filters[i], str);
858 835
859 return 0; 836 return 0;
860} 837}
@@ -906,6 +883,47 @@ static void print_tracepoint_events(void)
906} 883}
907 884
908/* 885/*
886 * Check whether event is in <debugfs_mount_point>/tracing/events
887 */
888
889int is_valid_tracepoint(const char *event_string)
890{
891 DIR *sys_dir, *evt_dir;
892 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
893 char evt_path[MAXPATHLEN];
894 char dir_path[MAXPATHLEN];
895
896 if (debugfs_valid_mountpoint(debugfs_path))
897 return 0;
898
899 sys_dir = opendir(debugfs_path);
900 if (!sys_dir)
901 return 0;
902
903 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
904
905 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
906 sys_dirent.d_name);
907 evt_dir = opendir(dir_path);
908 if (!evt_dir)
909 continue;
910
911 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
912 snprintf(evt_path, MAXPATHLEN, "%s:%s",
913 sys_dirent.d_name, evt_dirent.d_name);
914 if (!strcmp(evt_path, event_string)) {
915 closedir(evt_dir);
916 closedir(sys_dir);
917 return 1;
918 }
919 }
920 closedir(evt_dir);
921 }
922 closedir(sys_dir);
923 return 0;
924}
925
926/*
909 * Print the help text for the event symbols: 927 * Print the help text for the event symbols:
910 */ 928 */
911void print_events(void) 929void print_events(void)
@@ -963,3 +981,33 @@ void print_events(void)
963 981
964 exit(129); 982 exit(129);
965} 983}
984
985int perf_evsel_list__create_default(void)
986{
987 struct perf_evsel *evsel;
988 struct perf_event_attr attr;
989
990 memset(&attr, 0, sizeof(attr));
991 attr.type = PERF_TYPE_HARDWARE;
992 attr.config = PERF_COUNT_HW_CPU_CYCLES;
993
994 evsel = perf_evsel__new(&attr, 0);
995
996 if (evsel == NULL)
997 return -ENOMEM;
998
999 list_add(&evsel->node, &evsel_list);
1000 ++nr_counters;
1001 return 0;
1002}
1003
1004void perf_evsel_list__delete(void)
1005{
1006 struct perf_evsel *pos, *n;
1007
1008 list_for_each_entry_safe(pos, n, &evsel_list, node) {
1009 list_del_init(&pos->node);
1010 perf_evsel__delete(pos);
1011 }
1012 nr_counters = 0;
1013}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index fc4ab3fe877a..458e3ecf17af 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -4,6 +4,16 @@
4 * Parse symbolic events/counts passed in as options: 4 * Parse symbolic events/counts passed in as options:
5 */ 5 */
6 6
7#include "../../../include/linux/perf_event.h"
8
9struct list_head;
10struct perf_evsel;
11
12extern struct list_head evsel_list;
13
14int perf_evsel_list__create_default(void);
15void perf_evsel_list__delete(void);
16
7struct option; 17struct option;
8 18
9struct tracepoint_path { 19struct tracepoint_path {
@@ -13,14 +23,11 @@ struct tracepoint_path {
13}; 23};
14 24
15extern struct tracepoint_path *tracepoint_id_to_path(u64 config); 25extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
16extern bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events); 26extern bool have_tracepoints(struct list_head *evlist);
17 27
18extern int nr_counters; 28extern int nr_counters;
19 29
20extern struct perf_event_attr attrs[MAX_COUNTERS]; 30const char *event_name(struct perf_evsel *event);
21extern char *filters[MAX_COUNTERS];
22
23extern const char *event_name(int ctr);
24extern const char *__event_name(int type, u64 config); 31extern const char *__event_name(int type, u64 config);
25 32
26extern int parse_events(const struct option *opt, const char *str, int unset); 33extern int parse_events(const struct option *opt, const char *str, int unset);
@@ -29,9 +36,9 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
29#define EVENTS_HELP_MAX (128*1024) 36#define EVENTS_HELP_MAX (128*1024)
30 37
31extern void print_events(void); 38extern void print_events(void);
39extern int is_valid_tracepoint(const char *event_string);
32 40
33extern char debugfs_path[]; 41extern char debugfs_path[];
34extern int valid_debugfs_mount(const char *debugfs); 42extern int valid_debugfs_mount(const char *debugfs);
35 43
36
37#endif /* __PERF_PARSE_EVENTS_H */ 44#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index c7d72dce54b2..abc31a1dac1a 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -119,6 +119,10 @@ struct option {
119 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG } 119 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
120#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ 120#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
121 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } 121 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
122#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
123 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
124 .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
125 .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
122 126
123/* parse_options() will filter out the processed options and leave the 127/* parse_options() will filter out the processed options and leave the
124 * non-option argments in argv[]. 128 * non-option argments in argv[].
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3b6a5297bf16..6e29d9c9dccc 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -95,7 +95,7 @@ static int init_vmlinux(void)
95 goto out; 95 goto out;
96 96
97 if (machine__create_kernel_maps(&machine) < 0) { 97 if (machine__create_kernel_maps(&machine) < 0) {
98 pr_debug("machine__create_kernel_maps "); 98 pr_debug("machine__create_kernel_maps() failed.\n");
99 goto out; 99 goto out;
100 } 100 }
101out: 101out:
@@ -114,6 +114,8 @@ static struct symbol *__find_kernel_function_by_name(const char *name,
114const char *kernel_get_module_path(const char *module) 114const char *kernel_get_module_path(const char *module)
115{ 115{
116 struct dso *dso; 116 struct dso *dso;
117 struct map *map;
118 const char *vmlinux_name;
117 119
118 if (module) { 120 if (module) {
119 list_for_each_entry(dso, &machine.kernel_dsos, node) { 121 list_for_each_entry(dso, &machine.kernel_dsos, node) {
@@ -123,10 +125,17 @@ const char *kernel_get_module_path(const char *module)
123 } 125 }
124 pr_debug("Failed to find module %s.\n", module); 126 pr_debug("Failed to find module %s.\n", module);
125 return NULL; 127 return NULL;
128 }
129
130 map = machine.vmlinux_maps[MAP__FUNCTION];
131 dso = map->dso;
132
133 vmlinux_name = symbol_conf.vmlinux_name;
134 if (vmlinux_name) {
135 if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
136 return NULL;
126 } else { 137 } else {
127 dso = machine.vmlinux_maps[MAP__FUNCTION]->dso; 138 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
128 if (dso__load_vmlinux_path(dso,
129 machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
130 pr_debug("Failed to load kernel map.\n"); 139 pr_debug("Failed to load kernel map.\n");
131 return NULL; 140 return NULL;
132 } 141 }
@@ -140,7 +149,8 @@ static int open_vmlinux(const char *module)
140{ 149{
141 const char *path = kernel_get_module_path(module); 150 const char *path = kernel_get_module_path(module);
142 if (!path) { 151 if (!path) {
143 pr_err("Failed to find path of %s module", module ?: "kernel"); 152 pr_err("Failed to find path of %s module.\n",
153 module ?: "kernel");
144 return -ENOENT; 154 return -ENOENT;
145 } 155 }
146 pr_debug("Try to open %s\n", path); 156 pr_debug("Try to open %s\n", path);
@@ -162,7 +172,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
162 sym = __find_kernel_function_by_name(tp->symbol, &map); 172 sym = __find_kernel_function_by_name(tp->symbol, &map);
163 if (sym) { 173 if (sym) {
164 addr = map->unmap_ip(map, sym->start + tp->offset); 174 addr = map->unmap_ip(map, sym->start + tp->offset);
165 pr_debug("try to find %s+%ld@%llx\n", tp->symbol, 175 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
166 tp->offset, addr); 176 tp->offset, addr);
167 ret = find_perf_probe_point((unsigned long)addr, pp); 177 ret = find_perf_probe_point((unsigned long)addr, pp);
168 } 178 }
@@ -217,7 +227,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
217 pr_warning("Warning: No dwarf info found in the vmlinux - " 227 pr_warning("Warning: No dwarf info found in the vmlinux - "
218 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 228 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
219 if (!need_dwarf) { 229 if (!need_dwarf) {
220 pr_debug("Trying to use symbols.\nn"); 230 pr_debug("Trying to use symbols.\n");
221 return 0; 231 return 0;
222 } 232 }
223 } 233 }
@@ -286,42 +296,49 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
286#define LINEBUF_SIZE 256 296#define LINEBUF_SIZE 256
287#define NR_ADDITIONAL_LINES 2 297#define NR_ADDITIONAL_LINES 2
288 298
289static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 299static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
290{ 300{
291 char buf[LINEBUF_SIZE]; 301 char buf[LINEBUF_SIZE];
292 const char *color = PERF_COLOR_BLUE; 302 const char *color = show_num ? "" : PERF_COLOR_BLUE;
293 303 const char *prefix = NULL;
294 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
295 goto error;
296 if (!skip) {
297 if (show_num)
298 fprintf(stdout, "%7d %s", l, buf);
299 else
300 color_fprintf(stdout, color, " %s", buf);
301 }
302 304
303 while (strlen(buf) == LINEBUF_SIZE - 1 && 305 do {
304 buf[LINEBUF_SIZE - 2] != '\n') {
305 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 306 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
306 goto error; 307 goto error;
307 if (!skip) { 308 if (skip)
308 if (show_num) 309 continue;
309 fprintf(stdout, "%s", buf); 310 if (!prefix) {
310 else 311 prefix = show_num ? "%7d " : " ";
311 color_fprintf(stdout, color, "%s", buf); 312 color_fprintf(stdout, color, prefix, l);
312 } 313 }
313 } 314 color_fprintf(stdout, color, "%s", buf);
314 315
315 return 0; 316 } while (strchr(buf, '\n') == NULL);
317
318 return 1;
316error: 319error:
317 if (feof(fp)) 320 if (ferror(fp)) {
318 pr_warning("Source file is shorter than expected.\n");
319 else
320 pr_warning("File read error: %s\n", strerror(errno)); 321 pr_warning("File read error: %s\n", strerror(errno));
322 return -1;
323 }
324 return 0;
325}
321 326
322 return -1; 327static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
328{
329 int rv = __show_one_line(fp, l, skip, show_num);
330 if (rv == 0) {
331 pr_warning("Source file is shorter than expected.\n");
332 rv = -1;
333 }
334 return rv;
323} 335}
324 336
337#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
338#define show_one_line(f,l) _show_one_line(f,l,false,false)
339#define skip_one_line(f,l) _show_one_line(f,l,true,false)
340#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
341
325/* 342/*
326 * Show line-range always requires debuginfo to find source file and 343 * Show line-range always requires debuginfo to find source file and
327 * line number. 344 * line number.
@@ -370,7 +387,7 @@ int show_line_range(struct line_range *lr, const char *module)
370 fprintf(stdout, "<%s:%d>\n", lr->function, 387 fprintf(stdout, "<%s:%d>\n", lr->function,
371 lr->start - lr->offset); 388 lr->start - lr->offset);
372 else 389 else
373 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 390 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
374 391
375 fp = fopen(lr->path, "r"); 392 fp = fopen(lr->path, "r");
376 if (fp == NULL) { 393 if (fp == NULL) {
@@ -379,26 +396,30 @@ int show_line_range(struct line_range *lr, const char *module)
379 return -errno; 396 return -errno;
380 } 397 }
381 /* Skip to starting line number */ 398 /* Skip to starting line number */
382 while (l < lr->start && ret >= 0) 399 while (l < lr->start) {
383 ret = show_one_line(fp, l++, true, false); 400 ret = skip_one_line(fp, l++);
384 if (ret < 0) 401 if (ret < 0)
385 goto end; 402 goto end;
403 }
386 404
387 list_for_each_entry(ln, &lr->line_list, list) { 405 list_for_each_entry(ln, &lr->line_list, list) {
388 while (ln->line > l && ret >= 0) 406 for (; ln->line > l; l++) {
389 ret = show_one_line(fp, (l++) - lr->offset, 407 ret = show_one_line(fp, l - lr->offset);
390 false, false); 408 if (ret < 0)
391 if (ret >= 0) 409 goto end;
392 ret = show_one_line(fp, (l++) - lr->offset, 410 }
393 false, true); 411 ret = show_one_line_with_num(fp, l++ - lr->offset);
394 if (ret < 0) 412 if (ret < 0)
395 goto end; 413 goto end;
396 } 414 }
397 415
398 if (lr->end == INT_MAX) 416 if (lr->end == INT_MAX)
399 lr->end = l + NR_ADDITIONAL_LINES; 417 lr->end = l + NR_ADDITIONAL_LINES;
400 while (l <= lr->end && !feof(fp) && ret >= 0) 418 while (l <= lr->end) {
401 ret = show_one_line(fp, (l++) - lr->offset, false, false); 419 ret = show_one_line_or_eof(fp, l++ - lr->offset);
420 if (ret <= 0)
421 break;
422 }
402end: 423end:
403 fclose(fp); 424 fclose(fp);
404 return ret; 425 return ret;
@@ -457,7 +478,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
457 478
458 fd = open_vmlinux(module); 479 fd = open_vmlinux(module);
459 if (fd < 0) { 480 if (fd < 0) {
460 pr_warning("Failed to open debuginfo file.\n"); 481 pr_warning("Failed to open debug information file.\n");
461 return fd; 482 return fd;
462 } 483 }
463 484
@@ -517,56 +538,87 @@ int show_available_vars(struct perf_probe_event *pevs __unused,
517} 538}
518#endif 539#endif
519 540
541static int parse_line_num(char **ptr, int *val, const char *what)
542{
543 const char *start = *ptr;
544
545 errno = 0;
546 *val = strtol(*ptr, ptr, 0);
547 if (errno || *ptr == start) {
548 semantic_error("'%s' is not a valid number.\n", what);
549 return -EINVAL;
550 }
551 return 0;
552}
553
554/*
555 * Stuff 'lr' according to the line range described by 'arg'.
556 * The line range syntax is described by:
557 *
558 * SRC[:SLN[+NUM|-ELN]]
559 * FNC[:SLN[+NUM|-ELN]]
560 */
520int parse_line_range_desc(const char *arg, struct line_range *lr) 561int parse_line_range_desc(const char *arg, struct line_range *lr)
521{ 562{
522 const char *ptr; 563 char *range, *name = strdup(arg);
523 char *tmp; 564 int err;
524 /* 565
525 * <Syntax> 566 if (!name)
526 * SRC:SLN[+NUM|-ELN] 567 return -ENOMEM;
527 * FUNC[:SLN[+NUM|-ELN]] 568
528 */ 569 lr->start = 0;
529 ptr = strchr(arg, ':'); 570 lr->end = INT_MAX;
530 if (ptr) { 571
531 lr->start = (int)strtoul(ptr + 1, &tmp, 0); 572 range = strchr(name, ':');
532 if (*tmp == '+') { 573 if (range) {
533 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 574 *range++ = '\0';
534 lr->end--; /* 575
535 * Adjust the number of lines here. 576 err = parse_line_num(&range, &lr->start, "start line");
536 * If the number of lines == 1, the 577 if (err)
537 * the end of line should be equal to 578 goto err;
538 * the start of line. 579
539 */ 580 if (*range == '+' || *range == '-') {
540 } else if (*tmp == '-') 581 const char c = *range++;
541 lr->end = (int)strtoul(tmp + 1, &tmp, 0); 582
542 else 583 err = parse_line_num(&range, &lr->end, "end line");
543 lr->end = INT_MAX; 584 if (err)
585 goto err;
586
587 if (c == '+') {
588 lr->end += lr->start;
589 /*
590 * Adjust the number of lines here.
591 * If the number of lines == 1, the
592 * the end of line should be equal to
593 * the start of line.
594 */
595 lr->end--;
596 }
597 }
598
544 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 599 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
600
601 err = -EINVAL;
545 if (lr->start > lr->end) { 602 if (lr->start > lr->end) {
546 semantic_error("Start line must be smaller" 603 semantic_error("Start line must be smaller"
547 " than end line.\n"); 604 " than end line.\n");
548 return -EINVAL; 605 goto err;
549 } 606 }
550 if (*tmp != '\0') { 607 if (*range != '\0') {
551 semantic_error("Tailing with invalid character '%d'.\n", 608 semantic_error("Tailing with invalid str '%s'.\n", range);
552 *tmp); 609 goto err;
553 return -EINVAL;
554 } 610 }
555 tmp = strndup(arg, (ptr - arg));
556 } else {
557 tmp = strdup(arg);
558 lr->end = INT_MAX;
559 } 611 }
560 612
561 if (tmp == NULL) 613 if (strchr(name, '.'))
562 return -ENOMEM; 614 lr->file = name;
563
564 if (strchr(tmp, '.'))
565 lr->file = tmp;
566 else 615 else
567 lr->function = tmp; 616 lr->function = name;
568 617
569 return 0; 618 return 0;
619err:
620 free(name);
621 return err;
570} 622}
571 623
572/* Check the name is good for event/group */ 624/* Check the name is good for event/group */
@@ -690,39 +742,40 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
690 742
691 /* Exclusion check */ 743 /* Exclusion check */
692 if (pp->lazy_line && pp->line) { 744 if (pp->lazy_line && pp->line) {
693 semantic_error("Lazy pattern can't be used with line number."); 745 semantic_error("Lazy pattern can't be used with"
746 " line number.\n");
694 return -EINVAL; 747 return -EINVAL;
695 } 748 }
696 749
697 if (pp->lazy_line && pp->offset) { 750 if (pp->lazy_line && pp->offset) {
698 semantic_error("Lazy pattern can't be used with offset."); 751 semantic_error("Lazy pattern can't be used with offset.\n");
699 return -EINVAL; 752 return -EINVAL;
700 } 753 }
701 754
702 if (pp->line && pp->offset) { 755 if (pp->line && pp->offset) {
703 semantic_error("Offset can't be used with line number."); 756 semantic_error("Offset can't be used with line number.\n");
704 return -EINVAL; 757 return -EINVAL;
705 } 758 }
706 759
707 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 760 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
708 semantic_error("File always requires line number or " 761 semantic_error("File always requires line number or "
709 "lazy pattern."); 762 "lazy pattern.\n");
710 return -EINVAL; 763 return -EINVAL;
711 } 764 }
712 765
713 if (pp->offset && !pp->function) { 766 if (pp->offset && !pp->function) {
714 semantic_error("Offset requires an entry function."); 767 semantic_error("Offset requires an entry function.\n");
715 return -EINVAL; 768 return -EINVAL;
716 } 769 }
717 770
718 if (pp->retprobe && !pp->function) { 771 if (pp->retprobe && !pp->function) {
719 semantic_error("Return probe requires an entry function."); 772 semantic_error("Return probe requires an entry function.\n");
720 return -EINVAL; 773 return -EINVAL;
721 } 774 }
722 775
723 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 776 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
724 semantic_error("Offset/Line/Lazy pattern can't be used with " 777 semantic_error("Offset/Line/Lazy pattern can't be used with "
725 "return probe."); 778 "return probe.\n");
726 return -EINVAL; 779 return -EINVAL;
727 } 780 }
728 781
@@ -996,7 +1049,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
996 1049
997 return tmp - buf; 1050 return tmp - buf;
998error: 1051error:
999 pr_debug("Failed to synthesize perf probe argument: %s", 1052 pr_debug("Failed to synthesize perf probe argument: %s\n",
1000 strerror(-ret)); 1053 strerror(-ret));
1001 return ret; 1054 return ret;
1002} 1055}
@@ -1024,13 +1077,13 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1024 goto error; 1077 goto error;
1025 } 1078 }
1026 if (pp->file) { 1079 if (pp->file) {
1027 len = strlen(pp->file) - 31; 1080 tmp = pp->file;
1028 if (len < 0) 1081 len = strlen(tmp);
1029 len = 0; 1082 if (len > 30) {
1030 tmp = strchr(pp->file + len, '/'); 1083 tmp = strchr(pp->file + len - 30, '/');
1031 if (!tmp) 1084 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1032 tmp = pp->file + len; 1085 }
1033 ret = e_snprintf(file, 32, "@%s", tmp + 1); 1086 ret = e_snprintf(file, 32, "@%s", tmp);
1034 if (ret <= 0) 1087 if (ret <= 0)
1035 goto error; 1088 goto error;
1036 } 1089 }
@@ -1046,7 +1099,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1046 1099
1047 return buf; 1100 return buf;
1048error: 1101error:
1049 pr_debug("Failed to synthesize perf probe point: %s", 1102 pr_debug("Failed to synthesize perf probe point: %s\n",
1050 strerror(-ret)); 1103 strerror(-ret));
1051 if (buf) 1104 if (buf)
1052 free(buf); 1105 free(buf);
@@ -1787,7 +1840,7 @@ static int del_trace_probe_event(int fd, const char *group,
1787 1840
1788 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1841 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1789 if (ret < 0) { 1842 if (ret < 0) {
1790 pr_err("Failed to copy event."); 1843 pr_err("Failed to copy event.\n");
1791 return ret; 1844 return ret;
1792 } 1845 }
1793 1846
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3991d73d1cff..ab83b6ac5d65 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -117,28 +117,6 @@ static void line_list__free(struct list_head *head)
117} 117}
118 118
119/* Dwarf FL wrappers */ 119/* Dwarf FL wrappers */
120
121static int __linux_kernel_find_elf(Dwfl_Module *mod,
122 void **userdata,
123 const char *module_name,
124 Dwarf_Addr base,
125 char **file_name, Elf **elfp)
126{
127 int fd;
128 const char *path = kernel_get_module_path(module_name);
129
130 if (path) {
131 fd = open(path, O_RDONLY);
132 if (fd >= 0) {
133 *file_name = strdup(path);
134 return fd;
135 }
136 }
137 /* If failed, try to call standard method */
138 return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
139 file_name, elfp);
140}
141
142static char *debuginfo_path; /* Currently dummy */ 120static char *debuginfo_path; /* Currently dummy */
143 121
144static const Dwfl_Callbacks offline_callbacks = { 122static const Dwfl_Callbacks offline_callbacks = {
@@ -151,14 +129,6 @@ static const Dwfl_Callbacks offline_callbacks = {
151 .find_elf = dwfl_build_id_find_elf, 129 .find_elf = dwfl_build_id_find_elf,
152}; 130};
153 131
154static const Dwfl_Callbacks kernel_callbacks = {
155 .find_debuginfo = dwfl_standard_find_debuginfo,
156 .debuginfo_path = &debuginfo_path,
157
158 .find_elf = __linux_kernel_find_elf,
159 .section_address = dwfl_linux_kernel_module_section_address,
160};
161
162/* Get a Dwarf from offline image */ 132/* Get a Dwarf from offline image */
163static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) 133static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias)
164{ 134{
@@ -185,6 +155,38 @@ error:
185 return dbg; 155 return dbg;
186} 156}
187 157
158#if _ELFUTILS_PREREQ(0, 148)
159/* This method is buggy if elfutils is older than 0.148 */
160static int __linux_kernel_find_elf(Dwfl_Module *mod,
161 void **userdata,
162 const char *module_name,
163 Dwarf_Addr base,
164 char **file_name, Elf **elfp)
165{
166 int fd;
167 const char *path = kernel_get_module_path(module_name);
168
169 pr_debug2("Use file %s for %s\n", path, module_name);
170 if (path) {
171 fd = open(path, O_RDONLY);
172 if (fd >= 0) {
173 *file_name = strdup(path);
174 return fd;
175 }
176 }
177 /* If failed, try to call standard method */
178 return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
179 file_name, elfp);
180}
181
182static const Dwfl_Callbacks kernel_callbacks = {
183 .find_debuginfo = dwfl_standard_find_debuginfo,
184 .debuginfo_path = &debuginfo_path,
185
186 .find_elf = __linux_kernel_find_elf,
187 .section_address = dwfl_linux_kernel_module_section_address,
188};
189
188/* Get a Dwarf from live kernel image */ 190/* Get a Dwarf from live kernel image */
189static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, 191static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
190 Dwarf_Addr *bias) 192 Dwarf_Addr *bias)
@@ -205,11 +207,34 @@ static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
205 dbg = dwfl_addrdwarf(*dwflp, addr, bias); 207 dbg = dwfl_addrdwarf(*dwflp, addr, bias);
206 /* Here, check whether we could get a real dwarf */ 208 /* Here, check whether we could get a real dwarf */
207 if (!dbg) { 209 if (!dbg) {
210 pr_debug("Failed to find kernel dwarf at %lx\n",
211 (unsigned long)addr);
208 dwfl_end(*dwflp); 212 dwfl_end(*dwflp);
209 *dwflp = NULL; 213 *dwflp = NULL;
210 } 214 }
211 return dbg; 215 return dbg;
212} 216}
217#else
218/* With older elfutils, this just support kernel module... */
219static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp,
220 Dwarf_Addr *bias)
221{
222 int fd;
223 const char *path = kernel_get_module_path("kernel");
224
225 if (!path) {
226 pr_err("Failed to find vmlinux path\n");
227 return NULL;
228 }
229
230 pr_debug2("Use file %s for debuginfo\n", path);
231 fd = open(path, O_RDONLY);
232 if (fd < 0)
233 return NULL;
234
235 return dwfl_init_offline_dwarf(fd, dwflp, bias);
236}
237#endif
213 238
214/* Dwarf wrappers */ 239/* Dwarf wrappers */
215 240
@@ -627,8 +652,8 @@ static_var:
627 regs = get_arch_regstr(regn); 652 regs = get_arch_regstr(regn);
628 if (!regs) { 653 if (!regs) {
629 /* This should be a bug in DWARF or this tool */ 654 /* This should be a bug in DWARF or this tool */
630 pr_warning("Mapping for DWARF register number %u " 655 pr_warning("Mapping for the register number %u "
631 "missing on this architecture.", regn); 656 "missing on this architecture.\n", regn);
632 return -ERANGE; 657 return -ERANGE;
633 } 658 }
634 659
@@ -674,13 +699,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
674 if (ret != DW_TAG_pointer_type && 699 if (ret != DW_TAG_pointer_type &&
675 ret != DW_TAG_array_type) { 700 ret != DW_TAG_array_type) {
676 pr_warning("Failed to cast into string: " 701 pr_warning("Failed to cast into string: "
677 "%s(%s) is not a pointer nor array.", 702 "%s(%s) is not a pointer nor array.\n",
678 dwarf_diename(vr_die), dwarf_diename(&type)); 703 dwarf_diename(vr_die), dwarf_diename(&type));
679 return -EINVAL; 704 return -EINVAL;
680 } 705 }
681 if (ret == DW_TAG_pointer_type) { 706 if (ret == DW_TAG_pointer_type) {
682 if (die_get_real_type(&type, &type) == NULL) { 707 if (die_get_real_type(&type, &type) == NULL) {
683 pr_warning("Failed to get a type information."); 708 pr_warning("Failed to get a type"
709 " information.\n");
684 return -ENOENT; 710 return -ENOENT;
685 } 711 }
686 while (*ref_ptr) 712 while (*ref_ptr)
@@ -695,7 +721,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
695 if (!die_compare_name(&type, "char") && 721 if (!die_compare_name(&type, "char") &&
696 !die_compare_name(&type, "unsigned char")) { 722 !die_compare_name(&type, "unsigned char")) {
697 pr_warning("Failed to cast into string: " 723 pr_warning("Failed to cast into string: "
698 "%s is not (unsigned) char *.", 724 "%s is not (unsigned) char *.\n",
699 dwarf_diename(vr_die)); 725 dwarf_diename(vr_die));
700 return -EINVAL; 726 return -EINVAL;
701 } 727 }
@@ -805,8 +831,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
805 return -EINVAL; 831 return -EINVAL;
806 } 832 }
807 if (field->name[0] == '[') { 833 if (field->name[0] == '[') {
808 pr_err("Semantic error: %s is not a pointor nor array.", 834 pr_err("Semantic error: %s is not a pointor"
809 varname); 835 " nor array.\n", varname);
810 return -EINVAL; 836 return -EINVAL;
811 } 837 }
812 if (field->ref) { 838 if (field->ref) {
@@ -953,7 +979,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
953 name = dwarf_diename(sp_die); 979 name = dwarf_diename(sp_die);
954 if (name) { 980 if (name) {
955 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 981 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
956 pr_warning("Failed to get entry pc of %s\n", 982 pr_warning("Failed to get entry address of %s\n",
957 dwarf_diename(sp_die)); 983 dwarf_diename(sp_die));
958 return -ENOENT; 984 return -ENOENT;
959 } 985 }
@@ -969,7 +995,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
969 if (retprobe) { 995 if (retprobe) {
970 if (eaddr != paddr) { 996 if (eaddr != paddr) {
971 pr_warning("Return probe must be on the head of" 997 pr_warning("Return probe must be on the head of"
972 " a real function\n"); 998 " a real function.\n");
973 return -EINVAL; 999 return -EINVAL;
974 } 1000 }
975 tp->retprobe = true; 1001 tp->retprobe = true;
@@ -1008,7 +1034,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1008 Dwarf_Frame *frame; 1034 Dwarf_Frame *frame;
1009 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 1035 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
1010 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 1036 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
1011 pr_warning("Failed to get CFA on 0x%jx\n", 1037 pr_warning("Failed to get call frame on 0x%jx\n",
1012 (uintmax_t)pf->addr); 1038 (uintmax_t)pf->addr);
1013 return -ENOENT; 1039 return -ENOENT;
1014 } 1040 }
@@ -1035,7 +1061,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
1035 int ret = 0; 1061 int ret = 0;
1036 1062
1037 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1063 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1038 pr_warning("No source lines found in this CU.\n"); 1064 pr_warning("No source lines found.\n");
1039 return -ENOENT; 1065 return -ENOENT;
1040 } 1066 }
1041 1067
@@ -1137,7 +1163,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1137 } 1163 }
1138 1164
1139 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1165 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1140 pr_warning("No source lines found in this CU.\n"); 1166 pr_warning("No source lines found.\n");
1141 return -ENOENT; 1167 return -ENOENT;
1142 } 1168 }
1143 1169
@@ -1195,7 +1221,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1195 else { 1221 else {
1196 /* Get probe address */ 1222 /* Get probe address */
1197 if (dwarf_entrypc(in_die, &addr) != 0) { 1223 if (dwarf_entrypc(in_die, &addr) != 0) {
1198 pr_warning("Failed to get entry pc of %s.\n", 1224 pr_warning("Failed to get entry address of %s.\n",
1199 dwarf_diename(in_die)); 1225 dwarf_diename(in_die));
1200 param->retval = -ENOENT; 1226 param->retval = -ENOENT;
1201 return DWARF_CB_ABORT; 1227 return DWARF_CB_ABORT;
@@ -1236,8 +1262,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1236 param->retval = find_probe_point_lazy(sp_die, pf); 1262 param->retval = find_probe_point_lazy(sp_die, pf);
1237 else { 1263 else {
1238 if (dwarf_entrypc(sp_die, &pf->addr) != 0) { 1264 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1239 pr_warning("Failed to get entry pc of %s.\n", 1265 pr_warning("Failed to get entry address of "
1240 dwarf_diename(sp_die)); 1266 "%s.\n", dwarf_diename(sp_die));
1241 param->retval = -ENOENT; 1267 param->retval = -ENOENT;
1242 return DWARF_CB_ABORT; 1268 return DWARF_CB_ABORT;
1243 } 1269 }
@@ -1279,7 +1305,7 @@ static int find_probes(int fd, struct probe_finder *pf)
1279 1305
1280 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1306 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1281 if (!dbg) { 1307 if (!dbg) {
1282 pr_warning("No dwarf info found in the vmlinux - " 1308 pr_warning("No debug information found in the vmlinux - "
1283 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1309 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1284 return -EBADF; 1310 return -EBADF;
1285 } 1311 }
@@ -1524,7 +1550,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1524 /* Open the live linux kernel */ 1550 /* Open the live linux kernel */
1525 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); 1551 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
1526 if (!dbg) { 1552 if (!dbg) {
1527 pr_warning("No dwarf info found in the vmlinux - " 1553 pr_warning("No debug information found in the vmlinux - "
1528 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1554 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1529 ret = -EINVAL; 1555 ret = -EINVAL;
1530 goto end; 1556 goto end;
@@ -1534,7 +1560,8 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1534 addr += bias; 1560 addr += bias;
1535 /* Find cu die */ 1561 /* Find cu die */
1536 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { 1562 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) {
1537 pr_warning("No CU DIE is found at %lx\n", addr); 1563 pr_warning("Failed to find debug information for address %lx\n",
1564 addr);
1538 ret = -EINVAL; 1565 ret = -EINVAL;
1539 goto end; 1566 goto end;
1540 } 1567 }
@@ -1659,7 +1686,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1659 1686
1660 line_list__init(&lf->lr->line_list); 1687 line_list__init(&lf->lr->line_list);
1661 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { 1688 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1662 pr_warning("No source lines found in this CU.\n"); 1689 pr_warning("No source lines found.\n");
1663 return -ENOENT; 1690 return -ENOENT;
1664 } 1691 }
1665 1692
@@ -1784,7 +1811,7 @@ int find_line_range(int fd, struct line_range *lr)
1784 1811
1785 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1812 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1786 if (!dbg) { 1813 if (!dbg) {
1787 pr_warning("No dwarf info found in the vmlinux - " 1814 pr_warning("No debug information found in the vmlinux - "
1788 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1815 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1789 return -EBADF; 1816 return -EBADF;
1790 } 1817 }
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index bba69d455699..beaefc3c1223 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -34,9 +34,9 @@ extern int find_available_vars_at(int fd, struct perf_probe_event *pev,
34 bool externs); 34 bool externs);
35 35
36#include <dwarf.h> 36#include <dwarf.h>
37#include <libdw.h> 37#include <elfutils/libdw.h>
38#include <libdwfl.h> 38#include <elfutils/libdwfl.h>
39#include <version.h> 39#include <elfutils/version.h>
40 40
41struct probe_finder { 41struct probe_finder {
42 struct perf_probe_event *pev; /* Target probe event */ 42 struct perf_probe_event *pev; /* Target probe event */
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b059dc50cc2d..93680818e244 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * trace-event-perl. Feed perf trace events to an embedded Perl interpreter. 2 * trace-event-perl. Feed perf script events to an embedded Perl interpreter.
3 * 3 *
4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5 * 5 *
@@ -411,8 +411,8 @@ static int perl_generate_script(const char *outfile)
411 return -1; 411 return -1;
412 } 412 }
413 413
414 fprintf(ofp, "# perf trace event handlers, " 414 fprintf(ofp, "# perf script event handlers, "
415 "generated by perf trace -g perl\n"); 415 "generated by perf script -g perl\n");
416 416
417 fprintf(ofp, "# Licensed under the terms of the GNU GPL" 417 fprintf(ofp, "# Licensed under the terms of the GNU GPL"
418 " License version 2\n\n"); 418 " License version 2\n\n");
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 33a632523743..c6d99334bdfa 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -442,8 +442,8 @@ static int python_generate_script(const char *outfile)
442 fprintf(stderr, "couldn't open %s\n", fname); 442 fprintf(stderr, "couldn't open %s\n", fname);
443 return -1; 443 return -1;
444 } 444 }
445 fprintf(ofp, "# perf trace event handlers, " 445 fprintf(ofp, "# perf script event handlers, "
446 "generated by perf trace -g python\n"); 446 "generated by perf script -g python\n");
447 447
448 fprintf(ofp, "# Licensed under the terms of the GNU GPL" 448 fprintf(ofp, "# Licensed under the terms of the GNU GPL"
449 " License version 2\n\n"); 449 " License version 2\n\n");
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index fa9d652c2dc3..105f00bfd555 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -65,9 +65,49 @@ out_close:
65 return -1; 65 return -1;
66} 66}
67 67
68static void perf_session__id_header_size(struct perf_session *session)
69{
70 struct sample_data *data;
71 u64 sample_type = session->sample_type;
72 u16 size = 0;
73
74 if (!session->sample_id_all)
75 goto out;
76
77 if (sample_type & PERF_SAMPLE_TID)
78 size += sizeof(data->tid) * 2;
79
80 if (sample_type & PERF_SAMPLE_TIME)
81 size += sizeof(data->time);
82
83 if (sample_type & PERF_SAMPLE_ID)
84 size += sizeof(data->id);
85
86 if (sample_type & PERF_SAMPLE_STREAM_ID)
87 size += sizeof(data->stream_id);
88
89 if (sample_type & PERF_SAMPLE_CPU)
90 size += sizeof(data->cpu) * 2;
91out:
92 session->id_hdr_size = size;
93}
94
95void perf_session__set_sample_id_all(struct perf_session *session, bool value)
96{
97 session->sample_id_all = value;
98 perf_session__id_header_size(session);
99}
100
101void perf_session__set_sample_type(struct perf_session *session, u64 type)
102{
103 session->sample_type = type;
104}
105
68void perf_session__update_sample_type(struct perf_session *self) 106void perf_session__update_sample_type(struct perf_session *self)
69{ 107{
70 self->sample_type = perf_header__sample_type(&self->header); 108 self->sample_type = perf_header__sample_type(&self->header);
109 self->sample_id_all = perf_header__sample_id_all(&self->header);
110 perf_session__id_header_size(self);
71} 111}
72 112
73int perf_session__create_kernel_maps(struct perf_session *self) 113int perf_session__create_kernel_maps(struct perf_session *self)
@@ -85,7 +125,9 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
85 machines__destroy_guest_kernel_maps(&self->machines); 125 machines__destroy_guest_kernel_maps(&self->machines);
86} 126}
87 127
88struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) 128struct perf_session *perf_session__new(const char *filename, int mode,
129 bool force, bool repipe,
130 struct perf_event_ops *ops)
89{ 131{
90 size_t len = filename ? strlen(filename) + 1 : 0; 132 size_t len = filename ? strlen(filename) + 1 : 0;
91 struct perf_session *self = zalloc(sizeof(*self) + len); 133 struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -101,10 +143,20 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
101 INIT_LIST_HEAD(&self->dead_threads); 143 INIT_LIST_HEAD(&self->dead_threads);
102 self->hists_tree = RB_ROOT; 144 self->hists_tree = RB_ROOT;
103 self->last_match = NULL; 145 self->last_match = NULL;
104 self->mmap_window = 32; 146 /*
147 * On 64bit we can mmap the data file in one go. No need for tiny mmap
148 * slices. On 32bit we use 32MB.
149 */
150#if BITS_PER_LONG == 64
151 self->mmap_window = ULLONG_MAX;
152#else
153 self->mmap_window = 32 * 1024 * 1024ULL;
154#endif
105 self->machines = RB_ROOT; 155 self->machines = RB_ROOT;
106 self->repipe = repipe; 156 self->repipe = repipe;
107 INIT_LIST_HEAD(&self->ordered_samples.samples_head); 157 INIT_LIST_HEAD(&self->ordered_samples.samples);
158 INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
159 INIT_LIST_HEAD(&self->ordered_samples.to_free);
108 machine__init(&self->host_machine, "", HOST_KERNEL_ID); 160 machine__init(&self->host_machine, "", HOST_KERNEL_ID);
109 161
110 if (mode == O_RDONLY) { 162 if (mode == O_RDONLY) {
@@ -120,6 +172,13 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
120 } 172 }
121 173
122 perf_session__update_sample_type(self); 174 perf_session__update_sample_type(self);
175
176 if (ops && ops->ordering_requires_timestamps &&
177 ops->ordered_samples && !self->sample_id_all) {
178 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
179 ops->ordered_samples = false;
180 }
181
123out: 182out:
124 return self; 183 return self;
125out_free: 184out_free:
@@ -230,7 +289,15 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
230 return syms; 289 return syms;
231} 290}
232 291
292static int process_event_synth_stub(event_t *event __used,
293 struct perf_session *session __used)
294{
295 dump_printf(": unhandled!\n");
296 return 0;
297}
298
233static int process_event_stub(event_t *event __used, 299static int process_event_stub(event_t *event __used,
300 struct sample_data *sample __used,
234 struct perf_session *session __used) 301 struct perf_session *session __used)
235{ 302{
236 dump_printf(": unhandled!\n"); 303 dump_printf(": unhandled!\n");
@@ -262,7 +329,7 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
262 if (handler->exit == NULL) 329 if (handler->exit == NULL)
263 handler->exit = process_event_stub; 330 handler->exit = process_event_stub;
264 if (handler->lost == NULL) 331 if (handler->lost == NULL)
265 handler->lost = process_event_stub; 332 handler->lost = event__process_lost;
266 if (handler->read == NULL) 333 if (handler->read == NULL)
267 handler->read = process_event_stub; 334 handler->read = process_event_stub;
268 if (handler->throttle == NULL) 335 if (handler->throttle == NULL)
@@ -270,13 +337,13 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
270 if (handler->unthrottle == NULL) 337 if (handler->unthrottle == NULL)
271 handler->unthrottle = process_event_stub; 338 handler->unthrottle = process_event_stub;
272 if (handler->attr == NULL) 339 if (handler->attr == NULL)
273 handler->attr = process_event_stub; 340 handler->attr = process_event_synth_stub;
274 if (handler->event_type == NULL) 341 if (handler->event_type == NULL)
275 handler->event_type = process_event_stub; 342 handler->event_type = process_event_synth_stub;
276 if (handler->tracing_data == NULL) 343 if (handler->tracing_data == NULL)
277 handler->tracing_data = process_event_stub; 344 handler->tracing_data = process_event_synth_stub;
278 if (handler->build_id == NULL) 345 if (handler->build_id == NULL)
279 handler->build_id = process_event_stub; 346 handler->build_id = process_event_synth_stub;
280 if (handler->finished_round == NULL) { 347 if (handler->finished_round == NULL) {
281 if (handler->ordered_samples) 348 if (handler->ordered_samples)
282 handler->finished_round = process_finished_round; 349 handler->finished_round = process_finished_round;
@@ -386,33 +453,61 @@ static event__swap_op event__swap_ops[] = {
386 453
387struct sample_queue { 454struct sample_queue {
388 u64 timestamp; 455 u64 timestamp;
389 struct sample_event *event; 456 u64 file_offset;
457 event_t *event;
390 struct list_head list; 458 struct list_head list;
391}; 459};
392 460
461static void perf_session_free_sample_buffers(struct perf_session *session)
462{
463 struct ordered_samples *os = &session->ordered_samples;
464
465 while (!list_empty(&os->to_free)) {
466 struct sample_queue *sq;
467
468 sq = list_entry(os->to_free.next, struct sample_queue, list);
469 list_del(&sq->list);
470 free(sq);
471 }
472}
473
474static int perf_session_deliver_event(struct perf_session *session,
475 event_t *event,
476 struct sample_data *sample,
477 struct perf_event_ops *ops,
478 u64 file_offset);
479
393static void flush_sample_queue(struct perf_session *s, 480static void flush_sample_queue(struct perf_session *s,
394 struct perf_event_ops *ops) 481 struct perf_event_ops *ops)
395{ 482{
396 struct list_head *head = &s->ordered_samples.samples_head; 483 struct ordered_samples *os = &s->ordered_samples;
397 u64 limit = s->ordered_samples.next_flush; 484 struct list_head *head = &os->samples;
398 struct sample_queue *tmp, *iter; 485 struct sample_queue *tmp, *iter;
486 struct sample_data sample;
487 u64 limit = os->next_flush;
488 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
399 489
400 if (!ops->ordered_samples || !limit) 490 if (!ops->ordered_samples || !limit)
401 return; 491 return;
402 492
403 list_for_each_entry_safe(iter, tmp, head, list) { 493 list_for_each_entry_safe(iter, tmp, head, list) {
404 if (iter->timestamp > limit) 494 if (iter->timestamp > limit)
405 return; 495 break;
406 496
407 if (iter == s->ordered_samples.last_inserted) 497 event__parse_sample(iter->event, s, &sample);
408 s->ordered_samples.last_inserted = NULL; 498 perf_session_deliver_event(s, iter->event, &sample, ops,
499 iter->file_offset);
409 500
410 ops->sample((event_t *)iter->event, s); 501 os->last_flush = iter->timestamp;
411
412 s->ordered_samples.last_flush = iter->timestamp;
413 list_del(&iter->list); 502 list_del(&iter->list);
414 free(iter->event); 503 list_add(&iter->list, &os->sample_cache);
415 free(iter); 504 }
505
506 if (list_empty(head)) {
507 os->last_sample = NULL;
508 } else if (last_ts <= limit) {
509 os->last_sample =
510 list_entry(head->prev, struct sample_queue, list);
416 } 511 }
417} 512}
418 513
@@ -465,178 +560,267 @@ static int process_finished_round(event_t *event __used,
465 return 0; 560 return 0;
466} 561}
467 562
468static void __queue_sample_end(struct sample_queue *new, struct list_head *head)
469{
470 struct sample_queue *iter;
471
472 list_for_each_entry_reverse(iter, head, list) {
473 if (iter->timestamp < new->timestamp) {
474 list_add(&new->list, &iter->list);
475 return;
476 }
477 }
478
479 list_add(&new->list, head);
480}
481
482static void __queue_sample_before(struct sample_queue *new,
483 struct sample_queue *iter,
484 struct list_head *head)
485{
486 list_for_each_entry_continue_reverse(iter, head, list) {
487 if (iter->timestamp < new->timestamp) {
488 list_add(&new->list, &iter->list);
489 return;
490 }
491 }
492
493 list_add(&new->list, head);
494}
495
496static void __queue_sample_after(struct sample_queue *new,
497 struct sample_queue *iter,
498 struct list_head *head)
499{
500 list_for_each_entry_continue(iter, head, list) {
501 if (iter->timestamp > new->timestamp) {
502 list_add_tail(&new->list, &iter->list);
503 return;
504 }
505 }
506 list_add_tail(&new->list, head);
507}
508
509/* The queue is ordered by time */ 563/* The queue is ordered by time */
510static void __queue_sample_event(struct sample_queue *new, 564static void __queue_event(struct sample_queue *new, struct perf_session *s)
511 struct perf_session *s)
512{ 565{
513 struct sample_queue *last_inserted = s->ordered_samples.last_inserted; 566 struct ordered_samples *os = &s->ordered_samples;
514 struct list_head *head = &s->ordered_samples.samples_head; 567 struct sample_queue *sample = os->last_sample;
568 u64 timestamp = new->timestamp;
569 struct list_head *p;
515 570
571 os->last_sample = new;
516 572
517 if (!last_inserted) { 573 if (!sample) {
518 __queue_sample_end(new, head); 574 list_add(&new->list, &os->samples);
575 os->max_timestamp = timestamp;
519 return; 576 return;
520 } 577 }
521 578
522 /* 579 /*
523 * Most of the time the current event has a timestamp 580 * last_sample might point to some random place in the list as it's
524 * very close to the last event inserted, unless we just switched 581 * the last queued event. We expect that the new event is close to
525 * to another event buffer. Having a sorting based on a list and 582 * this.
526 * on the last inserted event that is close to the current one is
527 * probably more efficient than an rbtree based sorting.
528 */ 583 */
529 if (last_inserted->timestamp >= new->timestamp) 584 if (sample->timestamp <= timestamp) {
530 __queue_sample_before(new, last_inserted, head); 585 while (sample->timestamp <= timestamp) {
531 else 586 p = sample->list.next;
532 __queue_sample_after(new, last_inserted, head); 587 if (p == &os->samples) {
588 list_add_tail(&new->list, &os->samples);
589 os->max_timestamp = timestamp;
590 return;
591 }
592 sample = list_entry(p, struct sample_queue, list);
593 }
594 list_add_tail(&new->list, &sample->list);
595 } else {
596 while (sample->timestamp > timestamp) {
597 p = sample->list.prev;
598 if (p == &os->samples) {
599 list_add(&new->list, &os->samples);
600 return;
601 }
602 sample = list_entry(p, struct sample_queue, list);
603 }
604 list_add(&new->list, &sample->list);
605 }
533} 606}
534 607
535static int queue_sample_event(event_t *event, struct sample_data *data, 608#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
536 struct perf_session *s) 609
610static int perf_session_queue_event(struct perf_session *s, event_t *event,
611 struct sample_data *data, u64 file_offset)
537{ 612{
613 struct ordered_samples *os = &s->ordered_samples;
614 struct list_head *sc = &os->sample_cache;
538 u64 timestamp = data->time; 615 u64 timestamp = data->time;
539 struct sample_queue *new; 616 struct sample_queue *new;
540 617
618 if (!timestamp || timestamp == ~0ULL)
619 return -ETIME;
541 620
542 if (timestamp < s->ordered_samples.last_flush) { 621 if (timestamp < s->ordered_samples.last_flush) {
543 printf("Warning: Timestamp below last timeslice flush\n"); 622 printf("Warning: Timestamp below last timeslice flush\n");
544 return -EINVAL; 623 return -EINVAL;
545 } 624 }
546 625
547 new = malloc(sizeof(*new)); 626 if (!list_empty(sc)) {
548 if (!new) 627 new = list_entry(sc->next, struct sample_queue, list);
549 return -ENOMEM; 628 list_del(&new->list);
629 } else if (os->sample_buffer) {
630 new = os->sample_buffer + os->sample_buffer_idx;
631 if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
632 os->sample_buffer = NULL;
633 } else {
634 os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
635 if (!os->sample_buffer)
636 return -ENOMEM;
637 list_add(&os->sample_buffer->list, &os->to_free);
638 os->sample_buffer_idx = 2;
639 new = os->sample_buffer + 1;
640 }
550 641
551 new->timestamp = timestamp; 642 new->timestamp = timestamp;
643 new->file_offset = file_offset;
644 new->event = event;
552 645
553 new->event = malloc(event->header.size); 646 __queue_event(new, s);
554 if (!new->event) {
555 free(new);
556 return -ENOMEM;
557 }
558 647
559 memcpy(new->event, event, event->header.size); 648 return 0;
649}
560 650
561 __queue_sample_event(new, s); 651static void callchain__printf(struct sample_data *sample)
562 s->ordered_samples.last_inserted = new; 652{
653 unsigned int i;
563 654
564 if (new->timestamp > s->ordered_samples.max_timestamp) 655 printf("... chain: nr:%" PRIu64 "\n", sample->callchain->nr);
565 s->ordered_samples.max_timestamp = new->timestamp;
566 656
567 return 0; 657 for (i = 0; i < sample->callchain->nr; i++)
658 printf("..... %2d: %016" PRIx64 "\n",
659 i, sample->callchain->ips[i]);
568} 660}
569 661
570static int perf_session__process_sample(event_t *event, struct perf_session *s, 662static void perf_session__print_tstamp(struct perf_session *session,
571 struct perf_event_ops *ops) 663 event_t *event,
664 struct sample_data *sample)
572{ 665{
573 struct sample_data data; 666 if (event->header.type != PERF_RECORD_SAMPLE &&
667 !session->sample_id_all) {
668 fputs("-1 -1 ", stdout);
669 return;
670 }
574 671
575 if (!ops->ordered_samples) 672 if ((session->sample_type & PERF_SAMPLE_CPU))
576 return ops->sample(event, s); 673 printf("%u ", sample->cpu);
577 674
578 bzero(&data, sizeof(struct sample_data)); 675 if (session->sample_type & PERF_SAMPLE_TIME)
579 event__parse_sample(event, s->sample_type, &data); 676 printf("%" PRIu64 " ", sample->time);
677}
580 678
581 queue_sample_event(event, &data, s); 679static void dump_event(struct perf_session *session, event_t *event,
680 u64 file_offset, struct sample_data *sample)
681{
682 if (!dump_trace)
683 return;
582 684
583 return 0; 685 printf("\n%#" PRIx64 " [%#x]: event: %d\n",
686 file_offset, event->header.size, event->header.type);
687
688 trace_event(event);
689
690 if (sample)
691 perf_session__print_tstamp(session, event, sample);
692
693 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
694 event->header.size, event__get_event_name(event->header.type));
584} 695}
585 696
586static int perf_session__process_event(struct perf_session *self, 697static void dump_sample(struct perf_session *session, event_t *event,
587 event_t *event, 698 struct sample_data *sample)
588 struct perf_event_ops *ops,
589 u64 offset, u64 head)
590{ 699{
591 trace_event(event); 700 if (!dump_trace)
701 return;
592 702
593 if (event->header.type < PERF_RECORD_HEADER_MAX) { 703 printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n",
594 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 704 event->header.misc, sample->pid, sample->tid, sample->ip,
595 offset + head, event->header.size, 705 sample->period);
596 event__name[event->header.type]);
597 hists__inc_nr_events(&self->hists, event->header.type);
598 }
599 706
600 if (self->header.needs_swap && event__swap_ops[event->header.type]) 707 if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
601 event__swap_ops[event->header.type](event); 708 callchain__printf(sample);
709}
710
711static int perf_session_deliver_event(struct perf_session *session,
712 event_t *event,
713 struct sample_data *sample,
714 struct perf_event_ops *ops,
715 u64 file_offset)
716{
717 dump_event(session, event, file_offset, sample);
602 718
603 switch (event->header.type) { 719 switch (event->header.type) {
604 case PERF_RECORD_SAMPLE: 720 case PERF_RECORD_SAMPLE:
605 return perf_session__process_sample(event, self, ops); 721 dump_sample(session, event, sample);
722 return ops->sample(event, sample, session);
606 case PERF_RECORD_MMAP: 723 case PERF_RECORD_MMAP:
607 return ops->mmap(event, self); 724 return ops->mmap(event, sample, session);
608 case PERF_RECORD_COMM: 725 case PERF_RECORD_COMM:
609 return ops->comm(event, self); 726 return ops->comm(event, sample, session);
610 case PERF_RECORD_FORK: 727 case PERF_RECORD_FORK:
611 return ops->fork(event, self); 728 return ops->fork(event, sample, session);
612 case PERF_RECORD_EXIT: 729 case PERF_RECORD_EXIT:
613 return ops->exit(event, self); 730 return ops->exit(event, sample, session);
614 case PERF_RECORD_LOST: 731 case PERF_RECORD_LOST:
615 return ops->lost(event, self); 732 return ops->lost(event, sample, session);
616 case PERF_RECORD_READ: 733 case PERF_RECORD_READ:
617 return ops->read(event, self); 734 return ops->read(event, sample, session);
618 case PERF_RECORD_THROTTLE: 735 case PERF_RECORD_THROTTLE:
619 return ops->throttle(event, self); 736 return ops->throttle(event, sample, session);
620 case PERF_RECORD_UNTHROTTLE: 737 case PERF_RECORD_UNTHROTTLE:
621 return ops->unthrottle(event, self); 738 return ops->unthrottle(event, sample, session);
739 default:
740 ++session->hists.stats.nr_unknown_events;
741 return -1;
742 }
743}
744
745static int perf_session__preprocess_sample(struct perf_session *session,
746 event_t *event, struct sample_data *sample)
747{
748 if (event->header.type != PERF_RECORD_SAMPLE ||
749 !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
750 return 0;
751
752 if (!ip_callchain__valid(sample->callchain, event)) {
753 pr_debug("call-chain problem with event, skipping it.\n");
754 ++session->hists.stats.nr_invalid_chains;
755 session->hists.stats.total_invalid_chains += sample->period;
756 return -EINVAL;
757 }
758 return 0;
759}
760
761static int perf_session__process_user_event(struct perf_session *session, event_t *event,
762 struct perf_event_ops *ops, u64 file_offset)
763{
764 dump_event(session, event, file_offset, NULL);
765
766 /* These events are processed right away */
767 switch (event->header.type) {
622 case PERF_RECORD_HEADER_ATTR: 768 case PERF_RECORD_HEADER_ATTR:
623 return ops->attr(event, self); 769 return ops->attr(event, session);
624 case PERF_RECORD_HEADER_EVENT_TYPE: 770 case PERF_RECORD_HEADER_EVENT_TYPE:
625 return ops->event_type(event, self); 771 return ops->event_type(event, session);
626 case PERF_RECORD_HEADER_TRACING_DATA: 772 case PERF_RECORD_HEADER_TRACING_DATA:
627 /* setup for reading amidst mmap */ 773 /* setup for reading amidst mmap */
628 lseek(self->fd, offset + head, SEEK_SET); 774 lseek(session->fd, file_offset, SEEK_SET);
629 return ops->tracing_data(event, self); 775 return ops->tracing_data(event, session);
630 case PERF_RECORD_HEADER_BUILD_ID: 776 case PERF_RECORD_HEADER_BUILD_ID:
631 return ops->build_id(event, self); 777 return ops->build_id(event, session);
632 case PERF_RECORD_FINISHED_ROUND: 778 case PERF_RECORD_FINISHED_ROUND:
633 return ops->finished_round(event, self, ops); 779 return ops->finished_round(event, session, ops);
634 default: 780 default:
635 ++self->hists.stats.nr_unknown_events; 781 return -EINVAL;
636 return -1;
637 } 782 }
638} 783}
639 784
785static int perf_session__process_event(struct perf_session *session,
786 event_t *event,
787 struct perf_event_ops *ops,
788 u64 file_offset)
789{
790 struct sample_data sample;
791 int ret;
792
793 if (session->header.needs_swap && event__swap_ops[event->header.type])
794 event__swap_ops[event->header.type](event);
795
796 if (event->header.type >= PERF_RECORD_HEADER_MAX)
797 return -EINVAL;
798
799 hists__inc_nr_events(&session->hists, event->header.type);
800
801 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
802 return perf_session__process_user_event(session, event, ops, file_offset);
803
804 /*
805 * For all kernel events we get the sample data
806 */
807 event__parse_sample(event, session, &sample);
808
809 /* Preprocess sample records - precheck callchains */
810 if (perf_session__preprocess_sample(session, event, &sample))
811 return 0;
812
813 if (ops->ordered_samples) {
814 ret = perf_session_queue_event(session, event, &sample,
815 file_offset);
816 if (ret != -ETIME)
817 return ret;
818 }
819
820 return perf_session_deliver_event(session, event, &sample, ops,
821 file_offset);
822}
823
640void perf_event_header__bswap(struct perf_event_header *self) 824void perf_event_header__bswap(struct perf_event_header *self)
641{ 825{
642 self->type = bswap_32(self->type); 826 self->type = bswap_32(self->type);
@@ -656,21 +840,33 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
656 return thread; 840 return thread;
657} 841}
658 842
659int do_read(int fd, void *buf, size_t size) 843static void perf_session__warn_about_errors(const struct perf_session *session,
844 const struct perf_event_ops *ops)
660{ 845{
661 void *buf_start = buf; 846 if (ops->lost == event__process_lost &&
662 847 session->hists.stats.total_lost != 0) {
663 while (size) { 848 ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64
664 int ret = read(fd, buf, size); 849 "!\n\nCheck IO/CPU overload!\n\n",
665 850 session->hists.stats.total_period,
666 if (ret <= 0) 851 session->hists.stats.total_lost);
667 return ret; 852 }
668 853
669 size -= ret; 854 if (session->hists.stats.nr_unknown_events != 0) {
670 buf += ret; 855 ui__warning("Found %u unknown events!\n\n"
856 "Is this an older tool processing a perf.data "
857 "file generated by a more recent tool?\n\n"
858 "If that is not the case, consider "
859 "reporting to linux-kernel@vger.kernel.org.\n\n",
860 session->hists.stats.nr_unknown_events);
671 } 861 }
672 862
673 return buf - buf_start; 863 if (session->hists.stats.nr_invalid_chains != 0) {
864 ui__warning("Found invalid callchains!\n\n"
865 "%u out of %u events were discarded for this reason.\n\n"
866 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
867 session->hists.stats.nr_invalid_chains,
868 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
869 }
674} 870}
675 871
676#define session_done() (*(volatile int *)(&session_done)) 872#define session_done() (*(volatile int *)(&session_done))
@@ -690,7 +886,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
690 886
691 head = 0; 887 head = 0;
692more: 888more:
693 err = do_read(self->fd, &event, sizeof(struct perf_event_header)); 889 err = readn(self->fd, &event, sizeof(struct perf_event_header));
694 if (err <= 0) { 890 if (err <= 0) {
695 if (err == 0) 891 if (err == 0)
696 goto done; 892 goto done;
@@ -710,8 +906,7 @@ more:
710 p += sizeof(struct perf_event_header); 906 p += sizeof(struct perf_event_header);
711 907
712 if (size - sizeof(struct perf_event_header)) { 908 if (size - sizeof(struct perf_event_header)) {
713 err = do_read(self->fd, p, 909 err = readn(self->fd, p, size - sizeof(struct perf_event_header));
714 size - sizeof(struct perf_event_header));
715 if (err <= 0) { 910 if (err <= 0) {
716 if (err == 0) { 911 if (err == 0) {
717 pr_err("unexpected end of event stream\n"); 912 pr_err("unexpected end of event stream\n");
@@ -724,9 +919,8 @@ more:
724 } 919 }
725 920
726 if (size == 0 || 921 if (size == 0 ||
727 (skip = perf_session__process_event(self, &event, ops, 922 (skip = perf_session__process_event(self, &event, ops, head)) < 0) {
728 0, head)) < 0) { 923 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
729 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
730 head, event.header.size, event.header.type); 924 head, event.header.size, event.header.type);
731 /* 925 /*
732 * assume we lost track of the stream, check alignment, and 926 * assume we lost track of the stream, check alignment, and
@@ -740,9 +934,6 @@ more:
740 934
741 head += size; 935 head += size;
742 936
743 dump_printf("\n%#Lx [%#x]: event: %d\n",
744 head, event.header.size, event.header.type);
745
746 if (skip > 0) 937 if (skip > 0)
747 head += skip; 938 head += skip;
748 939
@@ -751,82 +942,91 @@ more:
751done: 942done:
752 err = 0; 943 err = 0;
753out_err: 944out_err:
945 perf_session__warn_about_errors(self, ops);
946 perf_session_free_sample_buffers(self);
754 return err; 947 return err;
755} 948}
756 949
757int __perf_session__process_events(struct perf_session *self, 950int __perf_session__process_events(struct perf_session *session,
758 u64 data_offset, u64 data_size, 951 u64 data_offset, u64 data_size,
759 u64 file_size, struct perf_event_ops *ops) 952 u64 file_size, struct perf_event_ops *ops)
760{ 953{
761 int err, mmap_prot, mmap_flags; 954 u64 head, page_offset, file_offset, file_pos, progress_next;
762 u64 head, shift; 955 int err, mmap_prot, mmap_flags, map_idx = 0;
763 u64 offset = 0; 956 struct ui_progress *progress;
764 size_t page_size; 957 size_t page_size, mmap_size;
958 char *buf, *mmaps[8];
765 event_t *event; 959 event_t *event;
766 uint32_t size; 960 uint32_t size;
767 char *buf;
768 struct ui_progress *progress = ui_progress__new("Processing events...",
769 self->size);
770 if (progress == NULL)
771 return -1;
772 961
773 perf_event_ops__fill_defaults(ops); 962 perf_event_ops__fill_defaults(ops);
774 963
775 page_size = sysconf(_SC_PAGESIZE); 964 page_size = sysconf(_SC_PAGESIZE);
776 965
777 head = data_offset; 966 page_offset = page_size * (data_offset / page_size);
778 shift = page_size * (head / page_size); 967 file_offset = page_offset;
779 offset += shift; 968 head = data_offset - page_offset;
780 head -= shift; 969
970 if (data_offset + data_size < file_size)
971 file_size = data_offset + data_size;
972
973 progress_next = file_size / 16;
974 progress = ui_progress__new("Processing events...", file_size);
975 if (progress == NULL)
976 return -1;
977
978 mmap_size = session->mmap_window;
979 if (mmap_size > file_size)
980 mmap_size = file_size;
981
982 memset(mmaps, 0, sizeof(mmaps));
781 983
782 mmap_prot = PROT_READ; 984 mmap_prot = PROT_READ;
783 mmap_flags = MAP_SHARED; 985 mmap_flags = MAP_SHARED;
784 986
785 if (self->header.needs_swap) { 987 if (session->header.needs_swap) {
786 mmap_prot |= PROT_WRITE; 988 mmap_prot |= PROT_WRITE;
787 mmap_flags = MAP_PRIVATE; 989 mmap_flags = MAP_PRIVATE;
788 } 990 }
789remap: 991remap:
790 buf = mmap(NULL, page_size * self->mmap_window, mmap_prot, 992 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd,
791 mmap_flags, self->fd, offset); 993 file_offset);
792 if (buf == MAP_FAILED) { 994 if (buf == MAP_FAILED) {
793 pr_err("failed to mmap file\n"); 995 pr_err("failed to mmap file\n");
794 err = -errno; 996 err = -errno;
795 goto out_err; 997 goto out_err;
796 } 998 }
999 mmaps[map_idx] = buf;
1000 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
1001 file_pos = file_offset + head;
797 1002
798more: 1003more:
799 event = (event_t *)(buf + head); 1004 event = (event_t *)(buf + head);
800 ui_progress__update(progress, offset);
801 1005
802 if (self->header.needs_swap) 1006 if (session->header.needs_swap)
803 perf_event_header__bswap(&event->header); 1007 perf_event_header__bswap(&event->header);
804 size = event->header.size; 1008 size = event->header.size;
805 if (size == 0) 1009 if (size == 0)
806 size = 8; 1010 size = 8;
807 1011
808 if (head + event->header.size >= page_size * self->mmap_window) { 1012 if (head + event->header.size > mmap_size) {
809 int munmap_ret; 1013 if (mmaps[map_idx]) {
810 1014 munmap(mmaps[map_idx], mmap_size);
811 shift = page_size * (head / page_size); 1015 mmaps[map_idx] = NULL;
812 1016 }
813 munmap_ret = munmap(buf, page_size * self->mmap_window);
814 assert(munmap_ret == 0);
815 1017
816 offset += shift; 1018 page_offset = page_size * (head / page_size);
817 head -= shift; 1019 file_offset += page_offset;
1020 head -= page_offset;
818 goto remap; 1021 goto remap;
819 } 1022 }
820 1023
821 size = event->header.size; 1024 size = event->header.size;
822 1025
823 dump_printf("\n%#Lx [%#x]: event: %d\n",
824 offset + head, event->header.size, event->header.type);
825
826 if (size == 0 || 1026 if (size == 0 ||
827 perf_session__process_event(self, event, ops, offset, head) < 0) { 1027 perf_session__process_event(session, event, ops, file_pos) < 0) {
828 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n", 1028 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
829 offset + head, event->header.size, 1029 file_offset + head, event->header.size,
830 event->header.type); 1030 event->header.type);
831 /* 1031 /*
832 * assume we lost track of the stream, check alignment, and 1032 * assume we lost track of the stream, check alignment, and
@@ -839,19 +1039,24 @@ more:
839 } 1039 }
840 1040
841 head += size; 1041 head += size;
1042 file_pos += size;
842 1043
843 if (offset + head >= data_offset + data_size) 1044 if (file_pos >= progress_next) {
844 goto done; 1045 progress_next += file_size / 16;
1046 ui_progress__update(progress, file_pos);
1047 }
845 1048
846 if (offset + head < file_size) 1049 if (file_pos < file_size)
847 goto more; 1050 goto more;
848done: 1051
849 err = 0; 1052 err = 0;
850 /* do the final flush for ordered samples */ 1053 /* do the final flush for ordered samples */
851 self->ordered_samples.next_flush = ULLONG_MAX; 1054 session->ordered_samples.next_flush = ULLONG_MAX;
852 flush_sample_queue(self, ops); 1055 flush_sample_queue(session, ops);
853out_err: 1056out_err:
854 ui_progress__delete(progress); 1057 ui_progress__delete(progress);
1058 perf_session__warn_about_errors(session, ops);
1059 perf_session_free_sample_buffers(session);
855 return err; 1060 return err;
856} 1061}
857 1062
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 9fa0fc2a863f..decd83f274fd 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -17,8 +17,12 @@ struct ordered_samples {
17 u64 last_flush; 17 u64 last_flush;
18 u64 next_flush; 18 u64 next_flush;
19 u64 max_timestamp; 19 u64 max_timestamp;
20 struct list_head samples_head; 20 struct list_head samples;
21 struct sample_queue *last_inserted; 21 struct list_head sample_cache;
22 struct list_head to_free;
23 struct sample_queue *sample_buffer;
24 struct sample_queue *last_sample;
25 int sample_buffer_idx;
22}; 26};
23 27
24struct perf_session { 28struct perf_session {
@@ -42,6 +46,8 @@ struct perf_session {
42 int fd; 46 int fd;
43 bool fd_pipe; 47 bool fd_pipe;
44 bool repipe; 48 bool repipe;
49 bool sample_id_all;
50 u16 id_hdr_size;
45 int cwdlen; 51 int cwdlen;
46 char *cwd; 52 char *cwd;
47 struct ordered_samples ordered_samples; 53 struct ordered_samples ordered_samples;
@@ -50,7 +56,9 @@ struct perf_session {
50 56
51struct perf_event_ops; 57struct perf_event_ops;
52 58
53typedef int (*event_op)(event_t *self, struct perf_session *session); 59typedef int (*event_op)(event_t *self, struct sample_data *sample,
60 struct perf_session *session);
61typedef int (*event_synth_op)(event_t *self, struct perf_session *session);
54typedef int (*event_op2)(event_t *self, struct perf_session *session, 62typedef int (*event_op2)(event_t *self, struct perf_session *session,
55 struct perf_event_ops *ops); 63 struct perf_event_ops *ops);
56 64
@@ -63,16 +71,19 @@ struct perf_event_ops {
63 lost, 71 lost,
64 read, 72 read,
65 throttle, 73 throttle,
66 unthrottle, 74 unthrottle;
67 attr, 75 event_synth_op attr,
68 event_type, 76 event_type,
69 tracing_data, 77 tracing_data,
70 build_id; 78 build_id;
71 event_op2 finished_round; 79 event_op2 finished_round;
72 bool ordered_samples; 80 bool ordered_samples;
81 bool ordering_requires_timestamps;
73}; 82};
74 83
75struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); 84struct perf_session *perf_session__new(const char *filename, int mode,
85 bool force, bool repipe,
86 struct perf_event_ops *ops);
76void perf_session__delete(struct perf_session *self); 87void perf_session__delete(struct perf_session *self);
77 88
78void perf_event_header__bswap(struct perf_event_header *self); 89void perf_event_header__bswap(struct perf_event_header *self);
@@ -98,8 +109,9 @@ void mem_bswap_64(void *src, int byte_size);
98 109
99int perf_session__create_kernel_maps(struct perf_session *self); 110int perf_session__create_kernel_maps(struct perf_session *self);
100 111
101int do_read(int fd, void *buf, size_t size);
102void perf_session__update_sample_type(struct perf_session *self); 112void perf_session__update_sample_type(struct perf_session *self);
113void perf_session__set_sample_id_all(struct perf_session *session, bool value);
114void perf_session__set_sample_type(struct perf_session *session, u64 type);
103void perf_session__remove_thread(struct perf_session *self, struct thread *th); 115void perf_session__remove_thread(struct perf_session *self, struct thread *th);
104 116
105static inline 117static inline
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b62a553cc67d..f44fa541d56e 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -170,7 +170,7 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
170 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 170 return repsep_snprintf(bf, size, "%-*s", width, dso_name);
171 } 171 }
172 172
173 return repsep_snprintf(bf, size, "%*Lx", width, self->ip); 173 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
174} 174}
175 175
176/* --sort symbol */ 176/* --sort symbol */
@@ -196,7 +196,7 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
196 196
197 if (verbose) { 197 if (verbose) {
198 char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!'; 198 char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
199 ret += repsep_snprintf(bf, size, "%*Lx %c ", 199 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
200 BITS_PER_LONG / 4, self->ip, o); 200 BITS_PER_LONG / 4, self->ip, o);
201 } 201 }
202 202
@@ -205,7 +205,7 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
205 ret += repsep_snprintf(bf + ret, size - ret, "%s", 205 ret += repsep_snprintf(bf + ret, size - ret, "%s",
206 self->ms.sym->name); 206 self->ms.sym->name);
207 else 207 else
208 ret += repsep_snprintf(bf + ret, size - ret, "%*Lx", 208 ret += repsep_snprintf(bf + ret, size - ret, "%-#*llx",
209 BITS_PER_LONG / 4, self->ip); 209 BITS_PER_LONG / 4, self->ip);
210 210
211 return ret; 211 return ret;
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 0409fc7c0058..8fc0bd3a3a4a 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -259,7 +259,7 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
259 if (!*pat) /* Tail wild card matches all */ 259 if (!*pat) /* Tail wild card matches all */
260 return true; 260 return true;
261 while (*str) 261 while (*str)
262 if (strglobmatch(str++, pat)) 262 if (__match_glob(str++, pat, ignore_space))
263 return true; 263 return true;
264 } 264 }
265 return !*str && !*pat; 265 return !*str && !*pat;
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index b3637db025a2..fb737fe9be91 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -12,6 +12,7 @@
12 * of the License. 12 * of the License.
13 */ 13 */
14 14
15#include <inttypes.h>
15#include <stdio.h> 16#include <stdio.h>
16#include <stdlib.h> 17#include <stdlib.h>
17#include <unistd.h> 18#include <unistd.h>
@@ -43,11 +44,11 @@ static double cpu2y(int cpu)
43 return cpu2slot(cpu) * SLOT_MULT; 44 return cpu2slot(cpu) * SLOT_MULT;
44} 45}
45 46
46static double time2pixels(u64 time) 47static double time2pixels(u64 __time)
47{ 48{
48 double X; 49 double X;
49 50
50 X = 1.0 * svg_page_width * (time - first_time) / (last_time - first_time); 51 X = 1.0 * svg_page_width * (__time - first_time) / (last_time - first_time);
51 return X; 52 return X;
52} 53}
53 54
@@ -94,7 +95,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
94 95
95 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; 96 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
96 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); 97 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
97 fprintf(svgfile, "<svg width=\"%i\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); 98 fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
98 99
99 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); 100 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
100 101
@@ -483,7 +484,7 @@ void svg_time_grid(void)
483 color = 128; 484 color = 128;
484 } 485 }
485 486
486 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%llu\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%1.3f\"/>\n", 487 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%" PRIu64 "\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%1.3f\"/>\n",
487 time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness); 488 time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness);
488 489
489 i += 10000000; 490 i += 10000000;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b39f499e575a..7821d0e6866f 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -11,6 +11,7 @@
11#include <sys/param.h> 11#include <sys/param.h>
12#include <fcntl.h> 12#include <fcntl.h>
13#include <unistd.h> 13#include <unistd.h>
14#include <inttypes.h>
14#include "build-id.h" 15#include "build-id.h"
15#include "debug.h" 16#include "debug.h"
16#include "symbol.h" 17#include "symbol.h"
@@ -22,6 +23,10 @@
22#include <limits.h> 23#include <limits.h>
23#include <sys/utsname.h> 24#include <sys/utsname.h>
24 25
26#ifndef KSYM_NAME_LEN
27#define KSYM_NAME_LEN 128
28#endif
29
25#ifndef NT_GNU_BUILD_ID 30#ifndef NT_GNU_BUILD_ID
26#define NT_GNU_BUILD_ID 3 31#define NT_GNU_BUILD_ID 3
27#endif 32#endif
@@ -41,6 +46,7 @@ struct symbol_conf symbol_conf = {
41 .exclude_other = true, 46 .exclude_other = true,
42 .use_modules = true, 47 .use_modules = true,
43 .try_vmlinux_path = true, 48 .try_vmlinux_path = true,
49 .symfs = "",
44}; 50};
45 51
46int dso__name_len(const struct dso *self) 52int dso__name_len(const struct dso *self)
@@ -92,7 +98,7 @@ static void symbols__fixup_end(struct rb_root *self)
92 prev = curr; 98 prev = curr;
93 curr = rb_entry(nd, struct symbol, rb_node); 99 curr = rb_entry(nd, struct symbol, rb_node);
94 100
95 if (prev->end == prev->start) 101 if (prev->end == prev->start && prev->end != curr->start)
96 prev->end = curr->start - 1; 102 prev->end = curr->start - 1;
97 } 103 }
98 104
@@ -121,7 +127,7 @@ static void __map_groups__fixup_end(struct map_groups *self, enum map_type type)
121 * We still haven't the actual symbols, so guess the 127 * We still haven't the actual symbols, so guess the
122 * last map final address. 128 * last map final address.
123 */ 129 */
124 curr->end = ~0UL; 130 curr->end = ~0ULL;
125} 131}
126 132
127static void map_groups__fixup_end(struct map_groups *self) 133static void map_groups__fixup_end(struct map_groups *self)
@@ -148,7 +154,7 @@ static struct symbol *symbol__new(u64 start, u64 len, u8 binding,
148 self->binding = binding; 154 self->binding = binding;
149 self->namelen = namelen - 1; 155 self->namelen = namelen - 1;
150 156
151 pr_debug4("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end); 157 pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", __func__, name, start, self->end);
152 158
153 memcpy(self->name, name, namelen); 159 memcpy(self->name, name, namelen);
154 160
@@ -162,7 +168,7 @@ void symbol__delete(struct symbol *self)
162 168
163static size_t symbol__fprintf(struct symbol *self, FILE *fp) 169static size_t symbol__fprintf(struct symbol *self, FILE *fp)
164{ 170{
165 return fprintf(fp, " %llx-%llx %c %s\n", 171 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
166 self->start, self->end, 172 self->start, self->end,
167 self->binding == STB_GLOBAL ? 'g' : 173 self->binding == STB_GLOBAL ? 'g' :
168 self->binding == STB_LOCAL ? 'l' : 'w', 174 self->binding == STB_LOCAL ? 'l' : 'w',
@@ -295,7 +301,9 @@ static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym)
295{ 301{
296 struct rb_node **p = &self->rb_node; 302 struct rb_node **p = &self->rb_node;
297 struct rb_node *parent = NULL; 303 struct rb_node *parent = NULL;
298 struct symbol_name_rb_node *symn = ((void *)sym) - sizeof(*parent), *s; 304 struct symbol_name_rb_node *symn, *s;
305
306 symn = container_of(sym, struct symbol_name_rb_node, sym);
299 307
300 while (*p != NULL) { 308 while (*p != NULL) {
301 parent = *p; 309 parent = *p;
@@ -423,16 +431,25 @@ size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
423 431
424int kallsyms__parse(const char *filename, void *arg, 432int kallsyms__parse(const char *filename, void *arg,
425 int (*process_symbol)(void *arg, const char *name, 433 int (*process_symbol)(void *arg, const char *name,
426 char type, u64 start)) 434 char type, u64 start, u64 end))
427{ 435{
428 char *line = NULL; 436 char *line = NULL;
429 size_t n; 437 size_t n;
430 int err = 0; 438 int err = -1;
439 u64 prev_start = 0;
440 char prev_symbol_type = 0;
441 char *prev_symbol_name;
431 FILE *file = fopen(filename, "r"); 442 FILE *file = fopen(filename, "r");
432 443
433 if (file == NULL) 444 if (file == NULL)
434 goto out_failure; 445 goto out_failure;
435 446
447 prev_symbol_name = malloc(KSYM_NAME_LEN);
448 if (prev_symbol_name == NULL)
449 goto out_close;
450
451 err = 0;
452
436 while (!feof(file)) { 453 while (!feof(file)) {
437 u64 start; 454 u64 start;
438 int line_len, len; 455 int line_len, len;
@@ -452,14 +469,33 @@ int kallsyms__parse(const char *filename, void *arg,
452 continue; 469 continue;
453 470
454 symbol_type = toupper(line[len]); 471 symbol_type = toupper(line[len]);
455 symbol_name = line + len + 2; 472 len += 2;
473 symbol_name = line + len;
474 len = line_len - len;
456 475
457 err = process_symbol(arg, symbol_name, symbol_type, start); 476 if (len >= KSYM_NAME_LEN) {
458 if (err) 477 err = -1;
459 break; 478 break;
479 }
480
481 if (prev_symbol_type) {
482 u64 end = start;
483 if (end != prev_start)
484 --end;
485 err = process_symbol(arg, prev_symbol_name,
486 prev_symbol_type, prev_start, end);
487 if (err)
488 break;
489 }
490
491 memcpy(prev_symbol_name, symbol_name, len + 1);
492 prev_symbol_type = symbol_type;
493 prev_start = start;
460 } 494 }
461 495
496 free(prev_symbol_name);
462 free(line); 497 free(line);
498out_close:
463 fclose(file); 499 fclose(file);
464 return err; 500 return err;
465 501
@@ -481,7 +517,7 @@ static u8 kallsyms2elf_type(char type)
481} 517}
482 518
483static int map__process_kallsym_symbol(void *arg, const char *name, 519static int map__process_kallsym_symbol(void *arg, const char *name,
484 char type, u64 start) 520 char type, u64 start, u64 end)
485{ 521{
486 struct symbol *sym; 522 struct symbol *sym;
487 struct process_kallsyms_args *a = arg; 523 struct process_kallsyms_args *a = arg;
@@ -490,11 +526,8 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
490 if (!symbol_type__is_a(type, a->map->type)) 526 if (!symbol_type__is_a(type, a->map->type))
491 return 0; 527 return 0;
492 528
493 /* 529 sym = symbol__new(start, end - start + 1,
494 * Will fix up the end later, when we have all symbols sorted. 530 kallsyms2elf_type(type), name);
495 */
496 sym = symbol__new(start, 0, kallsyms2elf_type(type), name);
497
498 if (sym == NULL) 531 if (sym == NULL)
499 return -ENOMEM; 532 return -ENOMEM;
500 /* 533 /*
@@ -530,7 +563,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
530 struct machine *machine = kmaps->machine; 563 struct machine *machine = kmaps->machine;
531 struct map *curr_map = map; 564 struct map *curr_map = map;
532 struct symbol *pos; 565 struct symbol *pos;
533 int count = 0; 566 int count = 0, moved = 0;
534 struct rb_root *root = &self->symbols[map->type]; 567 struct rb_root *root = &self->symbols[map->type];
535 struct rb_node *next = rb_first(root); 568 struct rb_node *next = rb_first(root);
536 int kernel_range = 0; 569 int kernel_range = 0;
@@ -588,6 +621,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
588 char dso_name[PATH_MAX]; 621 char dso_name[PATH_MAX];
589 struct dso *dso; 622 struct dso *dso;
590 623
624 if (count == 0) {
625 curr_map = map;
626 goto filter_symbol;
627 }
628
591 if (self->kernel == DSO_TYPE_GUEST_KERNEL) 629 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
592 snprintf(dso_name, sizeof(dso_name), 630 snprintf(dso_name, sizeof(dso_name),
593 "[guest.kernel].%d", 631 "[guest.kernel].%d",
@@ -613,7 +651,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
613 map_groups__insert(kmaps, curr_map); 651 map_groups__insert(kmaps, curr_map);
614 ++kernel_range; 652 ++kernel_range;
615 } 653 }
616 654filter_symbol:
617 if (filter && filter(curr_map, pos)) { 655 if (filter && filter(curr_map, pos)) {
618discard_symbol: rb_erase(&pos->rb_node, root); 656discard_symbol: rb_erase(&pos->rb_node, root);
619 symbol__delete(pos); 657 symbol__delete(pos);
@@ -621,8 +659,9 @@ discard_symbol: rb_erase(&pos->rb_node, root);
621 if (curr_map != map) { 659 if (curr_map != map) {
622 rb_erase(&pos->rb_node, root); 660 rb_erase(&pos->rb_node, root);
623 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); 661 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
624 } 662 ++moved;
625 count++; 663 } else
664 ++count;
626 } 665 }
627 } 666 }
628 667
@@ -632,7 +671,7 @@ discard_symbol: rb_erase(&pos->rb_node, root);
632 dso__set_loaded(curr_map->dso, curr_map->type); 671 dso__set_loaded(curr_map->dso, curr_map->type);
633 } 672 }
634 673
635 return count; 674 return count + moved;
636} 675}
637 676
638int dso__load_kallsyms(struct dso *self, const char *filename, 677int dso__load_kallsyms(struct dso *self, const char *filename,
@@ -641,7 +680,6 @@ int dso__load_kallsyms(struct dso *self, const char *filename,
641 if (dso__load_all_kallsyms(self, filename, map) < 0) 680 if (dso__load_all_kallsyms(self, filename, map) < 0)
642 return -1; 681 return -1;
643 682
644 symbols__fixup_end(&self->symbols[map->type]);
645 if (self->kernel == DSO_TYPE_GUEST_KERNEL) 683 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
646 self->origin = DSO__ORIG_GUEST_KERNEL; 684 self->origin = DSO__ORIG_GUEST_KERNEL;
647 else 685 else
@@ -831,8 +869,11 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map,
831 char sympltname[1024]; 869 char sympltname[1024];
832 Elf *elf; 870 Elf *elf;
833 int nr = 0, symidx, fd, err = 0; 871 int nr = 0, symidx, fd, err = 0;
872 char name[PATH_MAX];
834 873
835 fd = open(self->long_name, O_RDONLY); 874 snprintf(name, sizeof(name), "%s%s",
875 symbol_conf.symfs, self->long_name);
876 fd = open(name, O_RDONLY);
836 if (fd < 0) 877 if (fd < 0)
837 goto out; 878 goto out;
838 879
@@ -1121,6 +1162,13 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
1121 1162
1122 section_name = elf_sec__name(&shdr, secstrs); 1163 section_name = elf_sec__name(&shdr, secstrs);
1123 1164
1165 /* On ARM, symbols for thumb functions have 1 added to
1166 * the symbol address as a flag - remove it */
1167 if ((ehdr.e_machine == EM_ARM) &&
1168 (map->type == MAP__FUNCTION) &&
1169 (sym.st_value & 1))
1170 --sym.st_value;
1171
1124 if (self->kernel != DSO_TYPE_USER || kmodule) { 1172 if (self->kernel != DSO_TYPE_USER || kmodule) {
1125 char dso_name[PATH_MAX]; 1173 char dso_name[PATH_MAX];
1126 1174
@@ -1168,8 +1216,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
1168 } 1216 }
1169 1217
1170 if (curr_dso->adjust_symbols) { 1218 if (curr_dso->adjust_symbols) {
1171 pr_debug4("%s: adjusting symbol: st_value: %#Lx " 1219 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
1172 "sh_addr: %#Lx sh_offset: %#Lx\n", __func__, 1220 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
1173 (u64)sym.st_value, (u64)shdr.sh_addr, 1221 (u64)sym.st_value, (u64)shdr.sh_addr,
1174 (u64)shdr.sh_offset); 1222 (u64)shdr.sh_offset);
1175 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 1223 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
@@ -1444,16 +1492,19 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1444 self->origin++) { 1492 self->origin++) {
1445 switch (self->origin) { 1493 switch (self->origin) {
1446 case DSO__ORIG_BUILD_ID_CACHE: 1494 case DSO__ORIG_BUILD_ID_CACHE:
1447 if (dso__build_id_filename(self, name, size) == NULL) 1495 /* skip the locally configured cache if a symfs is given */
1496 if (symbol_conf.symfs[0] ||
1497 (dso__build_id_filename(self, name, size) == NULL)) {
1448 continue; 1498 continue;
1499 }
1449 break; 1500 break;
1450 case DSO__ORIG_FEDORA: 1501 case DSO__ORIG_FEDORA:
1451 snprintf(name, size, "/usr/lib/debug%s.debug", 1502 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1452 self->long_name); 1503 symbol_conf.symfs, self->long_name);
1453 break; 1504 break;
1454 case DSO__ORIG_UBUNTU: 1505 case DSO__ORIG_UBUNTU:
1455 snprintf(name, size, "/usr/lib/debug%s", 1506 snprintf(name, size, "%s/usr/lib/debug%s",
1456 self->long_name); 1507 symbol_conf.symfs, self->long_name);
1457 break; 1508 break;
1458 case DSO__ORIG_BUILDID: { 1509 case DSO__ORIG_BUILDID: {
1459 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1510 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -1465,19 +1516,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1465 sizeof(self->build_id), 1516 sizeof(self->build_id),
1466 build_id_hex); 1517 build_id_hex);
1467 snprintf(name, size, 1518 snprintf(name, size,
1468 "/usr/lib/debug/.build-id/%.2s/%s.debug", 1519 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1469 build_id_hex, build_id_hex + 2); 1520 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1470 } 1521 }
1471 break; 1522 break;
1472 case DSO__ORIG_DSO: 1523 case DSO__ORIG_DSO:
1473 snprintf(name, size, "%s", self->long_name); 1524 snprintf(name, size, "%s%s",
1525 symbol_conf.symfs, self->long_name);
1474 break; 1526 break;
1475 case DSO__ORIG_GUEST_KMODULE: 1527 case DSO__ORIG_GUEST_KMODULE:
1476 if (map->groups && map->groups->machine) 1528 if (map->groups && map->groups->machine)
1477 root_dir = map->groups->machine->root_dir; 1529 root_dir = map->groups->machine->root_dir;
1478 else 1530 else
1479 root_dir = ""; 1531 root_dir = "";
1480 snprintf(name, size, "%s%s", root_dir, self->long_name); 1532 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1533 root_dir, self->long_name);
1534 break;
1535
1536 case DSO__ORIG_KMODULE:
1537 snprintf(name, size, "%s%s", symbol_conf.symfs,
1538 self->long_name);
1481 break; 1539 break;
1482 1540
1483 default: 1541 default:
@@ -1772,21 +1830,24 @@ out_failure:
1772 return -1; 1830 return -1;
1773} 1831}
1774 1832
1775static int dso__load_vmlinux(struct dso *self, struct map *map, 1833int dso__load_vmlinux(struct dso *self, struct map *map,
1776 const char *vmlinux, symbol_filter_t filter) 1834 const char *vmlinux, symbol_filter_t filter)
1777{ 1835{
1778 int err = -1, fd; 1836 int err = -1, fd;
1837 char symfs_vmlinux[PATH_MAX];
1779 1838
1780 fd = open(vmlinux, O_RDONLY); 1839 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s",
1840 symbol_conf.symfs, vmlinux);
1841 fd = open(symfs_vmlinux, O_RDONLY);
1781 if (fd < 0) 1842 if (fd < 0)
1782 return -1; 1843 return -1;
1783 1844
1784 dso__set_loaded(self, map->type); 1845 dso__set_loaded(self, map->type);
1785 err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0); 1846 err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
1786 close(fd); 1847 close(fd);
1787 1848
1788 if (err > 0) 1849 if (err > 0)
1789 pr_debug("Using %s for symbols\n", vmlinux); 1850 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1790 1851
1791 return err; 1852 return err;
1792} 1853}
@@ -1828,8 +1889,8 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1828 const char *kallsyms_filename = NULL; 1889 const char *kallsyms_filename = NULL;
1829 char *kallsyms_allocated_filename = NULL; 1890 char *kallsyms_allocated_filename = NULL;
1830 /* 1891 /*
1831 * Step 1: if the user specified a vmlinux filename, use it and only 1892 * Step 1: if the user specified a kallsyms or vmlinux filename, use
1832 * it, reporting errors to the user if it cannot be used. 1893 * it and only it, reporting errors to the user if it cannot be used.
1833 * 1894 *
1834 * For instance, try to analyse an ARM perf.data file _without_ a 1895 * For instance, try to analyse an ARM perf.data file _without_ a
1835 * build-id, or if the user specifies the wrong path to the right 1896 * build-id, or if the user specifies the wrong path to the right
@@ -1842,6 +1903,11 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1842 * validation in dso__load_vmlinux and will bail out if they don't 1903 * validation in dso__load_vmlinux and will bail out if they don't
1843 * match. 1904 * match.
1844 */ 1905 */
1906 if (symbol_conf.kallsyms_name != NULL) {
1907 kallsyms_filename = symbol_conf.kallsyms_name;
1908 goto do_kallsyms;
1909 }
1910
1845 if (symbol_conf.vmlinux_name != NULL) { 1911 if (symbol_conf.vmlinux_name != NULL) {
1846 err = dso__load_vmlinux(self, map, 1912 err = dso__load_vmlinux(self, map,
1847 symbol_conf.vmlinux_name, filter); 1913 symbol_conf.vmlinux_name, filter);
@@ -1859,6 +1925,10 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1859 goto out_fixup; 1925 goto out_fixup;
1860 } 1926 }
1861 1927
1928 /* do not try local files if a symfs was given */
1929 if (symbol_conf.symfs[0] != 0)
1930 return -1;
1931
1862 /* 1932 /*
1863 * Say the kernel DSO was created when processing the build-id header table, 1933 * Say the kernel DSO was created when processing the build-id header table,
1864 * we have a build-id, so check if it is the same as the running kernel, 1934 * we have a build-id, so check if it is the same as the running kernel,
@@ -2123,14 +2193,55 @@ static struct dso *machine__create_kernel(struct machine *self)
2123 return kernel; 2193 return kernel;
2124} 2194}
2125 2195
2196struct process_args {
2197 u64 start;
2198};
2199
2200static int symbol__in_kernel(void *arg, const char *name,
2201 char type __used, u64 start, u64 end __used)
2202{
2203 struct process_args *args = arg;
2204
2205 if (strchr(name, '['))
2206 return 0;
2207
2208 args->start = start;
2209 return 1;
2210}
2211
2212/* Figure out the start address of kernel map from /proc/kallsyms */
2213static u64 machine__get_kernel_start_addr(struct machine *machine)
2214{
2215 const char *filename;
2216 char path[PATH_MAX];
2217 struct process_args args;
2218
2219 if (machine__is_host(machine)) {
2220 filename = "/proc/kallsyms";
2221 } else {
2222 if (machine__is_default_guest(machine))
2223 filename = (char *)symbol_conf.default_guest_kallsyms;
2224 else {
2225 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
2226 filename = path;
2227 }
2228 }
2229
2230 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
2231 return 0;
2232
2233 return args.start;
2234}
2235
2126int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) 2236int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
2127{ 2237{
2128 enum map_type type; 2238 enum map_type type;
2239 u64 start = machine__get_kernel_start_addr(self);
2129 2240
2130 for (type = 0; type < MAP__NR_TYPES; ++type) { 2241 for (type = 0; type < MAP__NR_TYPES; ++type) {
2131 struct kmap *kmap; 2242 struct kmap *kmap;
2132 2243
2133 self->vmlinux_maps[type] = map__new2(0, kernel, type); 2244 self->vmlinux_maps[type] = map__new2(start, kernel, type);
2134 if (self->vmlinux_maps[type] == NULL) 2245 if (self->vmlinux_maps[type] == NULL)
2135 return -1; 2246 return -1;
2136 2247
@@ -2208,9 +2319,6 @@ static int vmlinux_path__init(void)
2208 struct utsname uts; 2319 struct utsname uts;
2209 char bf[PATH_MAX]; 2320 char bf[PATH_MAX];
2210 2321
2211 if (uname(&uts) < 0)
2212 return -1;
2213
2214 vmlinux_path = malloc(sizeof(char *) * 5); 2322 vmlinux_path = malloc(sizeof(char *) * 5);
2215 if (vmlinux_path == NULL) 2323 if (vmlinux_path == NULL)
2216 return -1; 2324 return -1;
@@ -2223,6 +2331,14 @@ static int vmlinux_path__init(void)
2223 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2331 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2224 goto out_fail; 2332 goto out_fail;
2225 ++vmlinux_path__nr_entries; 2333 ++vmlinux_path__nr_entries;
2334
2335 /* only try running kernel version if no symfs was given */
2336 if (symbol_conf.symfs[0] != 0)
2337 return 0;
2338
2339 if (uname(&uts) < 0)
2340 return -1;
2341
2226 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 2342 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
2227 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 2343 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
2228 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2344 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
@@ -2282,6 +2398,8 @@ static int setup_list(struct strlist **list, const char *list_str,
2282 2398
2283int symbol__init(void) 2399int symbol__init(void)
2284{ 2400{
2401 const char *symfs;
2402
2285 if (symbol_conf.initialized) 2403 if (symbol_conf.initialized)
2286 return 0; 2404 return 0;
2287 2405
@@ -2310,6 +2428,18 @@ int symbol__init(void)
2310 symbol_conf.sym_list_str, "symbol") < 0) 2428 symbol_conf.sym_list_str, "symbol") < 0)
2311 goto out_free_comm_list; 2429 goto out_free_comm_list;
2312 2430
2431 /*
2432 * A path to symbols of "/" is identical to ""
2433 * reset here for simplicity.
2434 */
2435 symfs = realpath(symbol_conf.symfs, NULL);
2436 if (symfs == NULL)
2437 symfs = symbol_conf.symfs;
2438 if (strcmp(symfs, "/") == 0)
2439 symbol_conf.symfs = "";
2440 if (symfs != symbol_conf.symfs)
2441 free((void *)symfs);
2442
2313 symbol_conf.initialized = true; 2443 symbol_conf.initialized = true;
2314 return 0; 2444 return 0;
2315 2445
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 038f2201ee09..670cd1c88f54 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -72,6 +72,7 @@ struct symbol_conf {
72 show_cpu_utilization, 72 show_cpu_utilization,
73 initialized; 73 initialized;
74 const char *vmlinux_name, 74 const char *vmlinux_name,
75 *kallsyms_name,
75 *source_prefix, 76 *source_prefix,
76 *field_sep; 77 *field_sep;
77 const char *default_guest_vmlinux_name, 78 const char *default_guest_vmlinux_name,
@@ -85,6 +86,7 @@ struct symbol_conf {
85 struct strlist *dso_list, 86 struct strlist *dso_list,
86 *comm_list, 87 *comm_list,
87 *sym_list; 88 *sym_list;
89 const char *symfs;
88}; 90};
89 91
90extern struct symbol_conf symbol_conf; 92extern struct symbol_conf symbol_conf;
@@ -166,6 +168,8 @@ void dso__sort_by_name(struct dso *self, enum map_type type);
166struct dso *__dsos__findnew(struct list_head *head, const char *name); 168struct dso *__dsos__findnew(struct list_head *head, const char *name);
167 169
168int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); 170int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
171int dso__load_vmlinux(struct dso *self, struct map *map,
172 const char *vmlinux, symbol_filter_t filter);
169int dso__load_vmlinux_path(struct dso *self, struct map *map, 173int dso__load_vmlinux_path(struct dso *self, struct map *map,
170 symbol_filter_t filter); 174 symbol_filter_t filter);
171int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, 175int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,
@@ -213,7 +217,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
213int build_id__sprintf(const u8 *self, int len, char *bf); 217int build_id__sprintf(const u8 *self, int len, char *bf);
214int kallsyms__parse(const char *filename, void *arg, 218int kallsyms__parse(const char *filename, void *arg,
215 int (*process_symbol)(void *arg, const char *name, 219 int (*process_symbol)(void *arg, const char *name,
216 char type, u64 start)); 220 char type, u64 start, u64 end));
217 221
218void machine__destroy_kernel_maps(struct machine *self); 222void machine__destroy_kernel_maps(struct machine *self);
219int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); 223int __machine__create_kernel_maps(struct machine *self, struct dso *kernel);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 8c72d888e449..00f4eade2e3e 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -16,35 +16,50 @@ static int filter(const struct dirent *dir)
16 return 1; 16 return 1;
17} 17}
18 18
19int find_all_tid(int pid, pid_t ** all_tid) 19struct thread_map *thread_map__new_by_pid(pid_t pid)
20{ 20{
21 struct thread_map *threads;
21 char name[256]; 22 char name[256];
22 int items; 23 int items;
23 struct dirent **namelist = NULL; 24 struct dirent **namelist = NULL;
24 int ret = 0;
25 int i; 25 int i;
26 26
27 sprintf(name, "/proc/%d/task", pid); 27 sprintf(name, "/proc/%d/task", pid);
28 items = scandir(name, &namelist, filter, NULL); 28 items = scandir(name, &namelist, filter, NULL);
29 if (items <= 0) 29 if (items <= 0)
30 return -ENOENT; 30 return NULL;
31 *all_tid = malloc(sizeof(pid_t) * items);
32 if (!*all_tid) {
33 ret = -ENOMEM;
34 goto failure;
35 }
36
37 for (i = 0; i < items; i++)
38 (*all_tid)[i] = atoi(namelist[i]->d_name);
39 31
40 ret = items; 32 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
33 if (threads != NULL) {
34 for (i = 0; i < items; i++)
35 threads->map[i] = atoi(namelist[i]->d_name);
36 threads->nr = items;
37 }
41 38
42failure:
43 for (i=0; i<items; i++) 39 for (i=0; i<items; i++)
44 free(namelist[i]); 40 free(namelist[i]);
45 free(namelist); 41 free(namelist);
46 42
47 return ret; 43 return threads;
44}
45
46struct thread_map *thread_map__new_by_tid(pid_t tid)
47{
48 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
49
50 if (threads != NULL) {
51 threads->map[0] = tid;
52 threads->nr = 1;
53 }
54
55 return threads;
56}
57
58struct thread_map *thread_map__new(pid_t pid, pid_t tid)
59{
60 if (pid != -1)
61 return thread_map__new_by_pid(pid);
62 return thread_map__new_by_tid(tid);
48} 63}
49 64
50static struct thread *thread__new(pid_t pid) 65static struct thread *thread__new(pid_t pid)
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 688500ff826f..d7574101054a 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,11 +18,24 @@ struct thread {
18 int comm_len; 18 int comm_len;
19}; 19};
20 20
21struct thread_map {
22 int nr;
23 int map[];
24};
25
21struct perf_session; 26struct perf_session;
22 27
23void thread__delete(struct thread *self); 28void thread__delete(struct thread *self);
24 29
25int find_all_tid(int pid, pid_t ** all_tid); 30struct thread_map *thread_map__new_by_pid(pid_t pid);
31struct thread_map *thread_map__new_by_tid(pid_t tid);
32struct thread_map *thread_map__new(pid_t pid, pid_t tid);
33
34static inline void thread_map__delete(struct thread_map *threads)
35{
36 free(threads);
37}
38
26int thread__set_comm(struct thread *self, const char *comm); 39int thread__set_comm(struct thread *self, const char *comm);
27int thread__comm_len(struct thread *self); 40int thread__comm_len(struct thread *self);
28struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); 41struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index b1572601286c..35729f4c40cb 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -34,11 +34,13 @@
34#include <ctype.h> 34#include <ctype.h>
35#include <errno.h> 35#include <errno.h>
36#include <stdbool.h> 36#include <stdbool.h>
37#include <linux/list.h>
37#include <linux/kernel.h> 38#include <linux/kernel.h>
38 39
39#include "../perf.h" 40#include "../perf.h"
40#include "trace-event.h" 41#include "trace-event.h"
41#include "debugfs.h" 42#include "debugfs.h"
43#include "evsel.h"
42 44
43#define VERSION "0.5" 45#define VERSION "0.5"
44 46
@@ -469,16 +471,17 @@ out:
469} 471}
470 472
471static struct tracepoint_path * 473static struct tracepoint_path *
472get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events) 474get_tracepoints_path(struct list_head *pattrs)
473{ 475{
474 struct tracepoint_path path, *ppath = &path; 476 struct tracepoint_path path, *ppath = &path;
475 int i, nr_tracepoints = 0; 477 struct perf_evsel *pos;
478 int nr_tracepoints = 0;
476 479
477 for (i = 0; i < nb_events; i++) { 480 list_for_each_entry(pos, pattrs, node) {
478 if (pattrs[i].type != PERF_TYPE_TRACEPOINT) 481 if (pos->attr.type != PERF_TYPE_TRACEPOINT)
479 continue; 482 continue;
480 ++nr_tracepoints; 483 ++nr_tracepoints;
481 ppath->next = tracepoint_id_to_path(pattrs[i].config); 484 ppath->next = tracepoint_id_to_path(pos->attr.config);
482 if (!ppath->next) 485 if (!ppath->next)
483 die("%s\n", "No memory to alloc tracepoints list"); 486 die("%s\n", "No memory to alloc tracepoints list");
484 ppath = ppath->next; 487 ppath = ppath->next;
@@ -487,21 +490,21 @@ get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events)
487 return nr_tracepoints > 0 ? path.next : NULL; 490 return nr_tracepoints > 0 ? path.next : NULL;
488} 491}
489 492
490bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events) 493bool have_tracepoints(struct list_head *pattrs)
491{ 494{
492 int i; 495 struct perf_evsel *pos;
493 496
494 for (i = 0; i < nb_events; i++) 497 list_for_each_entry(pos, pattrs, node)
495 if (pattrs[i].type == PERF_TYPE_TRACEPOINT) 498 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
496 return true; 499 return true;
497 500
498 return false; 501 return false;
499} 502}
500 503
501int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events) 504int read_tracing_data(int fd, struct list_head *pattrs)
502{ 505{
503 char buf[BUFSIZ]; 506 char buf[BUFSIZ];
504 struct tracepoint_path *tps = get_tracepoints_path(pattrs, nb_events); 507 struct tracepoint_path *tps = get_tracepoints_path(pattrs);
505 508
506 /* 509 /*
507 * What? No tracepoints? No sense writing anything here, bail out. 510 * What? No tracepoints? No sense writing anything here, bail out.
@@ -545,14 +548,13 @@ int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
545 return 0; 548 return 0;
546} 549}
547 550
548ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, 551ssize_t read_tracing_data_size(int fd, struct list_head *pattrs)
549 int nb_events)
550{ 552{
551 ssize_t size; 553 ssize_t size;
552 int err = 0; 554 int err = 0;
553 555
554 calc_data_size = 1; 556 calc_data_size = 1;
555 err = read_tracing_data(fd, pattrs, nb_events); 557 err = read_tracing_data(fd, pattrs);
556 size = calc_data_size - 1; 558 size = calc_data_size - 1;
557 calc_data_size = 0; 559 calc_data_size = 0;
558 560
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b3e86b1e4444..b5f12ca24d99 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -262,9 +262,8 @@ raw_field_value(struct event *event, const char *name, void *data);
262void *raw_field_ptr(struct event *event, const char *name, void *data); 262void *raw_field_ptr(struct event *event, const char *name, void *data);
263unsigned long long eval_flag(const char *flag); 263unsigned long long eval_flag(const char *flag);
264 264
265int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); 265int read_tracing_data(int fd, struct list_head *pattrs);
266ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, 266ssize_t read_tracing_data_size(int fd, struct list_head *pattrs);
267 int nb_events);
268 267
269/* taken from kernel/trace/trace.h */ 268/* taken from kernel/trace/trace.h */
270enum trace_flag_type { 269enum trace_flag_type {
diff --git a/tools/perf/util/types.h b/tools/perf/util/types.h
index 7d6b8331f898..5f3689a3d085 100644
--- a/tools/perf/util/types.h
+++ b/tools/perf/util/types.h
@@ -1,12 +1,14 @@
1#ifndef __PERF_TYPES_H 1#ifndef __PERF_TYPES_H
2#define __PERF_TYPES_H 2#define __PERF_TYPES_H
3 3
4#include <stdint.h>
5
4/* 6/*
5 * We define u64 as unsigned long long for every architecture 7 * We define u64 as uint64_t for every architecture
6 * so that we can print it with %Lx without getting warnings. 8 * so that we can print it with "%"PRIx64 without getting warnings.
7 */ 9 */
8typedef unsigned long long u64; 10typedef uint64_t u64;
9typedef signed long long s64; 11typedef int64_t s64;
10typedef unsigned int u32; 12typedef unsigned int u32;
11typedef signed int s32; 13typedef signed int s32;
12typedef unsigned short u16; 14typedef unsigned short u16;
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index ebda8c3fde9e..60c463c16028 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -350,7 +350,7 @@ static char *callchain_list__sym_name(struct callchain_list *self,
350 if (self->ms.sym) 350 if (self->ms.sym)
351 return self->ms.sym->name; 351 return self->ms.sym->name;
352 352
353 snprintf(bf, bfsize, "%#Lx", self->ip); 353 snprintf(bf, bfsize, "%#" PRIx64, self->ip);
354 return bf; 354 return bf;
355} 355}
356 356
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index e35437dfa5b4..e5158369106e 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -1,5 +1,6 @@
1#include "../libslang.h" 1#include "../libslang.h"
2#include <elf.h> 2#include <elf.h>
3#include <inttypes.h>
3#include <sys/ttydefaults.h> 4#include <sys/ttydefaults.h>
4#include <ctype.h> 5#include <ctype.h>
5#include <string.h> 6#include <string.h>
@@ -57,7 +58,7 @@ static void map_browser__write(struct ui_browser *self, void *nd, int row)
57 int width; 58 int width;
58 59
59 ui_browser__set_percent_color(self, 0, current_entry); 60 ui_browser__set_percent_color(self, 0, current_entry);
60 slsmg_printf("%*llx %*llx %c ", 61 slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ",
61 mb->addrlen, sym->start, mb->addrlen, sym->end, 62 mb->addrlen, sym->start, mb->addrlen, sym->end,
62 sym->binding == STB_GLOBAL ? 'g' : 63 sym->binding == STB_GLOBAL ? 'g' :
63 sym->binding == STB_LOCAL ? 'l' : 'w'); 64 sym->binding == STB_LOCAL ? 'l' : 'w');
@@ -150,6 +151,6 @@ int map__browse(struct map *self)
150 ++mb.b.nr_entries; 151 ++mb.b.nr_entries;
151 } 152 }
152 153
153 mb.addrlen = snprintf(tmp, sizeof(tmp), "%llx", maxaddr); 154 mb.addrlen = snprintf(tmp, sizeof(tmp), "%" PRIx64, maxaddr);
154 return map_browser__run(&mb); 155 return map_browser__run(&mb);
155} 156}
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index 9706d9d40279..7b5a8926624e 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -104,9 +104,24 @@ out_destroy_form:
104 return rc; 104 return rc;
105} 105}
106 106
107static const char yes[] = "Yes", no[] = "No",
108 warning_str[] = "Warning!", ok[] = "Ok";
109
107bool ui__dialog_yesno(const char *msg) 110bool ui__dialog_yesno(const char *msg)
108{ 111{
109 /* newtWinChoice should really be accepting const char pointers... */ 112 /* newtWinChoice should really be accepting const char pointers... */
110 char yes[] = "Yes", no[] = "No"; 113 return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1;
111 return newtWinChoice(NULL, yes, no, (char *)msg) == 1; 114}
115
116void ui__warning(const char *format, ...)
117{
118 va_list args;
119
120 va_start(args, format);
121 if (use_browser > 0)
122 newtWinMessagev((char *)warning_str, (char *)ok,
123 (char *)format, args);
124 else
125 vfprintf(stderr, format, args);
126 va_end(args);
112} 127}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 214265674ddd..5b3ea49aa63e 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -114,3 +114,20 @@ unsigned long convert_unit(unsigned long value, char *unit)
114 114
115 return value; 115 return value;
116} 116}
117
118int readn(int fd, void *buf, size_t n)
119{
120 void *buf_start = buf;
121
122 while (n) {
123 int ret = read(fd, buf, n);
124
125 if (ret <= 0)
126 return ret;
127
128 n -= ret;
129 buf += ret;
130 }
131
132 return buf - buf_start;
133}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 7562707ddd1c..e833f26f3bfc 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -265,6 +265,7 @@ void argv_free(char **argv);
265bool strglobmatch(const char *str, const char *pat); 265bool strglobmatch(const char *str, const char *pat);
266bool strlazymatch(const char *str, const char *pat); 266bool strlazymatch(const char *str, const char *pat);
267unsigned long convert_unit(unsigned long value, char *unit); 267unsigned long convert_unit(unsigned long value, char *unit);
268int readn(int fd, void *buf, size_t size);
268 269
269#define _STR(x) #x 270#define _STR(x) #x
270#define STR(x) _STR(x) 271#define STR(x) _STR(x)
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index cfa55d686e3b..bdd33470b235 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -150,7 +150,7 @@ static void perf_read_values__display_pretty(FILE *fp,
150 if (width > tidwidth) 150 if (width > tidwidth)
151 tidwidth = width; 151 tidwidth = width;
152 for (j = 0; j < values->counters; j++) { 152 for (j = 0; j < values->counters; j++) {
153 width = snprintf(NULL, 0, "%Lu", values->value[i][j]); 153 width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
154 if (width > counterwidth[j]) 154 if (width > counterwidth[j])
155 counterwidth[j] = width; 155 counterwidth[j] = width;
156 } 156 }
@@ -165,7 +165,7 @@ static void perf_read_values__display_pretty(FILE *fp,
165 fprintf(fp, " %*d %*d", pidwidth, values->pid[i], 165 fprintf(fp, " %*d %*d", pidwidth, values->pid[i],
166 tidwidth, values->tid[i]); 166 tidwidth, values->tid[i]);
167 for (j = 0; j < values->counters; j++) 167 for (j = 0; j < values->counters; j++)
168 fprintf(fp, " %*Lu", 168 fprintf(fp, " %*" PRIu64,
169 counterwidth[j], values->value[i][j]); 169 counterwidth[j], values->value[i][j]);
170 fprintf(fp, "\n"); 170 fprintf(fp, "\n");
171 } 171 }
@@ -196,13 +196,13 @@ static void perf_read_values__display_raw(FILE *fp,
196 width = strlen(values->countername[j]); 196 width = strlen(values->countername[j]);
197 if (width > namewidth) 197 if (width > namewidth)
198 namewidth = width; 198 namewidth = width;
199 width = snprintf(NULL, 0, "%llx", values->counterrawid[j]); 199 width = snprintf(NULL, 0, "%" PRIx64, values->counterrawid[j]);
200 if (width > rawwidth) 200 if (width > rawwidth)
201 rawwidth = width; 201 rawwidth = width;
202 } 202 }
203 for (i = 0; i < values->threads; i++) { 203 for (i = 0; i < values->threads; i++) {
204 for (j = 0; j < values->counters; j++) { 204 for (j = 0; j < values->counters; j++) {
205 width = snprintf(NULL, 0, "%Lu", values->value[i][j]); 205 width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
206 if (width > countwidth) 206 if (width > countwidth)
207 countwidth = width; 207 countwidth = width;
208 } 208 }
@@ -214,7 +214,7 @@ static void perf_read_values__display_raw(FILE *fp,
214 countwidth, "Count"); 214 countwidth, "Count");
215 for (i = 0; i < values->threads; i++) 215 for (i = 0; i < values->threads; i++)
216 for (j = 0; j < values->counters; j++) 216 for (j = 0; j < values->counters; j++)
217 fprintf(fp, " %*d %*d %*s %*llx %*Lu\n", 217 fprintf(fp, " %*d %*d %*s %*" PRIx64 " %*" PRIu64,
218 pidwidth, values->pid[i], 218 pidwidth, values->pid[i],
219 tidwidth, values->tid[i], 219 tidwidth, values->tid[i],
220 namewidth, values->countername[j], 220 namewidth, values->countername[j],
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
new file mode 100644
index 000000000000..22afbf6c536a
--- /dev/null
+++ b/tools/perf/util/xyarray.c
@@ -0,0 +1,20 @@
1#include "xyarray.h"
2#include "util.h"
3
4struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
5{
6 size_t row_size = ylen * entry_size;
7 struct xyarray *xy = zalloc(sizeof(*xy) + xlen * row_size);
8
9 if (xy != NULL) {
10 xy->entry_size = entry_size;
11 xy->row_size = row_size;
12 }
13
14 return xy;
15}
16
17void xyarray__delete(struct xyarray *xy)
18{
19 free(xy);
20}
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
new file mode 100644
index 000000000000..c488a07275dd
--- /dev/null
+++ b/tools/perf/util/xyarray.h
@@ -0,0 +1,20 @@
1#ifndef _PERF_XYARRAY_H_
2#define _PERF_XYARRAY_H_ 1
3
4#include <sys/types.h>
5
6struct xyarray {
7 size_t row_size;
8 size_t entry_size;
9 char contents[];
10};
11
12struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
13void xyarray__delete(struct xyarray *xy);
14
15static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
16{
17 return &xy->contents[x * xy->row_size + y * xy->entry_size];
18}
19
20#endif /* _PERF_XYARRAY_H_ */
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
new file mode 100644
index 000000000000..fd8e1f1297aa
--- /dev/null
+++ b/tools/power/x86/turbostat/Makefile
@@ -0,0 +1,8 @@
1turbostat : turbostat.c
2
3clean :
4 rm -f turbostat
5
6install :
7 install turbostat /usr/bin/turbostat
8 install turbostat.8 /usr/share/man/man8
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
new file mode 100644
index 000000000000..ff75125deed0
--- /dev/null
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -0,0 +1,172 @@
1.TH TURBOSTAT 8
2.SH NAME
3turbostat \- Report processor frequency and idle statistics
4.SH SYNOPSIS
5.ft B
6.B turbostat
7.RB [ "\-v" ]
8.RB [ "\-M MSR#" ]
9.RB command
10.br
11.B turbostat
12.RB [ "\-v" ]
13.RB [ "\-M MSR#" ]
14.RB [ "\-i interval_sec" ]
15.SH DESCRIPTION
16\fBturbostat \fP reports processor topology, frequency
17and idle power state statistics on modern X86 processors.
18Either \fBcommand\fP is forked and statistics are printed
19upon its completion, or statistics are printed periodically.
20
21\fBturbostat \fP
22requires that the processor
23supports an "invariant" TSC, plus the APERF and MPERF MSRs.
24\fBturbostat \fP will report idle cpu power state residency
25on processors that additionally support C-state residency counters.
26
27.SS Options
28The \fB-v\fP option increases verbosity.
29.PP
30The \fB-M MSR#\fP option dumps the specified MSR,
31in addition to the usual frequency and idle statistics.
32.PP
33The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds.
34The default is 5 seconds.
35.PP
36The \fBcommand\fP parameter forks \fBcommand\fP and upon its exit,
37displays the statistics gathered since it was forked.
38.PP
39.SH FIELD DESCRIPTIONS
40.nf
41\fBpkg\fP processor package number.
42\fBcore\fP processor core number.
43\fBCPU\fP Linux CPU (logical processor) number.
44\fB%c0\fP percent of the interval that the CPU retired instructions.
45\fBGHz\fP average clock rate while the CPU was in c0 state.
46\fBTSC\fP average GHz that the TSC ran during the entire interval.
47\fB%c1, %c3, %c6\fP show the percentage residency in hardware core idle states.
48\fB%pc3, %pc6\fP percentage residency in hardware package idle states.
49.fi
50.PP
51.SH EXAMPLE
52Without any parameters, turbostat prints out counters ever 5 seconds.
53(override interval with "-i sec" option, or specify a command
54for turbostat to fork).
55
56The first row of statistics reflect the average for the entire system.
57Subsequent rows show per-CPU statistics.
58
59.nf
60[root@x980]# ./turbostat
61core CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6
62 0.04 1.62 3.38 0.11 0.00 99.85 0.00 95.07
63 0 0 0.04 1.62 3.38 0.06 0.00 99.90 0.00 95.07
64 0 6 0.02 1.62 3.38 0.08 0.00 99.90 0.00 95.07
65 1 2 0.10 1.62 3.38 0.29 0.00 99.61 0.00 95.07
66 1 8 0.11 1.62 3.38 0.28 0.00 99.61 0.00 95.07
67 2 4 0.01 1.62 3.38 0.01 0.00 99.98 0.00 95.07
68 2 10 0.01 1.61 3.38 0.02 0.00 99.98 0.00 95.07
69 8 1 0.07 1.62 3.38 0.15 0.00 99.78 0.00 95.07
70 8 7 0.03 1.62 3.38 0.19 0.00 99.78 0.00 95.07
71 9 3 0.01 1.62 3.38 0.02 0.00 99.98 0.00 95.07
72 9 9 0.01 1.62 3.38 0.02 0.00 99.98 0.00 95.07
73 10 5 0.01 1.62 3.38 0.13 0.00 99.86 0.00 95.07
74 10 11 0.08 1.62 3.38 0.05 0.00 99.86 0.00 95.07
75.fi
76.SH VERBOSE EXAMPLE
77The "-v" option adds verbosity to the output:
78
79.nf
80GenuineIntel 11 CPUID levels; family:model:stepping 0x6:2c:2 (6:44:2)
8112 * 133 = 1600 MHz max efficiency
8225 * 133 = 3333 MHz TSC frequency
8326 * 133 = 3467 MHz max turbo 4 active cores
8426 * 133 = 3467 MHz max turbo 3 active cores
8527 * 133 = 3600 MHz max turbo 2 active cores
8627 * 133 = 3600 MHz max turbo 1 active cores
87
88.fi
89The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency
90available at the minimum package voltage. The \fBTSC frequency\fP is the nominal
91maximum frequency of the processor if turbo-mode were not available. This frequency
92should be sustainable on all CPUs indefinitely, given nominal power and cooling.
93The remaining rows show what maximum turbo frequency is possible
94depending on the number of idle cores. Note that this information is
95not available on all processors.
96.SH FORK EXAMPLE
97If turbostat is invoked with a command, it will fork that command
98and output the statistics gathered when the command exits.
99eg. Here a cycle soaker is run on 1 CPU (see %c0) for a few seconds
100until ^C while the other CPUs are mostly idle:
101
102.nf
103[root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null
104
105^Ccore CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6
106 8.49 3.63 3.38 16.23 0.66 74.63 0.00 0.00
107 0 0 1.22 3.62 3.38 32.18 0.00 66.60 0.00 0.00
108 0 6 0.40 3.61 3.38 33.00 0.00 66.60 0.00 0.00
109 1 2 0.11 3.14 3.38 0.19 3.95 95.75 0.00 0.00
110 1 8 0.05 2.88 3.38 0.25 3.95 95.75 0.00 0.00
111 2 4 0.00 3.13 3.38 0.02 0.00 99.98 0.00 0.00
112 2 10 0.00 3.09 3.38 0.02 0.00 99.98 0.00 0.00
113 8 1 0.04 3.50 3.38 14.43 0.00 85.54 0.00 0.00
114 8 7 0.03 2.98 3.38 14.43 0.00 85.54 0.00 0.00
115 9 3 0.00 3.16 3.38 100.00 0.00 0.00 0.00 0.00
116 9 9 99.93 3.63 3.38 0.06 0.00 0.00 0.00 0.00
117 10 5 0.01 2.82 3.38 0.08 0.00 99.91 0.00 0.00
118 10 11 0.02 3.36 3.38 0.06 0.00 99.91 0.00 0.00
1196.950866 sec
120
121.fi
122Above the cycle soaker drives cpu9 up 3.6 Ghz turbo limit
123while the other processors are generally in various states of idle.
124
125Note that cpu3 is an HT sibling sharing core9
126with cpu9, and thus it is unable to get to an idle state
127deeper than c1 while cpu9 is busy.
128
129Note that turbostat reports average GHz of 3.61, while
130the arithmetic average of the GHz column above is 3.24.
131This is a weighted average, where the weight is %c0. ie. it is the total number of
132un-halted cycles elapsed per time divided by the number of CPUs.
133.SH NOTES
134
135.B "turbostat "
136must be run as root.
137
138.B "turbostat "
139reads hardware counters, but doesn't write them.
140So it will not interfere with the OS or other programs, including
141multiple invocations of itself.
142
143\fBturbostat \fP
144may work poorly on Linux-2.6.20 through 2.6.29,
145as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF
146in those kernels.
147
148The APERF, MPERF MSRs are defined to count non-halted cycles.
149Although it is not guaranteed by the architecture, turbostat assumes
150that they count at TSC rate, which is true on all processors tested to date.
151
152.SH REFERENCES
153"Intel® Turbo Boost Technology
154in Intel® Core™ Microarchitecture (Nehalem) Based Processors"
155http://download.intel.com/design/processor/applnots/320354.pdf
156
157"Intel® 64 and IA-32 Architectures Software Developer's Manual
158Volume 3B: System Programming Guide"
159http://www.intel.com/products/processor/manuals/
160
161.SH FILES
162.ta
163.nf
164/dev/cpu/*/msr
165.fi
166
167.SH "SEE ALSO"
168msr(4), vmstat(8)
169.PP
170.SH AUTHORS
171.nf
172Written by Len Brown <len.brown@intel.com>
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
new file mode 100644
index 000000000000..4c6983de6fd9
--- /dev/null
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -0,0 +1,1048 @@
1/*
2 * turbostat -- show CPU frequency and C-state residency
3 * on modern Intel turbo-capable processors.
4 *
5 * Copyright (c) 2010, Intel Corporation.
6 * Len Brown <len.brown@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22#include <stdio.h>
23#include <unistd.h>
24#include <sys/types.h>
25#include <sys/wait.h>
26#include <sys/stat.h>
27#include <sys/resource.h>
28#include <fcntl.h>
29#include <signal.h>
30#include <sys/time.h>
31#include <stdlib.h>
32#include <dirent.h>
33#include <string.h>
34#include <ctype.h>
35
36#define MSR_TSC 0x10
37#define MSR_NEHALEM_PLATFORM_INFO 0xCE
38#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
39#define MSR_APERF 0xE8
40#define MSR_MPERF 0xE7
41#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */
42#define MSR_PKG_C3_RESIDENCY 0x3F8
43#define MSR_PKG_C6_RESIDENCY 0x3F9
44#define MSR_PKG_C7_RESIDENCY 0x3FA /* SNB only */
45#define MSR_CORE_C3_RESIDENCY 0x3FC
46#define MSR_CORE_C6_RESIDENCY 0x3FD
47#define MSR_CORE_C7_RESIDENCY 0x3FE /* SNB only */
48
49char *proc_stat = "/proc/stat";
50unsigned int interval_sec = 5; /* set with -i interval_sec */
51unsigned int verbose; /* set with -v */
52unsigned int skip_c0;
53unsigned int skip_c1;
54unsigned int do_nhm_cstates;
55unsigned int do_snb_cstates;
56unsigned int has_aperf;
57unsigned int units = 1000000000; /* Ghz etc */
58unsigned int genuine_intel;
59unsigned int has_invariant_tsc;
60unsigned int do_nehalem_platform_info;
61unsigned int do_nehalem_turbo_ratio_limit;
62unsigned int extra_msr_offset;
63double bclk;
64unsigned int show_pkg;
65unsigned int show_core;
66unsigned int show_cpu;
67
68int aperf_mperf_unstable;
69int backwards_count;
70char *progname;
71int need_reinitialize;
72
73int num_cpus;
74
75typedef struct per_cpu_counters {
76 unsigned long long tsc; /* per thread */
77 unsigned long long aperf; /* per thread */
78 unsigned long long mperf; /* per thread */
79 unsigned long long c1; /* per thread (calculated) */
80 unsigned long long c3; /* per core */
81 unsigned long long c6; /* per core */
82 unsigned long long c7; /* per core */
83 unsigned long long pc2; /* per package */
84 unsigned long long pc3; /* per package */
85 unsigned long long pc6; /* per package */
86 unsigned long long pc7; /* per package */
87 unsigned long long extra_msr; /* per thread */
88 int pkg;
89 int core;
90 int cpu;
91 struct per_cpu_counters *next;
92} PCC;
93
94PCC *pcc_even;
95PCC *pcc_odd;
96PCC *pcc_delta;
97PCC *pcc_average;
98struct timeval tv_even;
99struct timeval tv_odd;
100struct timeval tv_delta;
101
102unsigned long long get_msr(int cpu, off_t offset)
103{
104 ssize_t retval;
105 unsigned long long msr;
106 char pathname[32];
107 int fd;
108
109 sprintf(pathname, "/dev/cpu/%d/msr", cpu);
110 fd = open(pathname, O_RDONLY);
111 if (fd < 0) {
112 perror(pathname);
113 need_reinitialize = 1;
114 return 0;
115 }
116
117 retval = pread(fd, &msr, sizeof msr, offset);
118 if (retval != sizeof msr) {
119 fprintf(stderr, "cpu%d pread(..., 0x%zx) = %jd\n",
120 cpu, offset, retval);
121 exit(-2);
122 }
123
124 close(fd);
125 return msr;
126}
127
128void print_header()
129{
130 if (show_pkg)
131 fprintf(stderr, "pkg ");
132 if (show_core)
133 fprintf(stderr, "core");
134 if (show_cpu)
135 fprintf(stderr, " CPU");
136 if (do_nhm_cstates)
137 fprintf(stderr, " %%c0 ");
138 if (has_aperf)
139 fprintf(stderr, " GHz");
140 fprintf(stderr, " TSC");
141 if (do_nhm_cstates)
142 fprintf(stderr, " %%c1 ");
143 if (do_nhm_cstates)
144 fprintf(stderr, " %%c3 ");
145 if (do_nhm_cstates)
146 fprintf(stderr, " %%c6 ");
147 if (do_snb_cstates)
148 fprintf(stderr, " %%c7 ");
149 if (do_snb_cstates)
150 fprintf(stderr, " %%pc2 ");
151 if (do_nhm_cstates)
152 fprintf(stderr, " %%pc3 ");
153 if (do_nhm_cstates)
154 fprintf(stderr, " %%pc6 ");
155 if (do_snb_cstates)
156 fprintf(stderr, " %%pc7 ");
157 if (extra_msr_offset)
158 fprintf(stderr, " MSR 0x%x ", extra_msr_offset);
159
160 putc('\n', stderr);
161}
162
163void dump_pcc(PCC *pcc)
164{
165 fprintf(stderr, "package: %d ", pcc->pkg);
166 fprintf(stderr, "core:: %d ", pcc->core);
167 fprintf(stderr, "CPU: %d ", pcc->cpu);
168 fprintf(stderr, "TSC: %016llX\n", pcc->tsc);
169 fprintf(stderr, "c3: %016llX\n", pcc->c3);
170 fprintf(stderr, "c6: %016llX\n", pcc->c6);
171 fprintf(stderr, "c7: %016llX\n", pcc->c7);
172 fprintf(stderr, "aperf: %016llX\n", pcc->aperf);
173 fprintf(stderr, "pc2: %016llX\n", pcc->pc2);
174 fprintf(stderr, "pc3: %016llX\n", pcc->pc3);
175 fprintf(stderr, "pc6: %016llX\n", pcc->pc6);
176 fprintf(stderr, "pc7: %016llX\n", pcc->pc7);
177 fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, pcc->extra_msr);
178}
179
180void dump_list(PCC *pcc)
181{
182 printf("dump_list 0x%p\n", pcc);
183
184 for (; pcc; pcc = pcc->next)
185 dump_pcc(pcc);
186}
187
188void print_pcc(PCC *p)
189{
190 double interval_float;
191
192 interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0;
193
194 /* topology columns, print blanks on 1st (average) line */
195 if (p == pcc_average) {
196 if (show_pkg)
197 fprintf(stderr, " ");
198 if (show_core)
199 fprintf(stderr, " ");
200 if (show_cpu)
201 fprintf(stderr, " ");
202 } else {
203 if (show_pkg)
204 fprintf(stderr, "%4d", p->pkg);
205 if (show_core)
206 fprintf(stderr, "%4d", p->core);
207 if (show_cpu)
208 fprintf(stderr, "%4d", p->cpu);
209 }
210
211 /* %c0 */
212 if (do_nhm_cstates) {
213 if (!skip_c0)
214 fprintf(stderr, "%7.2f", 100.0 * p->mperf/p->tsc);
215 else
216 fprintf(stderr, " ****");
217 }
218
219 /* GHz */
220 if (has_aperf) {
221 if (!aperf_mperf_unstable) {
222 fprintf(stderr, "%5.2f",
223 1.0 * p->tsc / units * p->aperf /
224 p->mperf / interval_float);
225 } else {
226 if (p->aperf > p->tsc || p->mperf > p->tsc) {
227 fprintf(stderr, " ****");
228 } else {
229 fprintf(stderr, "%4.1f*",
230 1.0 * p->tsc /
231 units * p->aperf /
232 p->mperf / interval_float);
233 }
234 }
235 }
236
237 /* TSC */
238 fprintf(stderr, "%5.2f", 1.0 * p->tsc/units/interval_float);
239
240 if (do_nhm_cstates) {
241 if (!skip_c1)
242 fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc);
243 else
244 fprintf(stderr, " ****");
245 }
246 if (do_nhm_cstates)
247 fprintf(stderr, "%7.2f", 100.0 * p->c3/p->tsc);
248 if (do_nhm_cstates)
249 fprintf(stderr, "%7.2f", 100.0 * p->c6/p->tsc);
250 if (do_snb_cstates)
251 fprintf(stderr, "%7.2f", 100.0 * p->c7/p->tsc);
252 if (do_snb_cstates)
253 fprintf(stderr, "%7.2f", 100.0 * p->pc2/p->tsc);
254 if (do_nhm_cstates)
255 fprintf(stderr, "%7.2f", 100.0 * p->pc3/p->tsc);
256 if (do_nhm_cstates)
257 fprintf(stderr, "%7.2f", 100.0 * p->pc6/p->tsc);
258 if (do_snb_cstates)
259 fprintf(stderr, "%7.2f", 100.0 * p->pc7/p->tsc);
260 if (extra_msr_offset)
261 fprintf(stderr, " 0x%016llx", p->extra_msr);
262 putc('\n', stderr);
263}
264
265void print_counters(PCC *cnt)
266{
267 PCC *pcc;
268
269 print_header();
270
271 if (num_cpus > 1)
272 print_pcc(pcc_average);
273
274 for (pcc = cnt; pcc != NULL; pcc = pcc->next)
275 print_pcc(pcc);
276
277}
278
279#define SUBTRACT_COUNTER(after, before, delta) (delta = (after - before), (before > after))
280
281
282int compute_delta(PCC *after, PCC *before, PCC *delta)
283{
284 int errors = 0;
285 int perf_err = 0;
286
287 skip_c0 = skip_c1 = 0;
288
289 for ( ; after && before && delta;
290 after = after->next, before = before->next, delta = delta->next) {
291 if (before->cpu != after->cpu) {
292 printf("cpu configuration changed: %d != %d\n",
293 before->cpu, after->cpu);
294 return -1;
295 }
296
297 if (SUBTRACT_COUNTER(after->tsc, before->tsc, delta->tsc)) {
298 fprintf(stderr, "cpu%d TSC went backwards %llX to %llX\n",
299 before->cpu, before->tsc, after->tsc);
300 errors++;
301 }
302 /* check for TSC < 1 Mcycles over interval */
303 if (delta->tsc < (1000 * 1000)) {
304 fprintf(stderr, "Insanely slow TSC rate,"
305 " TSC stops in idle?\n");
306 fprintf(stderr, "You can disable all c-states"
307 " by booting with \"idle=poll\"\n");
308 fprintf(stderr, "or just the deep ones with"
309 " \"processor.max_cstate=1\"\n");
310 exit(-3);
311 }
312 if (SUBTRACT_COUNTER(after->c3, before->c3, delta->c3)) {
313 fprintf(stderr, "cpu%d c3 counter went backwards %llX to %llX\n",
314 before->cpu, before->c3, after->c3);
315 errors++;
316 }
317 if (SUBTRACT_COUNTER(after->c6, before->c6, delta->c6)) {
318 fprintf(stderr, "cpu%d c6 counter went backwards %llX to %llX\n",
319 before->cpu, before->c6, after->c6);
320 errors++;
321 }
322 if (SUBTRACT_COUNTER(after->c7, before->c7, delta->c7)) {
323 fprintf(stderr, "cpu%d c7 counter went backwards %llX to %llX\n",
324 before->cpu, before->c7, after->c7);
325 errors++;
326 }
327 if (SUBTRACT_COUNTER(after->pc2, before->pc2, delta->pc2)) {
328 fprintf(stderr, "cpu%d pc2 counter went backwards %llX to %llX\n",
329 before->cpu, before->pc2, after->pc2);
330 errors++;
331 }
332 if (SUBTRACT_COUNTER(after->pc3, before->pc3, delta->pc3)) {
333 fprintf(stderr, "cpu%d pc3 counter went backwards %llX to %llX\n",
334 before->cpu, before->pc3, after->pc3);
335 errors++;
336 }
337 if (SUBTRACT_COUNTER(after->pc6, before->pc6, delta->pc6)) {
338 fprintf(stderr, "cpu%d pc6 counter went backwards %llX to %llX\n",
339 before->cpu, before->pc6, after->pc6);
340 errors++;
341 }
342 if (SUBTRACT_COUNTER(after->pc7, before->pc7, delta->pc7)) {
343 fprintf(stderr, "cpu%d pc7 counter went backwards %llX to %llX\n",
344 before->cpu, before->pc7, after->pc7);
345 errors++;
346 }
347
348 perf_err = SUBTRACT_COUNTER(after->aperf, before->aperf, delta->aperf);
349 if (perf_err) {
350 fprintf(stderr, "cpu%d aperf counter went backwards %llX to %llX\n",
351 before->cpu, before->aperf, after->aperf);
352 }
353 perf_err |= SUBTRACT_COUNTER(after->mperf, before->mperf, delta->mperf);
354 if (perf_err) {
355 fprintf(stderr, "cpu%d mperf counter went backwards %llX to %llX\n",
356 before->cpu, before->mperf, after->mperf);
357 }
358 if (perf_err) {
359 if (!aperf_mperf_unstable) {
360 fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname);
361 fprintf(stderr, "* Frequency results do not cover entire interval *\n");
362 fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n");
363
364 aperf_mperf_unstable = 1;
365 }
366 /*
367 * mperf delta is likely a huge "positive" number
368 * can not use it for calculating c0 time
369 */
370 skip_c0 = 1;
371 skip_c1 = 1;
372 }
373
374 /*
375 * As mperf and tsc collection are not atomic,
376 * it is possible for mperf's non-halted cycles
377 * to exceed TSC's all cycles: show c1 = 0% in that case.
378 */
379 if (delta->mperf > delta->tsc)
380 delta->c1 = 0;
381 else /* normal case, derive c1 */
382 delta->c1 = delta->tsc - delta->mperf
383 - delta->c3 - delta->c6 - delta->c7;
384
385 if (delta->mperf == 0)
386 delta->mperf = 1; /* divide by 0 protection */
387
388 /*
389 * for "extra msr", just copy the latest w/o subtracting
390 */
391 delta->extra_msr = after->extra_msr;
392 if (errors) {
393 fprintf(stderr, "ERROR cpu%d before:\n", before->cpu);
394 dump_pcc(before);
395 fprintf(stderr, "ERROR cpu%d after:\n", before->cpu);
396 dump_pcc(after);
397 errors = 0;
398 }
399 }
400 return 0;
401}
402
403void compute_average(PCC *delta, PCC *avg)
404{
405 PCC *sum;
406
407 sum = calloc(1, sizeof(PCC));
408 if (sum == NULL) {
409 perror("calloc sum");
410 exit(1);
411 }
412
413 for (; delta; delta = delta->next) {
414 sum->tsc += delta->tsc;
415 sum->c1 += delta->c1;
416 sum->c3 += delta->c3;
417 sum->c6 += delta->c6;
418 sum->c7 += delta->c7;
419 sum->aperf += delta->aperf;
420 sum->mperf += delta->mperf;
421 sum->pc2 += delta->pc2;
422 sum->pc3 += delta->pc3;
423 sum->pc6 += delta->pc6;
424 sum->pc7 += delta->pc7;
425 }
426 avg->tsc = sum->tsc/num_cpus;
427 avg->c1 = sum->c1/num_cpus;
428 avg->c3 = sum->c3/num_cpus;
429 avg->c6 = sum->c6/num_cpus;
430 avg->c7 = sum->c7/num_cpus;
431 avg->aperf = sum->aperf/num_cpus;
432 avg->mperf = sum->mperf/num_cpus;
433 avg->pc2 = sum->pc2/num_cpus;
434 avg->pc3 = sum->pc3/num_cpus;
435 avg->pc6 = sum->pc6/num_cpus;
436 avg->pc7 = sum->pc7/num_cpus;
437
438 free(sum);
439}
440
441void get_counters(PCC *pcc)
442{
443 for ( ; pcc; pcc = pcc->next) {
444 pcc->tsc = get_msr(pcc->cpu, MSR_TSC);
445 if (do_nhm_cstates)
446 pcc->c3 = get_msr(pcc->cpu, MSR_CORE_C3_RESIDENCY);
447 if (do_nhm_cstates)
448 pcc->c6 = get_msr(pcc->cpu, MSR_CORE_C6_RESIDENCY);
449 if (do_snb_cstates)
450 pcc->c7 = get_msr(pcc->cpu, MSR_CORE_C7_RESIDENCY);
451 if (has_aperf)
452 pcc->aperf = get_msr(pcc->cpu, MSR_APERF);
453 if (has_aperf)
454 pcc->mperf = get_msr(pcc->cpu, MSR_MPERF);
455 if (do_snb_cstates)
456 pcc->pc2 = get_msr(pcc->cpu, MSR_PKG_C2_RESIDENCY);
457 if (do_nhm_cstates)
458 pcc->pc3 = get_msr(pcc->cpu, MSR_PKG_C3_RESIDENCY);
459 if (do_nhm_cstates)
460 pcc->pc6 = get_msr(pcc->cpu, MSR_PKG_C6_RESIDENCY);
461 if (do_snb_cstates)
462 pcc->pc7 = get_msr(pcc->cpu, MSR_PKG_C7_RESIDENCY);
463 if (extra_msr_offset)
464 pcc->extra_msr = get_msr(pcc->cpu, extra_msr_offset);
465 }
466}
467
468
469void print_nehalem_info()
470{
471 unsigned long long msr;
472 unsigned int ratio;
473
474 if (!do_nehalem_platform_info)
475 return;
476
477 msr = get_msr(0, MSR_NEHALEM_PLATFORM_INFO);
478
479 ratio = (msr >> 40) & 0xFF;
480 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
481 ratio, bclk, ratio * bclk);
482
483 ratio = (msr >> 8) & 0xFF;
484 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n",
485 ratio, bclk, ratio * bclk);
486
487 if (verbose > 1)
488 fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr);
489
490 if (!do_nehalem_turbo_ratio_limit)
491 return;
492
493 msr = get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT);
494
495 ratio = (msr >> 24) & 0xFF;
496 if (ratio)
497 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
498 ratio, bclk, ratio * bclk);
499
500 ratio = (msr >> 16) & 0xFF;
501 if (ratio)
502 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 3 active cores\n",
503 ratio, bclk, ratio * bclk);
504
505 ratio = (msr >> 8) & 0xFF;
506 if (ratio)
507 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 2 active cores\n",
508 ratio, bclk, ratio * bclk);
509
510 ratio = (msr >> 0) & 0xFF;
511 if (ratio)
512 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
513 ratio, bclk, ratio * bclk);
514
515}
516
517void free_counter_list(PCC *list)
518{
519 PCC *p;
520
521 for (p = list; p; ) {
522 PCC *free_me;
523
524 free_me = p;
525 p = p->next;
526 free(free_me);
527 }
528 return;
529}
530
531void free_all_counters(void)
532{
533 free_counter_list(pcc_even);
534 pcc_even = NULL;
535
536 free_counter_list(pcc_odd);
537 pcc_odd = NULL;
538
539 free_counter_list(pcc_delta);
540 pcc_delta = NULL;
541
542 free_counter_list(pcc_average);
543 pcc_average = NULL;
544}
545
546void insert_cpu_counters(PCC **list, PCC *new)
547{
548 PCC *prev;
549
550 /*
551 * list was empty
552 */
553 if (*list == NULL) {
554 new->next = *list;
555 *list = new;
556 return;
557 }
558
559 show_cpu = 1; /* there is more than one CPU */
560
561 /*
562 * insert on front of list.
563 * It is sorted by ascending package#, core#, cpu#
564 */
565 if (((*list)->pkg > new->pkg) ||
566 (((*list)->pkg == new->pkg) && ((*list)->core > new->core)) ||
567 (((*list)->pkg == new->pkg) && ((*list)->core == new->core) && ((*list)->cpu > new->cpu))) {
568 new->next = *list;
569 *list = new;
570 return;
571 }
572
573 prev = *list;
574
575 while (prev->next && (prev->next->pkg < new->pkg)) {
576 prev = prev->next;
577 show_pkg = 1; /* there is more than 1 package */
578 }
579
580 while (prev->next && (prev->next->pkg == new->pkg)
581 && (prev->next->core < new->core)) {
582 prev = prev->next;
583 show_core = 1; /* there is more than 1 core */
584 }
585
586 while (prev->next && (prev->next->pkg == new->pkg)
587 && (prev->next->core == new->core)
588 && (prev->next->cpu < new->cpu)) {
589 prev = prev->next;
590 }
591
592 /*
593 * insert after "prev"
594 */
595 new->next = prev->next;
596 prev->next = new;
597
598 return;
599}
600
601void alloc_new_cpu_counters(int pkg, int core, int cpu)
602{
603 PCC *new;
604
605 if (verbose > 1)
606 printf("pkg%d core%d, cpu%d\n", pkg, core, cpu);
607
608 new = (PCC *)calloc(1, sizeof(PCC));
609 if (new == NULL) {
610 perror("calloc");
611 exit(1);
612 }
613 new->pkg = pkg;
614 new->core = core;
615 new->cpu = cpu;
616 insert_cpu_counters(&pcc_odd, new);
617
618 new = (PCC *)calloc(1, sizeof(PCC));
619 if (new == NULL) {
620 perror("calloc");
621 exit(1);
622 }
623 new->pkg = pkg;
624 new->core = core;
625 new->cpu = cpu;
626 insert_cpu_counters(&pcc_even, new);
627
628 new = (PCC *)calloc(1, sizeof(PCC));
629 if (new == NULL) {
630 perror("calloc");
631 exit(1);
632 }
633 new->pkg = pkg;
634 new->core = core;
635 new->cpu = cpu;
636 insert_cpu_counters(&pcc_delta, new);
637
638 new = (PCC *)calloc(1, sizeof(PCC));
639 if (new == NULL) {
640 perror("calloc");
641 exit(1);
642 }
643 new->pkg = pkg;
644 new->core = core;
645 new->cpu = cpu;
646 pcc_average = new;
647}
648
649int get_physical_package_id(int cpu)
650{
651 char path[64];
652 FILE *filep;
653 int pkg;
654
655 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", cpu);
656 filep = fopen(path, "r");
657 if (filep == NULL) {
658 perror(path);
659 exit(1);
660 }
661 fscanf(filep, "%d", &pkg);
662 fclose(filep);
663 return pkg;
664}
665
666int get_core_id(int cpu)
667{
668 char path[64];
669 FILE *filep;
670 int core;
671
672 sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
673 filep = fopen(path, "r");
674 if (filep == NULL) {
675 perror(path);
676 exit(1);
677 }
678 fscanf(filep, "%d", &core);
679 fclose(filep);
680 return core;
681}
682
683/*
684 * run func(index, cpu) on every cpu in /proc/stat
685 */
686
687int for_all_cpus(void (func)(int, int, int))
688{
689 FILE *fp;
690 int cpu_count;
691 int retval;
692
693 fp = fopen(proc_stat, "r");
694 if (fp == NULL) {
695 perror(proc_stat);
696 exit(1);
697 }
698
699 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
700 if (retval != 0) {
701 perror("/proc/stat format");
702 exit(1);
703 }
704
705 for (cpu_count = 0; ; cpu_count++) {
706 int cpu;
707
708 retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu);
709 if (retval != 1)
710 break;
711
712 func(get_physical_package_id(cpu), get_core_id(cpu), cpu);
713 }
714 fclose(fp);
715 return cpu_count;
716}
717
718void re_initialize(void)
719{
720 printf("turbostat: topology changed, re-initializing.\n");
721 free_all_counters();
722 num_cpus = for_all_cpus(alloc_new_cpu_counters);
723 need_reinitialize = 0;
724 printf("num_cpus is now %d\n", num_cpus);
725}
726
727void dummy(int pkg, int core, int cpu) { return; }
728/*
729 * check to see if a cpu came on-line
730 */
731void verify_num_cpus()
732{
733 int new_num_cpus;
734
735 new_num_cpus = for_all_cpus(dummy);
736
737 if (new_num_cpus != num_cpus) {
738 if (verbose)
739 printf("num_cpus was %d, is now %d\n",
740 num_cpus, new_num_cpus);
741 need_reinitialize = 1;
742 }
743
744 return;
745}
746
747void turbostat_loop()
748{
749restart:
750 get_counters(pcc_even);
751 gettimeofday(&tv_even, (struct timezone *)NULL);
752
753 while (1) {
754 verify_num_cpus();
755 if (need_reinitialize) {
756 re_initialize();
757 goto restart;
758 }
759 sleep(interval_sec);
760 get_counters(pcc_odd);
761 gettimeofday(&tv_odd, (struct timezone *)NULL);
762
763 compute_delta(pcc_odd, pcc_even, pcc_delta);
764 timersub(&tv_odd, &tv_even, &tv_delta);
765 compute_average(pcc_delta, pcc_average);
766 print_counters(pcc_delta);
767 if (need_reinitialize) {
768 re_initialize();
769 goto restart;
770 }
771 sleep(interval_sec);
772 get_counters(pcc_even);
773 gettimeofday(&tv_even, (struct timezone *)NULL);
774 compute_delta(pcc_even, pcc_odd, pcc_delta);
775 timersub(&tv_even, &tv_odd, &tv_delta);
776 compute_average(pcc_delta, pcc_average);
777 print_counters(pcc_delta);
778 }
779}
780
781void check_dev_msr()
782{
783 struct stat sb;
784
785 if (stat("/dev/cpu/0/msr", &sb)) {
786 fprintf(stderr, "no /dev/cpu/0/msr\n");
787 fprintf(stderr, "Try \"# modprobe msr\"\n");
788 exit(-5);
789 }
790}
791
792void check_super_user()
793{
794 if (getuid() != 0) {
795 fprintf(stderr, "must be root\n");
796 exit(-6);
797 }
798}
799
800int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
801{
802 if (!genuine_intel)
803 return 0;
804
805 if (family != 6)
806 return 0;
807
808 switch (model) {
809 case 0x1A: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
810 case 0x1E: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
811 case 0x1F: /* Core i7 and i5 Processor - Nehalem */
812 case 0x25: /* Westmere Client - Clarkdale, Arrandale */
813 case 0x2C: /* Westmere EP - Gulftown */
814 case 0x2A: /* SNB */
815 case 0x2D: /* SNB Xeon */
816 return 1;
817 case 0x2E: /* Nehalem-EX Xeon - Beckton */
818 case 0x2F: /* Westmere-EX Xeon - Eagleton */
819 default:
820 return 0;
821 }
822}
823
824int is_snb(unsigned int family, unsigned int model)
825{
826 if (!genuine_intel)
827 return 0;
828
829 switch (model) {
830 case 0x2A:
831 case 0x2D:
832 return 1;
833 }
834 return 0;
835}
836
837double discover_bclk(unsigned int family, unsigned int model)
838{
839 if (is_snb(family, model))
840 return 100.00;
841 else
842 return 133.33;
843}
844
845void check_cpuid()
846{
847 unsigned int eax, ebx, ecx, edx, max_level;
848 unsigned int fms, family, model, stepping;
849
850 eax = ebx = ecx = edx = 0;
851
852 asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0));
853
854 if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
855 genuine_intel = 1;
856
857 if (verbose)
858 fprintf(stderr, "%.4s%.4s%.4s ",
859 (char *)&ebx, (char *)&edx, (char *)&ecx);
860
861 asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx");
862 family = (fms >> 8) & 0xf;
863 model = (fms >> 4) & 0xf;
864 stepping = fms & 0xf;
865 if (family == 6 || family == 0xf)
866 model += ((fms >> 16) & 0xf) << 4;
867
868 if (verbose)
869 fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
870 max_level, family, model, stepping, family, model, stepping);
871
872 if (!(edx & (1 << 5))) {
873 fprintf(stderr, "CPUID: no MSR\n");
874 exit(1);
875 }
876
877 /*
878 * check max extended function levels of CPUID.
879 * This is needed to check for invariant TSC.
880 * This check is valid for both Intel and AMD.
881 */
882 ebx = ecx = edx = 0;
883 asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000000));
884
885 if (max_level < 0x80000007) {
886 fprintf(stderr, "CPUID: no invariant TSC (max_level 0x%x)\n", max_level);
887 exit(1);
888 }
889
890 /*
891 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
892 * this check is valid for both Intel and AMD
893 */
894 asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000007));
895 has_invariant_tsc = edx && (1 << 8);
896
897 if (!has_invariant_tsc) {
898 fprintf(stderr, "No invariant TSC\n");
899 exit(1);
900 }
901
902 /*
903 * APERF/MPERF is advertised by CPUID.EAX=0x6: ECX.bit0
904 * this check is valid for both Intel and AMD
905 */
906
907 asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x6));
908 has_aperf = ecx && (1 << 0);
909 if (!has_aperf) {
910 fprintf(stderr, "No APERF MSR\n");
911 exit(1);
912 }
913
914 do_nehalem_platform_info = genuine_intel && has_invariant_tsc;
915 do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */
916 do_snb_cstates = is_snb(family, model);
917 bclk = discover_bclk(family, model);
918
919 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
920}
921
922
923void usage()
924{
925 fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n",
926 progname);
927 exit(1);
928}
929
930
931/*
932 * in /dev/cpu/ return success for names that are numbers
933 * ie. filter out ".", "..", "microcode".
934 */
935int dir_filter(const struct dirent *dirp)
936{
937 if (isdigit(dirp->d_name[0]))
938 return 1;
939 else
940 return 0;
941}
942
943int open_dev_cpu_msr(int dummy1)
944{
945 return 0;
946}
947
948void turbostat_init()
949{
950 check_cpuid();
951
952 check_dev_msr();
953 check_super_user();
954
955 num_cpus = for_all_cpus(alloc_new_cpu_counters);
956
957 if (verbose)
958 print_nehalem_info();
959}
960
961int fork_it(char **argv)
962{
963 int retval;
964 pid_t child_pid;
965 get_counters(pcc_even);
966 gettimeofday(&tv_even, (struct timezone *)NULL);
967
968 child_pid = fork();
969 if (!child_pid) {
970 /* child */
971 execvp(argv[0], argv);
972 } else {
973 int status;
974
975 /* parent */
976 if (child_pid == -1) {
977 perror("fork");
978 exit(1);
979 }
980
981 signal(SIGINT, SIG_IGN);
982 signal(SIGQUIT, SIG_IGN);
983 if (waitpid(child_pid, &status, 0) == -1) {
984 perror("wait");
985 exit(1);
986 }
987 }
988 get_counters(pcc_odd);
989 gettimeofday(&tv_odd, (struct timezone *)NULL);
990 retval = compute_delta(pcc_odd, pcc_even, pcc_delta);
991
992 timersub(&tv_odd, &tv_even, &tv_delta);
993 compute_average(pcc_delta, pcc_average);
994 if (!retval)
995 print_counters(pcc_delta);
996
997 fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);;
998
999 return 0;
1000}
1001
1002void cmdline(int argc, char **argv)
1003{
1004 int opt;
1005
1006 progname = argv[0];
1007
1008 while ((opt = getopt(argc, argv, "+vi:M:")) != -1) {
1009 switch (opt) {
1010 case 'v':
1011 verbose++;
1012 break;
1013 case 'i':
1014 interval_sec = atoi(optarg);
1015 break;
1016 case 'M':
1017 sscanf(optarg, "%x", &extra_msr_offset);
1018 if (verbose > 1)
1019 fprintf(stderr, "MSR 0x%X\n", extra_msr_offset);
1020 break;
1021 default:
1022 usage();
1023 }
1024 }
1025}
1026
1027int main(int argc, char **argv)
1028{
1029 cmdline(argc, argv);
1030
1031 if (verbose > 1)
1032 fprintf(stderr, "turbostat Dec 6, 2010"
1033 " - Len Brown <lenb@kernel.org>\n");
1034 if (verbose > 1)
1035 fprintf(stderr, "http://userweb.kernel.org/~lenb/acpi/utils/pmtools/turbostat/\n");
1036
1037 turbostat_init();
1038
1039 /*
1040 * if any params left, it must be a command to fork
1041 */
1042 if (argc - optind)
1043 return fork_it(argv + optind);
1044 else
1045 turbostat_loop();
1046
1047 return 0;
1048}
diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile
new file mode 100644
index 000000000000..f458237fdd79
--- /dev/null
+++ b/tools/power/x86/x86_energy_perf_policy/Makefile
@@ -0,0 +1,8 @@
1x86_energy_perf_policy : x86_energy_perf_policy.c
2
3clean :
4 rm -f x86_energy_perf_policy
5
6install :
7 install x86_energy_perf_policy /usr/bin/
8 install x86_energy_perf_policy.8 /usr/share/man/man8/
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
new file mode 100644
index 000000000000..8eaaad648cdb
--- /dev/null
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
@@ -0,0 +1,104 @@
1.\" This page Copyright (C) 2010 Len Brown <len.brown@intel.com>
2.\" Distributed under the GPL, Copyleft 1994.
3.TH X86_ENERGY_PERF_POLICY 8
4.SH NAME
5x86_energy_perf_policy \- read or write MSR_IA32_ENERGY_PERF_BIAS
6.SH SYNOPSIS
7.ft B
8.B x86_energy_perf_policy
9.RB [ "\-c cpu" ]
10.RB [ "\-v" ]
11.RB "\-r"
12.br
13.B x86_energy_perf_policy
14.RB [ "\-c cpu" ]
15.RB [ "\-v" ]
16.RB 'performance'
17.br
18.B x86_energy_perf_policy
19.RB [ "\-c cpu" ]
20.RB [ "\-v" ]
21.RB 'normal'
22.br
23.B x86_energy_perf_policy
24.RB [ "\-c cpu" ]
25.RB [ "\-v" ]
26.RB 'powersave'
27.br
28.B x86_energy_perf_policy
29.RB [ "\-c cpu" ]
30.RB [ "\-v" ]
31.RB n
32.br
33.SH DESCRIPTION
34\fBx86_energy_perf_policy\fP
35allows software to convey
36its policy for the relative importance of performance
37versus energy savings to the processor.
38
39The processor uses this information in model-specific ways
40when it must select trade-offs between performance and
41energy efficiency.
42
43This policy hint does not supersede Processor Performance states
44(P-states) or CPU Idle power states (C-states), but allows
45software to have influence where it would otherwise be unable
46to express a preference.
47
48For example, this setting may tell the hardware how
49aggressively or conservatively to control frequency
50in the "turbo range" above the explicitly OS-controlled
51P-state frequency range. It may also tell the hardware
52how aggressively is should enter the OS requested C-states.
53
54Support for this feature is indicated by CPUID.06H.ECX.bit3
55per the Intel Architectures Software Developer's Manual.
56
57.SS Options
58\fB-c\fP limits operation to a single CPU.
59The default is to operate on all CPUs.
60Note that MSR_IA32_ENERGY_PERF_BIAS is defined per
61logical processor, but that the initial implementations
62of the MSR were shared among all processors in each package.
63.PP
64\fB-v\fP increases verbosity. By default
65x86_energy_perf_policy is silent.
66.PP
67\fB-r\fP is for "read-only" mode - the unchanged state
68is read and displayed.
69.PP
70.I performance
71Set a policy where performance is paramount.
72The processor will be unwilling to sacrifice any performance
73for the sake of energy saving. This is the hardware default.
74.PP
75.I normal
76Set a policy with a normal balance between performance and energy efficiency.
77The processor will tolerate minor performance compromise
78for potentially significant energy savings.
79This reasonable default for most desktops and servers.
80.PP
81.I powersave
82Set a policy where the processor can accept
83a measurable performance hit to maximize energy efficiency.
84.PP
85.I n
86Set MSR_IA32_ENERGY_PERF_BIAS to the specified number.
87The range of valid numbers is 0-15, where 0 is maximum
88performance and 15 is maximum energy efficiency.
89
90.SH NOTES
91.B "x86_energy_perf_policy "
92runs only as root.
93.SH FILES
94.ta
95.nf
96/dev/cpu/*/msr
97.fi
98
99.SH "SEE ALSO"
100msr(4)
101.PP
102.SH AUTHORS
103.nf
104Written by Len Brown <len.brown@intel.com>
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
new file mode 100644
index 000000000000..d9678a34dd70
--- /dev/null
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
@@ -0,0 +1,325 @@
1/*
2 * x86_energy_perf_policy -- set the energy versus performance
3 * policy preference bias on recent X86 processors.
4 */
5/*
6 * Copyright (c) 2010, Intel Corporation.
7 * Len Brown <len.brown@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#include <stdio.h>
24#include <unistd.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/resource.h>
28#include <fcntl.h>
29#include <signal.h>
30#include <sys/time.h>
31#include <stdlib.h>
32#include <string.h>
33
34unsigned int verbose; /* set with -v */
35unsigned int read_only; /* set with -r */
36char *progname;
37unsigned long long new_bias;
38int cpu = -1;
39
40/*
41 * Usage:
42 *
43 * -c cpu: limit action to a single CPU (default is all CPUs)
44 * -v: verbose output (can invoke more than once)
45 * -r: read-only, don't change any settings
46 *
47 * performance
48 * Performance is paramount.
49 * Unwilling to sacrafice any performance
50 * for the sake of energy saving. (hardware default)
51 *
52 * normal
53 * Can tolerate minor performance compromise
54 * for potentially significant energy savings.
55 * (reasonable default for most desktops and servers)
56 *
57 * powersave
58 * Can tolerate significant performance hit
59 * to maximize energy savings.
60 *
61 * n
62 * a numerical value to write to the underlying MSR.
63 */
64void usage(void)
65{
66 printf("%s: [-c cpu] [-v] "
67 "(-r | 'performance' | 'normal' | 'powersave' | n)\n",
68 progname);
69 exit(1);
70}
71
72#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
73
74#define BIAS_PERFORMANCE 0
75#define BIAS_BALANCE 6
76#define BIAS_POWERSAVE 15
77
78void cmdline(int argc, char **argv)
79{
80 int opt;
81
82 progname = argv[0];
83
84 while ((opt = getopt(argc, argv, "+rvc:")) != -1) {
85 switch (opt) {
86 case 'c':
87 cpu = atoi(optarg);
88 break;
89 case 'r':
90 read_only = 1;
91 break;
92 case 'v':
93 verbose++;
94 break;
95 default:
96 usage();
97 }
98 }
99 /* if -r, then should be no additional optind */
100 if (read_only && (argc > optind))
101 usage();
102
103 /*
104 * if no -r , then must be one additional optind
105 */
106 if (!read_only) {
107
108 if (argc != optind + 1) {
109 printf("must supply -r or policy param\n");
110 usage();
111 }
112
113 if (!strcmp("performance", argv[optind])) {
114 new_bias = BIAS_PERFORMANCE;
115 } else if (!strcmp("normal", argv[optind])) {
116 new_bias = BIAS_BALANCE;
117 } else if (!strcmp("powersave", argv[optind])) {
118 new_bias = BIAS_POWERSAVE;
119 } else {
120 char *endptr;
121
122 new_bias = strtoull(argv[optind], &endptr, 0);
123 if (endptr == argv[optind] ||
124 new_bias > BIAS_POWERSAVE) {
125 fprintf(stderr, "invalid value: %s\n",
126 argv[optind]);
127 usage();
128 }
129 }
130 }
131}
132
133/*
134 * validate_cpuid()
135 * returns on success, quietly exits on failure (make verbose with -v)
136 */
137void validate_cpuid(void)
138{
139 unsigned int eax, ebx, ecx, edx, max_level;
140 char brand[16];
141 unsigned int fms, family, model, stepping;
142
143 eax = ebx = ecx = edx = 0;
144
145 asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx),
146 "=d" (edx) : "a" (0));
147
148 if (ebx != 0x756e6547 || edx != 0x49656e69 || ecx != 0x6c65746e) {
149 if (verbose)
150 fprintf(stderr, "%.4s%.4s%.4s != GenuineIntel",
151 (char *)&ebx, (char *)&edx, (char *)&ecx);
152 exit(1);
153 }
154
155 asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx");
156 family = (fms >> 8) & 0xf;
157 model = (fms >> 4) & 0xf;
158 stepping = fms & 0xf;
159 if (family == 6 || family == 0xf)
160 model += ((fms >> 16) & 0xf) << 4;
161
162 if (verbose > 1)
163 printf("CPUID %s %d levels family:model:stepping "
164 "0x%x:%x:%x (%d:%d:%d)\n", brand, max_level,
165 family, model, stepping, family, model, stepping);
166
167 if (!(edx & (1 << 5))) {
168 if (verbose)
169 printf("CPUID: no MSR\n");
170 exit(1);
171 }
172
173 /*
174 * Support for MSR_IA32_ENERGY_PERF_BIAS
175 * is indicated by CPUID.06H.ECX.bit3
176 */
177 asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (6));
178 if (verbose)
179 printf("CPUID.06H.ECX: 0x%x\n", ecx);
180 if (!(ecx & (1 << 3))) {
181 if (verbose)
182 printf("CPUID: No MSR_IA32_ENERGY_PERF_BIAS\n");
183 exit(1);
184 }
185 return; /* success */
186}
187
188unsigned long long get_msr(int cpu, int offset)
189{
190 unsigned long long msr;
191 char msr_path[32];
192 int retval;
193 int fd;
194
195 sprintf(msr_path, "/dev/cpu/%d/msr", cpu);
196 fd = open(msr_path, O_RDONLY);
197 if (fd < 0) {
198 printf("Try \"# modprobe msr\"\n");
199 perror(msr_path);
200 exit(1);
201 }
202
203 retval = pread(fd, &msr, sizeof msr, offset);
204
205 if (retval != sizeof msr) {
206 printf("pread cpu%d 0x%x = %d\n", cpu, offset, retval);
207 exit(-2);
208 }
209 close(fd);
210 return msr;
211}
212
213unsigned long long put_msr(int cpu, unsigned long long new_msr, int offset)
214{
215 unsigned long long old_msr;
216 char msr_path[32];
217 int retval;
218 int fd;
219
220 sprintf(msr_path, "/dev/cpu/%d/msr", cpu);
221 fd = open(msr_path, O_RDWR);
222 if (fd < 0) {
223 perror(msr_path);
224 exit(1);
225 }
226
227 retval = pread(fd, &old_msr, sizeof old_msr, offset);
228 if (retval != sizeof old_msr) {
229 perror("pwrite");
230 printf("pread cpu%d 0x%x = %d\n", cpu, offset, retval);
231 exit(-2);
232 }
233
234 retval = pwrite(fd, &new_msr, sizeof new_msr, offset);
235 if (retval != sizeof new_msr) {
236 perror("pwrite");
237 printf("pwrite cpu%d 0x%x = %d\n", cpu, offset, retval);
238 exit(-2);
239 }
240
241 close(fd);
242
243 return old_msr;
244}
245
246void print_msr(int cpu)
247{
248 printf("cpu%d: 0x%016llx\n",
249 cpu, get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS));
250}
251
252void update_msr(int cpu)
253{
254 unsigned long long previous_msr;
255
256 previous_msr = put_msr(cpu, new_bias, MSR_IA32_ENERGY_PERF_BIAS);
257
258 if (verbose)
259 printf("cpu%d msr0x%x 0x%016llx -> 0x%016llx\n",
260 cpu, MSR_IA32_ENERGY_PERF_BIAS, previous_msr, new_bias);
261
262 return;
263}
264
265char *proc_stat = "/proc/stat";
266/*
267 * run func() on every cpu in /dev/cpu
268 */
269void for_every_cpu(void (func)(int))
270{
271 FILE *fp;
272 int retval;
273
274 fp = fopen(proc_stat, "r");
275 if (fp == NULL) {
276 perror(proc_stat);
277 exit(1);
278 }
279
280 retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
281 if (retval != 0) {
282 perror("/proc/stat format");
283 exit(1);
284 }
285
286 while (1) {
287 int cpu;
288
289 retval = fscanf(fp,
290 "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n",
291 &cpu);
292 if (retval != 1)
293 return;
294
295 func(cpu);
296 }
297 fclose(fp);
298}
299
300int main(int argc, char **argv)
301{
302 cmdline(argc, argv);
303
304 if (verbose > 1)
305 printf("x86_energy_perf_policy Nov 24, 2010"
306 " - Len Brown <lenb@kernel.org>\n");
307 if (verbose > 1 && !read_only)
308 printf("new_bias %lld\n", new_bias);
309
310 validate_cpuid();
311
312 if (cpu != -1) {
313 if (read_only)
314 print_msr(cpu);
315 else
316 update_msr(cpu);
317 } else {
318 if (read_only)
319 for_every_cpu(print_msr);
320 else
321 for_every_cpu(update_msr);
322 }
323
324 return 0;
325}
diff --git a/tools/slub/slabinfo.c b/tools/slub/slabinfo.c
new file mode 100644
index 000000000000..516551c9f172
--- /dev/null
+++ b/tools/slub/slabinfo.c
@@ -0,0 +1,1364 @@
1/*
2 * Slabinfo: Tool to get reports about slabs
3 *
4 * (C) 2007 sgi, Christoph Lameter
5 *
6 * Compile by:
7 *
8 * gcc -o slabinfo slabinfo.c
9 */
10#include <stdio.h>
11#include <stdlib.h>
12#include <sys/types.h>
13#include <dirent.h>
14#include <strings.h>
15#include <string.h>
16#include <unistd.h>
17#include <stdarg.h>
18#include <getopt.h>
19#include <regex.h>
20#include <errno.h>
21
22#define MAX_SLABS 500
23#define MAX_ALIASES 500
24#define MAX_NODES 1024
25
26struct slabinfo {
27 char *name;
28 int alias;
29 int refs;
30 int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
31 int hwcache_align, object_size, objs_per_slab;
32 int sanity_checks, slab_size, store_user, trace;
33 int order, poison, reclaim_account, red_zone;
34 unsigned long partial, objects, slabs, objects_partial, objects_total;
35 unsigned long alloc_fastpath, alloc_slowpath;
36 unsigned long free_fastpath, free_slowpath;
37 unsigned long free_frozen, free_add_partial, free_remove_partial;
38 unsigned long alloc_from_partial, alloc_slab, free_slab, alloc_refill;
39 unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
40 unsigned long deactivate_to_head, deactivate_to_tail;
41 unsigned long deactivate_remote_frees, order_fallback;
42 int numa[MAX_NODES];
43 int numa_partial[MAX_NODES];
44} slabinfo[MAX_SLABS];
45
46struct aliasinfo {
47 char *name;
48 char *ref;
49 struct slabinfo *slab;
50} aliasinfo[MAX_ALIASES];
51
52int slabs = 0;
53int actual_slabs = 0;
54int aliases = 0;
55int alias_targets = 0;
56int highest_node = 0;
57
58char buffer[4096];
59
60int show_empty = 0;
61int show_report = 0;
62int show_alias = 0;
63int show_slab = 0;
64int skip_zero = 1;
65int show_numa = 0;
66int show_track = 0;
67int show_first_alias = 0;
68int validate = 0;
69int shrink = 0;
70int show_inverted = 0;
71int show_single_ref = 0;
72int show_totals = 0;
73int sort_size = 0;
74int sort_active = 0;
75int set_debug = 0;
76int show_ops = 0;
77int show_activity = 0;
78
79/* Debug options */
80int sanity = 0;
81int redzone = 0;
82int poison = 0;
83int tracking = 0;
84int tracing = 0;
85
86int page_size;
87
88regex_t pattern;
89
90static void fatal(const char *x, ...)
91{
92 va_list ap;
93
94 va_start(ap, x);
95 vfprintf(stderr, x, ap);
96 va_end(ap);
97 exit(EXIT_FAILURE);
98}
99
100static void usage(void)
101{
102 printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n"
103 "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
104 "-a|--aliases Show aliases\n"
105 "-A|--activity Most active slabs first\n"
106 "-d<options>|--debug=<options> Set/Clear Debug options\n"
107 "-D|--display-active Switch line format to activity\n"
108 "-e|--empty Show empty slabs\n"
109 "-f|--first-alias Show first alias\n"
110 "-h|--help Show usage information\n"
111 "-i|--inverted Inverted list\n"
112 "-l|--slabs Show slabs\n"
113 "-n|--numa Show NUMA information\n"
114 "-o|--ops Show kmem_cache_ops\n"
115 "-s|--shrink Shrink slabs\n"
116 "-r|--report Detailed report on single slabs\n"
117 "-S|--Size Sort by size\n"
118 "-t|--tracking Show alloc/free information\n"
119 "-T|--Totals Show summary information\n"
120 "-v|--validate Validate slabs\n"
121 "-z|--zero Include empty slabs\n"
122 "-1|--1ref Single reference\n"
123 "\nValid debug options (FZPUT may be combined)\n"
124 "a / A Switch on all debug options (=FZUP)\n"
125 "- Switch off all debug options\n"
126 "f / F Sanity Checks (SLAB_DEBUG_FREE)\n"
127 "z / Z Redzoning\n"
128 "p / P Poisoning\n"
129 "u / U Tracking\n"
130 "t / T Tracing\n"
131 );
132}
133
134static unsigned long read_obj(const char *name)
135{
136 FILE *f = fopen(name, "r");
137
138 if (!f)
139 buffer[0] = 0;
140 else {
141 if (!fgets(buffer, sizeof(buffer), f))
142 buffer[0] = 0;
143 fclose(f);
144 if (buffer[strlen(buffer)] == '\n')
145 buffer[strlen(buffer)] = 0;
146 }
147 return strlen(buffer);
148}
149
150
151/*
152 * Get the contents of an attribute
153 */
154static unsigned long get_obj(const char *name)
155{
156 if (!read_obj(name))
157 return 0;
158
159 return atol(buffer);
160}
161
162static unsigned long get_obj_and_str(const char *name, char **x)
163{
164 unsigned long result = 0;
165 char *p;
166
167 *x = NULL;
168
169 if (!read_obj(name)) {
170 x = NULL;
171 return 0;
172 }
173 result = strtoul(buffer, &p, 10);
174 while (*p == ' ')
175 p++;
176 if (*p)
177 *x = strdup(p);
178 return result;
179}
180
181static void set_obj(struct slabinfo *s, const char *name, int n)
182{
183 char x[100];
184 FILE *f;
185
186 snprintf(x, 100, "%s/%s", s->name, name);
187 f = fopen(x, "w");
188 if (!f)
189 fatal("Cannot write to %s\n", x);
190
191 fprintf(f, "%d\n", n);
192 fclose(f);
193}
194
195static unsigned long read_slab_obj(struct slabinfo *s, const char *name)
196{
197 char x[100];
198 FILE *f;
199 size_t l;
200
201 snprintf(x, 100, "%s/%s", s->name, name);
202 f = fopen(x, "r");
203 if (!f) {
204 buffer[0] = 0;
205 l = 0;
206 } else {
207 l = fread(buffer, 1, sizeof(buffer), f);
208 buffer[l] = 0;
209 fclose(f);
210 }
211 return l;
212}
213
214
215/*
216 * Put a size string together
217 */
218static int store_size(char *buffer, unsigned long value)
219{
220 unsigned long divisor = 1;
221 char trailer = 0;
222 int n;
223
224 if (value > 1000000000UL) {
225 divisor = 100000000UL;
226 trailer = 'G';
227 } else if (value > 1000000UL) {
228 divisor = 100000UL;
229 trailer = 'M';
230 } else if (value > 1000UL) {
231 divisor = 100;
232 trailer = 'K';
233 }
234
235 value /= divisor;
236 n = sprintf(buffer, "%ld",value);
237 if (trailer) {
238 buffer[n] = trailer;
239 n++;
240 buffer[n] = 0;
241 }
242 if (divisor != 1) {
243 memmove(buffer + n - 2, buffer + n - 3, 4);
244 buffer[n-2] = '.';
245 n++;
246 }
247 return n;
248}
249
250static void decode_numa_list(int *numa, char *t)
251{
252 int node;
253 int nr;
254
255 memset(numa, 0, MAX_NODES * sizeof(int));
256
257 if (!t)
258 return;
259
260 while (*t == 'N') {
261 t++;
262 node = strtoul(t, &t, 10);
263 if (*t == '=') {
264 t++;
265 nr = strtoul(t, &t, 10);
266 numa[node] = nr;
267 if (node > highest_node)
268 highest_node = node;
269 }
270 while (*t == ' ')
271 t++;
272 }
273}
274
275static void slab_validate(struct slabinfo *s)
276{
277 if (strcmp(s->name, "*") == 0)
278 return;
279
280 set_obj(s, "validate", 1);
281}
282
283static void slab_shrink(struct slabinfo *s)
284{
285 if (strcmp(s->name, "*") == 0)
286 return;
287
288 set_obj(s, "shrink", 1);
289}
290
291int line = 0;
292
293static void first_line(void)
294{
295 if (show_activity)
296 printf("Name Objects Alloc Free %%Fast Fallb O\n");
297 else
298 printf("Name Objects Objsize Space "
299 "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n");
300}
301
302/*
303 * Find the shortest alias of a slab
304 */
305static struct aliasinfo *find_one_alias(struct slabinfo *find)
306{
307 struct aliasinfo *a;
308 struct aliasinfo *best = NULL;
309
310 for(a = aliasinfo;a < aliasinfo + aliases; a++) {
311 if (a->slab == find &&
312 (!best || strlen(best->name) < strlen(a->name))) {
313 best = a;
314 if (strncmp(a->name,"kmall", 5) == 0)
315 return best;
316 }
317 }
318 return best;
319}
320
321static unsigned long slab_size(struct slabinfo *s)
322{
323 return s->slabs * (page_size << s->order);
324}
325
326static unsigned long slab_activity(struct slabinfo *s)
327{
328 return s->alloc_fastpath + s->free_fastpath +
329 s->alloc_slowpath + s->free_slowpath;
330}
331
332static void slab_numa(struct slabinfo *s, int mode)
333{
334 int node;
335
336 if (strcmp(s->name, "*") == 0)
337 return;
338
339 if (!highest_node) {
340 printf("\n%s: No NUMA information available.\n", s->name);
341 return;
342 }
343
344 if (skip_zero && !s->slabs)
345 return;
346
347 if (!line) {
348 printf("\n%-21s:", mode ? "NUMA nodes" : "Slab");
349 for(node = 0; node <= highest_node; node++)
350 printf(" %4d", node);
351 printf("\n----------------------");
352 for(node = 0; node <= highest_node; node++)
353 printf("-----");
354 printf("\n");
355 }
356 printf("%-21s ", mode ? "All slabs" : s->name);
357 for(node = 0; node <= highest_node; node++) {
358 char b[20];
359
360 store_size(b, s->numa[node]);
361 printf(" %4s", b);
362 }
363 printf("\n");
364 if (mode) {
365 printf("%-21s ", "Partial slabs");
366 for(node = 0; node <= highest_node; node++) {
367 char b[20];
368
369 store_size(b, s->numa_partial[node]);
370 printf(" %4s", b);
371 }
372 printf("\n");
373 }
374 line++;
375}
376
377static void show_tracking(struct slabinfo *s)
378{
379 printf("\n%s: Kernel object allocation\n", s->name);
380 printf("-----------------------------------------------------------------------\n");
381 if (read_slab_obj(s, "alloc_calls"))
382 printf(buffer);
383 else
384 printf("No Data\n");
385
386 printf("\n%s: Kernel object freeing\n", s->name);
387 printf("------------------------------------------------------------------------\n");
388 if (read_slab_obj(s, "free_calls"))
389 printf(buffer);
390 else
391 printf("No Data\n");
392
393}
394
395static void ops(struct slabinfo *s)
396{
397 if (strcmp(s->name, "*") == 0)
398 return;
399
400 if (read_slab_obj(s, "ops")) {
401 printf("\n%s: kmem_cache operations\n", s->name);
402 printf("--------------------------------------------\n");
403 printf(buffer);
404 } else
405 printf("\n%s has no kmem_cache operations\n", s->name);
406}
407
408static const char *onoff(int x)
409{
410 if (x)
411 return "On ";
412 return "Off";
413}
414
415static void slab_stats(struct slabinfo *s)
416{
417 unsigned long total_alloc;
418 unsigned long total_free;
419 unsigned long total;
420
421 if (!s->alloc_slab)
422 return;
423
424 total_alloc = s->alloc_fastpath + s->alloc_slowpath;
425 total_free = s->free_fastpath + s->free_slowpath;
426
427 if (!total_alloc)
428 return;
429
430 printf("\n");
431 printf("Slab Perf Counter Alloc Free %%Al %%Fr\n");
432 printf("--------------------------------------------------\n");
433 printf("Fastpath %8lu %8lu %3lu %3lu\n",
434 s->alloc_fastpath, s->free_fastpath,
435 s->alloc_fastpath * 100 / total_alloc,
436 s->free_fastpath * 100 / total_free);
437 printf("Slowpath %8lu %8lu %3lu %3lu\n",
438 total_alloc - s->alloc_fastpath, s->free_slowpath,
439 (total_alloc - s->alloc_fastpath) * 100 / total_alloc,
440 s->free_slowpath * 100 / total_free);
441 printf("Page Alloc %8lu %8lu %3lu %3lu\n",
442 s->alloc_slab, s->free_slab,
443 s->alloc_slab * 100 / total_alloc,
444 s->free_slab * 100 / total_free);
445 printf("Add partial %8lu %8lu %3lu %3lu\n",
446 s->deactivate_to_head + s->deactivate_to_tail,
447 s->free_add_partial,
448 (s->deactivate_to_head + s->deactivate_to_tail) * 100 / total_alloc,
449 s->free_add_partial * 100 / total_free);
450 printf("Remove partial %8lu %8lu %3lu %3lu\n",
451 s->alloc_from_partial, s->free_remove_partial,
452 s->alloc_from_partial * 100 / total_alloc,
453 s->free_remove_partial * 100 / total_free);
454
455 printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n",
456 s->deactivate_remote_frees, s->free_frozen,
457 s->deactivate_remote_frees * 100 / total_alloc,
458 s->free_frozen * 100 / total_free);
459
460 printf("Total %8lu %8lu\n\n", total_alloc, total_free);
461
462 if (s->cpuslab_flush)
463 printf("Flushes %8lu\n", s->cpuslab_flush);
464
465 if (s->alloc_refill)
466 printf("Refill %8lu\n", s->alloc_refill);
467
468 total = s->deactivate_full + s->deactivate_empty +
469 s->deactivate_to_head + s->deactivate_to_tail;
470
471 if (total)
472 printf("Deactivate Full=%lu(%lu%%) Empty=%lu(%lu%%) "
473 "ToHead=%lu(%lu%%) ToTail=%lu(%lu%%)\n",
474 s->deactivate_full, (s->deactivate_full * 100) / total,
475 s->deactivate_empty, (s->deactivate_empty * 100) / total,
476 s->deactivate_to_head, (s->deactivate_to_head * 100) / total,
477 s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
478}
479
480static void report(struct slabinfo *s)
481{
482 if (strcmp(s->name, "*") == 0)
483 return;
484
485 printf("\nSlabcache: %-20s Aliases: %2d Order : %2d Objects: %lu\n",
486 s->name, s->aliases, s->order, s->objects);
487 if (s->hwcache_align)
488 printf("** Hardware cacheline aligned\n");
489 if (s->cache_dma)
490 printf("** Memory is allocated in a special DMA zone\n");
491 if (s->destroy_by_rcu)
492 printf("** Slabs are destroyed via RCU\n");
493 if (s->reclaim_account)
494 printf("** Reclaim accounting active\n");
495
496 printf("\nSizes (bytes) Slabs Debug Memory\n");
497 printf("------------------------------------------------------------------------\n");
498 printf("Object : %7d Total : %7ld Sanity Checks : %s Total: %7ld\n",
499 s->object_size, s->slabs, onoff(s->sanity_checks),
500 s->slabs * (page_size << s->order));
501 printf("SlabObj: %7d Full : %7ld Redzoning : %s Used : %7ld\n",
502 s->slab_size, s->slabs - s->partial - s->cpu_slabs,
503 onoff(s->red_zone), s->objects * s->object_size);
504 printf("SlabSiz: %7d Partial: %7ld Poisoning : %s Loss : %7ld\n",
505 page_size << s->order, s->partial, onoff(s->poison),
506 s->slabs * (page_size << s->order) - s->objects * s->object_size);
507 printf("Loss : %7d CpuSlab: %7d Tracking : %s Lalig: %7ld\n",
508 s->slab_size - s->object_size, s->cpu_slabs, onoff(s->store_user),
509 (s->slab_size - s->object_size) * s->objects);
510 printf("Align : %7d Objects: %7d Tracing : %s Lpadd: %7ld\n",
511 s->align, s->objs_per_slab, onoff(s->trace),
512 ((page_size << s->order) - s->objs_per_slab * s->slab_size) *
513 s->slabs);
514
515 ops(s);
516 show_tracking(s);
517 slab_numa(s, 1);
518 slab_stats(s);
519}
520
521static void slabcache(struct slabinfo *s)
522{
523 char size_str[20];
524 char dist_str[40];
525 char flags[20];
526 char *p = flags;
527
528 if (strcmp(s->name, "*") == 0)
529 return;
530
531 if (actual_slabs == 1) {
532 report(s);
533 return;
534 }
535
536 if (skip_zero && !show_empty && !s->slabs)
537 return;
538
539 if (show_empty && s->slabs)
540 return;
541
542 store_size(size_str, slab_size(s));
543 snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs - s->cpu_slabs,
544 s->partial, s->cpu_slabs);
545
546 if (!line++)
547 first_line();
548
549 if (s->aliases)
550 *p++ = '*';
551 if (s->cache_dma)
552 *p++ = 'd';
553 if (s->hwcache_align)
554 *p++ = 'A';
555 if (s->poison)
556 *p++ = 'P';
557 if (s->reclaim_account)
558 *p++ = 'a';
559 if (s->red_zone)
560 *p++ = 'Z';
561 if (s->sanity_checks)
562 *p++ = 'F';
563 if (s->store_user)
564 *p++ = 'U';
565 if (s->trace)
566 *p++ = 'T';
567
568 *p = 0;
569 if (show_activity) {
570 unsigned long total_alloc;
571 unsigned long total_free;
572
573 total_alloc = s->alloc_fastpath + s->alloc_slowpath;
574 total_free = s->free_fastpath + s->free_slowpath;
575
576 printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d\n",
577 s->name, s->objects,
578 total_alloc, total_free,
579 total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
580 total_free ? (s->free_fastpath * 100 / total_free) : 0,
581 s->order_fallback, s->order);
582 }
583 else
584 printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
585 s->name, s->objects, s->object_size, size_str, dist_str,
586 s->objs_per_slab, s->order,
587 s->slabs ? (s->partial * 100) / s->slabs : 100,
588 s->slabs ? (s->objects * s->object_size * 100) /
589 (s->slabs * (page_size << s->order)) : 100,
590 flags);
591}
592
593/*
594 * Analyze debug options. Return false if something is amiss.
595 */
596static int debug_opt_scan(char *opt)
597{
598 if (!opt || !opt[0] || strcmp(opt, "-") == 0)
599 return 1;
600
601 if (strcasecmp(opt, "a") == 0) {
602 sanity = 1;
603 poison = 1;
604 redzone = 1;
605 tracking = 1;
606 return 1;
607 }
608
609 for ( ; *opt; opt++)
610 switch (*opt) {
611 case 'F' : case 'f':
612 if (sanity)
613 return 0;
614 sanity = 1;
615 break;
616 case 'P' : case 'p':
617 if (poison)
618 return 0;
619 poison = 1;
620 break;
621
622 case 'Z' : case 'z':
623 if (redzone)
624 return 0;
625 redzone = 1;
626 break;
627
628 case 'U' : case 'u':
629 if (tracking)
630 return 0;
631 tracking = 1;
632 break;
633
634 case 'T' : case 't':
635 if (tracing)
636 return 0;
637 tracing = 1;
638 break;
639 default:
640 return 0;
641 }
642 return 1;
643}
644
645static int slab_empty(struct slabinfo *s)
646{
647 if (s->objects > 0)
648 return 0;
649
650 /*
651 * We may still have slabs even if there are no objects. Shrinking will
652 * remove them.
653 */
654 if (s->slabs != 0)
655 set_obj(s, "shrink", 1);
656
657 return 1;
658}
659
660static void slab_debug(struct slabinfo *s)
661{
662 if (strcmp(s->name, "*") == 0)
663 return;
664
665 if (sanity && !s->sanity_checks) {
666 set_obj(s, "sanity", 1);
667 }
668 if (!sanity && s->sanity_checks) {
669 if (slab_empty(s))
670 set_obj(s, "sanity", 0);
671 else
672 fprintf(stderr, "%s not empty cannot disable sanity checks\n", s->name);
673 }
674 if (redzone && !s->red_zone) {
675 if (slab_empty(s))
676 set_obj(s, "red_zone", 1);
677 else
678 fprintf(stderr, "%s not empty cannot enable redzoning\n", s->name);
679 }
680 if (!redzone && s->red_zone) {
681 if (slab_empty(s))
682 set_obj(s, "red_zone", 0);
683 else
684 fprintf(stderr, "%s not empty cannot disable redzoning\n", s->name);
685 }
686 if (poison && !s->poison) {
687 if (slab_empty(s))
688 set_obj(s, "poison", 1);
689 else
690 fprintf(stderr, "%s not empty cannot enable poisoning\n", s->name);
691 }
692 if (!poison && s->poison) {
693 if (slab_empty(s))
694 set_obj(s, "poison", 0);
695 else
696 fprintf(stderr, "%s not empty cannot disable poisoning\n", s->name);
697 }
698 if (tracking && !s->store_user) {
699 if (slab_empty(s))
700 set_obj(s, "store_user", 1);
701 else
702 fprintf(stderr, "%s not empty cannot enable tracking\n", s->name);
703 }
704 if (!tracking && s->store_user) {
705 if (slab_empty(s))
706 set_obj(s, "store_user", 0);
707 else
708 fprintf(stderr, "%s not empty cannot disable tracking\n", s->name);
709 }
710 if (tracing && !s->trace) {
711 if (slabs == 1)
712 set_obj(s, "trace", 1);
713 else
714 fprintf(stderr, "%s can only enable trace for one slab at a time\n", s->name);
715 }
716 if (!tracing && s->trace)
717 set_obj(s, "trace", 1);
718}
719
720static void totals(void)
721{
722 struct slabinfo *s;
723
724 int used_slabs = 0;
725 char b1[20], b2[20], b3[20], b4[20];
726 unsigned long long max = 1ULL << 63;
727
728 /* Object size */
729 unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
730
731 /* Number of partial slabs in a slabcache */
732 unsigned long long min_partial = max, max_partial = 0,
733 avg_partial, total_partial = 0;
734
735 /* Number of slabs in a slab cache */
736 unsigned long long min_slabs = max, max_slabs = 0,
737 avg_slabs, total_slabs = 0;
738
739 /* Size of the whole slab */
740 unsigned long long min_size = max, max_size = 0,
741 avg_size, total_size = 0;
742
743 /* Bytes used for object storage in a slab */
744 unsigned long long min_used = max, max_used = 0,
745 avg_used, total_used = 0;
746
747 /* Waste: Bytes used for alignment and padding */
748 unsigned long long min_waste = max, max_waste = 0,
749 avg_waste, total_waste = 0;
750 /* Number of objects in a slab */
751 unsigned long long min_objects = max, max_objects = 0,
752 avg_objects, total_objects = 0;
753 /* Waste per object */
754 unsigned long long min_objwaste = max,
755 max_objwaste = 0, avg_objwaste,
756 total_objwaste = 0;
757
758 /* Memory per object */
759 unsigned long long min_memobj = max,
760 max_memobj = 0, avg_memobj,
761 total_objsize = 0;
762
763 /* Percentage of partial slabs per slab */
764 unsigned long min_ppart = 100, max_ppart = 0,
765 avg_ppart, total_ppart = 0;
766
767 /* Number of objects in partial slabs */
768 unsigned long min_partobj = max, max_partobj = 0,
769 avg_partobj, total_partobj = 0;
770
771 /* Percentage of partial objects of all objects in a slab */
772 unsigned long min_ppartobj = 100, max_ppartobj = 0,
773 avg_ppartobj, total_ppartobj = 0;
774
775
776 for (s = slabinfo; s < slabinfo + slabs; s++) {
777 unsigned long long size;
778 unsigned long used;
779 unsigned long long wasted;
780 unsigned long long objwaste;
781 unsigned long percentage_partial_slabs;
782 unsigned long percentage_partial_objs;
783
784 if (!s->slabs || !s->objects)
785 continue;
786
787 used_slabs++;
788
789 size = slab_size(s);
790 used = s->objects * s->object_size;
791 wasted = size - used;
792 objwaste = s->slab_size - s->object_size;
793
794 percentage_partial_slabs = s->partial * 100 / s->slabs;
795 if (percentage_partial_slabs > 100)
796 percentage_partial_slabs = 100;
797
798 percentage_partial_objs = s->objects_partial * 100
799 / s->objects;
800
801 if (percentage_partial_objs > 100)
802 percentage_partial_objs = 100;
803
804 if (s->object_size < min_objsize)
805 min_objsize = s->object_size;
806 if (s->partial < min_partial)
807 min_partial = s->partial;
808 if (s->slabs < min_slabs)
809 min_slabs = s->slabs;
810 if (size < min_size)
811 min_size = size;
812 if (wasted < min_waste)
813 min_waste = wasted;
814 if (objwaste < min_objwaste)
815 min_objwaste = objwaste;
816 if (s->objects < min_objects)
817 min_objects = s->objects;
818 if (used < min_used)
819 min_used = used;
820 if (s->objects_partial < min_partobj)
821 min_partobj = s->objects_partial;
822 if (percentage_partial_slabs < min_ppart)
823 min_ppart = percentage_partial_slabs;
824 if (percentage_partial_objs < min_ppartobj)
825 min_ppartobj = percentage_partial_objs;
826 if (s->slab_size < min_memobj)
827 min_memobj = s->slab_size;
828
829 if (s->object_size > max_objsize)
830 max_objsize = s->object_size;
831 if (s->partial > max_partial)
832 max_partial = s->partial;
833 if (s->slabs > max_slabs)
834 max_slabs = s->slabs;
835 if (size > max_size)
836 max_size = size;
837 if (wasted > max_waste)
838 max_waste = wasted;
839 if (objwaste > max_objwaste)
840 max_objwaste = objwaste;
841 if (s->objects > max_objects)
842 max_objects = s->objects;
843 if (used > max_used)
844 max_used = used;
845 if (s->objects_partial > max_partobj)
846 max_partobj = s->objects_partial;
847 if (percentage_partial_slabs > max_ppart)
848 max_ppart = percentage_partial_slabs;
849 if (percentage_partial_objs > max_ppartobj)
850 max_ppartobj = percentage_partial_objs;
851 if (s->slab_size > max_memobj)
852 max_memobj = s->slab_size;
853
854 total_partial += s->partial;
855 total_slabs += s->slabs;
856 total_size += size;
857 total_waste += wasted;
858
859 total_objects += s->objects;
860 total_used += used;
861 total_partobj += s->objects_partial;
862 total_ppart += percentage_partial_slabs;
863 total_ppartobj += percentage_partial_objs;
864
865 total_objwaste += s->objects * objwaste;
866 total_objsize += s->objects * s->slab_size;
867 }
868
869 if (!total_objects) {
870 printf("No objects\n");
871 return;
872 }
873 if (!used_slabs) {
874 printf("No slabs\n");
875 return;
876 }
877
878 /* Per slab averages */
879 avg_partial = total_partial / used_slabs;
880 avg_slabs = total_slabs / used_slabs;
881 avg_size = total_size / used_slabs;
882 avg_waste = total_waste / used_slabs;
883
884 avg_objects = total_objects / used_slabs;
885 avg_used = total_used / used_slabs;
886 avg_partobj = total_partobj / used_slabs;
887 avg_ppart = total_ppart / used_slabs;
888 avg_ppartobj = total_ppartobj / used_slabs;
889
890 /* Per object object sizes */
891 avg_objsize = total_used / total_objects;
892 avg_objwaste = total_objwaste / total_objects;
893 avg_partobj = total_partobj * 100 / total_objects;
894 avg_memobj = total_objsize / total_objects;
895
896 printf("Slabcache Totals\n");
897 printf("----------------\n");
898 printf("Slabcaches : %3d Aliases : %3d->%-3d Active: %3d\n",
899 slabs, aliases, alias_targets, used_slabs);
900
901 store_size(b1, total_size);store_size(b2, total_waste);
902 store_size(b3, total_waste * 100 / total_used);
903 printf("Memory used: %6s # Loss : %6s MRatio:%6s%%\n", b1, b2, b3);
904
905 store_size(b1, total_objects);store_size(b2, total_partobj);
906 store_size(b3, total_partobj * 100 / total_objects);
907 printf("# Objects : %6s # PartObj: %6s ORatio:%6s%%\n", b1, b2, b3);
908
909 printf("\n");
910 printf("Per Cache Average Min Max Total\n");
911 printf("---------------------------------------------------------\n");
912
913 store_size(b1, avg_objects);store_size(b2, min_objects);
914 store_size(b3, max_objects);store_size(b4, total_objects);
915 printf("#Objects %10s %10s %10s %10s\n",
916 b1, b2, b3, b4);
917
918 store_size(b1, avg_slabs);store_size(b2, min_slabs);
919 store_size(b3, max_slabs);store_size(b4, total_slabs);
920 printf("#Slabs %10s %10s %10s %10s\n",
921 b1, b2, b3, b4);
922
923 store_size(b1, avg_partial);store_size(b2, min_partial);
924 store_size(b3, max_partial);store_size(b4, total_partial);
925 printf("#PartSlab %10s %10s %10s %10s\n",
926 b1, b2, b3, b4);
927 store_size(b1, avg_ppart);store_size(b2, min_ppart);
928 store_size(b3, max_ppart);
929 store_size(b4, total_partial * 100 / total_slabs);
930 printf("%%PartSlab%10s%% %10s%% %10s%% %10s%%\n",
931 b1, b2, b3, b4);
932
933 store_size(b1, avg_partobj);store_size(b2, min_partobj);
934 store_size(b3, max_partobj);
935 store_size(b4, total_partobj);
936 printf("PartObjs %10s %10s %10s %10s\n",
937 b1, b2, b3, b4);
938
939 store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj);
940 store_size(b3, max_ppartobj);
941 store_size(b4, total_partobj * 100 / total_objects);
942 printf("%% PartObj%10s%% %10s%% %10s%% %10s%%\n",
943 b1, b2, b3, b4);
944
945 store_size(b1, avg_size);store_size(b2, min_size);
946 store_size(b3, max_size);store_size(b4, total_size);
947 printf("Memory %10s %10s %10s %10s\n",
948 b1, b2, b3, b4);
949
950 store_size(b1, avg_used);store_size(b2, min_used);
951 store_size(b3, max_used);store_size(b4, total_used);
952 printf("Used %10s %10s %10s %10s\n",
953 b1, b2, b3, b4);
954
955 store_size(b1, avg_waste);store_size(b2, min_waste);
956 store_size(b3, max_waste);store_size(b4, total_waste);
957 printf("Loss %10s %10s %10s %10s\n",
958 b1, b2, b3, b4);
959
960 printf("\n");
961 printf("Per Object Average Min Max\n");
962 printf("---------------------------------------------\n");
963
964 store_size(b1, avg_memobj);store_size(b2, min_memobj);
965 store_size(b3, max_memobj);
966 printf("Memory %10s %10s %10s\n",
967 b1, b2, b3);
968 store_size(b1, avg_objsize);store_size(b2, min_objsize);
969 store_size(b3, max_objsize);
970 printf("User %10s %10s %10s\n",
971 b1, b2, b3);
972
973 store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
974 store_size(b3, max_objwaste);
975 printf("Loss %10s %10s %10s\n",
976 b1, b2, b3);
977}
978
979static void sort_slabs(void)
980{
981 struct slabinfo *s1,*s2;
982
983 for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
984 for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
985 int result;
986
987 if (sort_size)
988 result = slab_size(s1) < slab_size(s2);
989 else if (sort_active)
990 result = slab_activity(s1) < slab_activity(s2);
991 else
992 result = strcasecmp(s1->name, s2->name);
993
994 if (show_inverted)
995 result = -result;
996
997 if (result > 0) {
998 struct slabinfo t;
999
1000 memcpy(&t, s1, sizeof(struct slabinfo));
1001 memcpy(s1, s2, sizeof(struct slabinfo));
1002 memcpy(s2, &t, sizeof(struct slabinfo));
1003 }
1004 }
1005 }
1006}
1007
1008static void sort_aliases(void)
1009{
1010 struct aliasinfo *a1,*a2;
1011
1012 for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) {
1013 for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) {
1014 char *n1, *n2;
1015
1016 n1 = a1->name;
1017 n2 = a2->name;
1018 if (show_alias && !show_inverted) {
1019 n1 = a1->ref;
1020 n2 = a2->ref;
1021 }
1022 if (strcasecmp(n1, n2) > 0) {
1023 struct aliasinfo t;
1024
1025 memcpy(&t, a1, sizeof(struct aliasinfo));
1026 memcpy(a1, a2, sizeof(struct aliasinfo));
1027 memcpy(a2, &t, sizeof(struct aliasinfo));
1028 }
1029 }
1030 }
1031}
1032
1033static void link_slabs(void)
1034{
1035 struct aliasinfo *a;
1036 struct slabinfo *s;
1037
1038 for (a = aliasinfo; a < aliasinfo + aliases; a++) {
1039
1040 for (s = slabinfo; s < slabinfo + slabs; s++)
1041 if (strcmp(a->ref, s->name) == 0) {
1042 a->slab = s;
1043 s->refs++;
1044 break;
1045 }
1046 if (s == slabinfo + slabs)
1047 fatal("Unresolved alias %s\n", a->ref);
1048 }
1049}
1050
1051static void alias(void)
1052{
1053 struct aliasinfo *a;
1054 char *active = NULL;
1055
1056 sort_aliases();
1057 link_slabs();
1058
1059 for(a = aliasinfo; a < aliasinfo + aliases; a++) {
1060
1061 if (!show_single_ref && a->slab->refs == 1)
1062 continue;
1063
1064 if (!show_inverted) {
1065 if (active) {
1066 if (strcmp(a->slab->name, active) == 0) {
1067 printf(" %s", a->name);
1068 continue;
1069 }
1070 }
1071 printf("\n%-12s <- %s", a->slab->name, a->name);
1072 active = a->slab->name;
1073 }
1074 else
1075 printf("%-20s -> %s\n", a->name, a->slab->name);
1076 }
1077 if (active)
1078 printf("\n");
1079}
1080
1081
1082static void rename_slabs(void)
1083{
1084 struct slabinfo *s;
1085 struct aliasinfo *a;
1086
1087 for (s = slabinfo; s < slabinfo + slabs; s++) {
1088 if (*s->name != ':')
1089 continue;
1090
1091 if (s->refs > 1 && !show_first_alias)
1092 continue;
1093
1094 a = find_one_alias(s);
1095
1096 if (a)
1097 s->name = a->name;
1098 else {
1099 s->name = "*";
1100 actual_slabs--;
1101 }
1102 }
1103}
1104
1105static int slab_mismatch(char *slab)
1106{
1107 return regexec(&pattern, slab, 0, NULL, 0);
1108}
1109
1110static void read_slab_dir(void)
1111{
1112 DIR *dir;
1113 struct dirent *de;
1114 struct slabinfo *slab = slabinfo;
1115 struct aliasinfo *alias = aliasinfo;
1116 char *p;
1117 char *t;
1118 int count;
1119
1120 if (chdir("/sys/kernel/slab") && chdir("/sys/slab"))
1121 fatal("SYSFS support for SLUB not active\n");
1122
1123 dir = opendir(".");
1124 while ((de = readdir(dir))) {
1125 if (de->d_name[0] == '.' ||
1126 (de->d_name[0] != ':' && slab_mismatch(de->d_name)))
1127 continue;
1128 switch (de->d_type) {
1129 case DT_LNK:
1130 alias->name = strdup(de->d_name);
1131 count = readlink(de->d_name, buffer, sizeof(buffer));
1132
1133 if (count < 0)
1134 fatal("Cannot read symlink %s\n", de->d_name);
1135
1136 buffer[count] = 0;
1137 p = buffer + count;
1138 while (p > buffer && p[-1] != '/')
1139 p--;
1140 alias->ref = strdup(p);
1141 alias++;
1142 break;
1143 case DT_DIR:
1144 if (chdir(de->d_name))
1145 fatal("Unable to access slab %s\n", slab->name);
1146 slab->name = strdup(de->d_name);
1147 slab->alias = 0;
1148 slab->refs = 0;
1149 slab->aliases = get_obj("aliases");
1150 slab->align = get_obj("align");
1151 slab->cache_dma = get_obj("cache_dma");
1152 slab->cpu_slabs = get_obj("cpu_slabs");
1153 slab->destroy_by_rcu = get_obj("destroy_by_rcu");
1154 slab->hwcache_align = get_obj("hwcache_align");
1155 slab->object_size = get_obj("object_size");
1156 slab->objects = get_obj("objects");
1157 slab->objects_partial = get_obj("objects_partial");
1158 slab->objects_total = get_obj("objects_total");
1159 slab->objs_per_slab = get_obj("objs_per_slab");
1160 slab->order = get_obj("order");
1161 slab->partial = get_obj("partial");
1162 slab->partial = get_obj_and_str("partial", &t);
1163 decode_numa_list(slab->numa_partial, t);
1164 free(t);
1165 slab->poison = get_obj("poison");
1166 slab->reclaim_account = get_obj("reclaim_account");
1167 slab->red_zone = get_obj("red_zone");
1168 slab->sanity_checks = get_obj("sanity_checks");
1169 slab->slab_size = get_obj("slab_size");
1170 slab->slabs = get_obj_and_str("slabs", &t);
1171 decode_numa_list(slab->numa, t);
1172 free(t);
1173 slab->store_user = get_obj("store_user");
1174 slab->trace = get_obj("trace");
1175 slab->alloc_fastpath = get_obj("alloc_fastpath");
1176 slab->alloc_slowpath = get_obj("alloc_slowpath");
1177 slab->free_fastpath = get_obj("free_fastpath");
1178 slab->free_slowpath = get_obj("free_slowpath");
1179 slab->free_frozen= get_obj("free_frozen");
1180 slab->free_add_partial = get_obj("free_add_partial");
1181 slab->free_remove_partial = get_obj("free_remove_partial");
1182 slab->alloc_from_partial = get_obj("alloc_from_partial");
1183 slab->alloc_slab = get_obj("alloc_slab");
1184 slab->alloc_refill = get_obj("alloc_refill");
1185 slab->free_slab = get_obj("free_slab");
1186 slab->cpuslab_flush = get_obj("cpuslab_flush");
1187 slab->deactivate_full = get_obj("deactivate_full");
1188 slab->deactivate_empty = get_obj("deactivate_empty");
1189 slab->deactivate_to_head = get_obj("deactivate_to_head");
1190 slab->deactivate_to_tail = get_obj("deactivate_to_tail");
1191 slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
1192 slab->order_fallback = get_obj("order_fallback");
1193 chdir("..");
1194 if (slab->name[0] == ':')
1195 alias_targets++;
1196 slab++;
1197 break;
1198 default :
1199 fatal("Unknown file type %lx\n", de->d_type);
1200 }
1201 }
1202 closedir(dir);
1203 slabs = slab - slabinfo;
1204 actual_slabs = slabs;
1205 aliases = alias - aliasinfo;
1206 if (slabs > MAX_SLABS)
1207 fatal("Too many slabs\n");
1208 if (aliases > MAX_ALIASES)
1209 fatal("Too many aliases\n");
1210}
1211
1212static void output_slabs(void)
1213{
1214 struct slabinfo *slab;
1215
1216 for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
1217
1218 if (slab->alias)
1219 continue;
1220
1221
1222 if (show_numa)
1223 slab_numa(slab, 0);
1224 else if (show_track)
1225 show_tracking(slab);
1226 else if (validate)
1227 slab_validate(slab);
1228 else if (shrink)
1229 slab_shrink(slab);
1230 else if (set_debug)
1231 slab_debug(slab);
1232 else if (show_ops)
1233 ops(slab);
1234 else if (show_slab)
1235 slabcache(slab);
1236 else if (show_report)
1237 report(slab);
1238 }
1239}
1240
1241struct option opts[] = {
1242 { "aliases", 0, NULL, 'a' },
1243 { "activity", 0, NULL, 'A' },
1244 { "debug", 2, NULL, 'd' },
1245 { "display-activity", 0, NULL, 'D' },
1246 { "empty", 0, NULL, 'e' },
1247 { "first-alias", 0, NULL, 'f' },
1248 { "help", 0, NULL, 'h' },
1249 { "inverted", 0, NULL, 'i'},
1250 { "numa", 0, NULL, 'n' },
1251 { "ops", 0, NULL, 'o' },
1252 { "report", 0, NULL, 'r' },
1253 { "shrink", 0, NULL, 's' },
1254 { "slabs", 0, NULL, 'l' },
1255 { "track", 0, NULL, 't'},
1256 { "validate", 0, NULL, 'v' },
1257 { "zero", 0, NULL, 'z' },
1258 { "1ref", 0, NULL, '1'},
1259 { NULL, 0, NULL, 0 }
1260};
1261
1262int main(int argc, char *argv[])
1263{
1264 int c;
1265 int err;
1266 char *pattern_source;
1267
1268 page_size = getpagesize();
1269
1270 while ((c = getopt_long(argc, argv, "aAd::Defhil1noprstvzTS",
1271 opts, NULL)) != -1)
1272 switch (c) {
1273 case '1':
1274 show_single_ref = 1;
1275 break;
1276 case 'a':
1277 show_alias = 1;
1278 break;
1279 case 'A':
1280 sort_active = 1;
1281 break;
1282 case 'd':
1283 set_debug = 1;
1284 if (!debug_opt_scan(optarg))
1285 fatal("Invalid debug option '%s'\n", optarg);
1286 break;
1287 case 'D':
1288 show_activity = 1;
1289 break;
1290 case 'e':
1291 show_empty = 1;
1292 break;
1293 case 'f':
1294 show_first_alias = 1;
1295 break;
1296 case 'h':
1297 usage();
1298 return 0;
1299 case 'i':
1300 show_inverted = 1;
1301 break;
1302 case 'n':
1303 show_numa = 1;
1304 break;
1305 case 'o':
1306 show_ops = 1;
1307 break;
1308 case 'r':
1309 show_report = 1;
1310 break;
1311 case 's':
1312 shrink = 1;
1313 break;
1314 case 'l':
1315 show_slab = 1;
1316 break;
1317 case 't':
1318 show_track = 1;
1319 break;
1320 case 'v':
1321 validate = 1;
1322 break;
1323 case 'z':
1324 skip_zero = 0;
1325 break;
1326 case 'T':
1327 show_totals = 1;
1328 break;
1329 case 'S':
1330 sort_size = 1;
1331 break;
1332
1333 default:
1334 fatal("%s: Invalid option '%c'\n", argv[0], optopt);
1335
1336 }
1337
1338 if (!show_slab && !show_alias && !show_track && !show_report
1339 && !validate && !shrink && !set_debug && !show_ops)
1340 show_slab = 1;
1341
1342 if (argc > optind)
1343 pattern_source = argv[optind];
1344 else
1345 pattern_source = ".*";
1346
1347 err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
1348 if (err)
1349 fatal("%s: Invalid pattern '%s' code %d\n",
1350 argv[0], pattern_source, err);
1351 read_slab_dir();
1352 if (show_alias)
1353 alias();
1354 else
1355 if (show_totals)
1356 totals();
1357 else {
1358 link_slabs();
1359 rename_slabs();
1360 sort_slabs();
1361 output_slabs();
1362 }
1363 return 0;
1364}
diff --git a/tools/testing/ktest/compare-ktest-sample.pl b/tools/testing/ktest/compare-ktest-sample.pl
new file mode 100755
index 000000000000..9a571e71683c
--- /dev/null
+++ b/tools/testing/ktest/compare-ktest-sample.pl
@@ -0,0 +1,30 @@
1#!/usr/bin/perl
2
3open (IN,"ktest.pl");
4while (<IN>) {
5 if (/\$opt\{"?([A-Z].*?)(\[.*\])?"?\}/ ||
6 /set_test_option\("(.*?)"/) {
7 $opt{$1} = 1;
8 }
9}
10close IN;
11
12open (IN, "sample.conf");
13while (<IN>) {
14 if (/^\s*#?\s*(\S+)\s*=/) {
15 $samp{$1} = 1;
16 }
17}
18close IN;
19
20foreach $opt (keys %opt) {
21 if (!defined($samp{$opt})) {
22 print "opt = $opt\n";
23 }
24}
25
26foreach $samp (keys %samp) {
27 if (!defined($opt{$samp})) {
28 print "samp = $samp\n";
29 }
30}
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
new file mode 100755
index 000000000000..e1c62eeb88f5
--- /dev/null
+++ b/tools/testing/ktest/ktest.pl
@@ -0,0 +1,2023 @@
1#!/usr/bin/perl -w
2#
3# Copywrite 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4# Licensed under the terms of the GNU GPL License version 2
5#
6
7use strict;
8use IPC::Open2;
9use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
10use File::Path qw(mkpath);
11use File::Copy qw(cp);
12use FileHandle;
13
14my $VERSION = "0.2";
15
16$| = 1;
17
18my %opt;
19my %repeat_tests;
20my %repeats;
21my %default;
22
23#default opts
24$default{"NUM_TESTS"} = 1;
25$default{"REBOOT_TYPE"} = "grub";
26$default{"TEST_TYPE"} = "test";
27$default{"BUILD_TYPE"} = "randconfig";
28$default{"MAKE_CMD"} = "make";
29$default{"TIMEOUT"} = 120;
30$default{"TMP_DIR"} = "/tmp/ktest";
31$default{"SLEEP_TIME"} = 60; # sleep time between tests
32$default{"BUILD_NOCLEAN"} = 0;
33$default{"REBOOT_ON_ERROR"} = 0;
34$default{"POWEROFF_ON_ERROR"} = 0;
35$default{"REBOOT_ON_SUCCESS"} = 1;
36$default{"POWEROFF_ON_SUCCESS"} = 0;
37$default{"BUILD_OPTIONS"} = "";
38$default{"BISECT_SLEEP_TIME"} = 60; # sleep time between bisects
39$default{"CLEAR_LOG"} = 0;
40$default{"SUCCESS_LINE"} = "login:";
41$default{"BOOTED_TIMEOUT"} = 1;
42$default{"DIE_ON_FAILURE"} = 1;
43$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
44$default{"SCP_TO_TARGET"} = "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
45$default{"REBOOT"} = "ssh \$SSH_USER\@\$MACHINE reboot";
46$default{"STOP_AFTER_SUCCESS"} = 10;
47$default{"STOP_AFTER_FAILURE"} = 60;
48$default{"LOCALVERSION"} = "-test";
49
50my $ktest_config;
51my $version;
52my $machine;
53my $ssh_user;
54my $tmpdir;
55my $builddir;
56my $outputdir;
57my $output_config;
58my $test_type;
59my $build_type;
60my $build_options;
61my $reboot_type;
62my $reboot_script;
63my $power_cycle;
64my $reboot;
65my $reboot_on_error;
66my $poweroff_on_error;
67my $die_on_failure;
68my $powercycle_after_reboot;
69my $poweroff_after_halt;
70my $ssh_exec;
71my $scp_to_target;
72my $power_off;
73my $grub_menu;
74my $grub_number;
75my $target;
76my $make;
77my $post_install;
78my $noclean;
79my $minconfig;
80my $addconfig;
81my $in_bisect = 0;
82my $bisect_bad = "";
83my $reverse_bisect;
84my $in_patchcheck = 0;
85my $run_test;
86my $redirect;
87my $buildlog;
88my $dmesg;
89my $monitor_fp;
90my $monitor_pid;
91my $monitor_cnt = 0;
92my $sleep_time;
93my $bisect_sleep_time;
94my $store_failures;
95my $timeout;
96my $booted_timeout;
97my $console;
98my $success_line;
99my $stop_after_success;
100my $stop_after_failure;
101my $build_target;
102my $target_image;
103my $localversion;
104my $iteration = 0;
105my $successes = 0;
106
107my %entered_configs;
108my %config_help;
109
110$config_help{"MACHINE"} = << "EOF"
111 The machine hostname that you will test.
112EOF
113 ;
114$config_help{"SSH_USER"} = << "EOF"
115 The box is expected to have ssh on normal bootup, provide the user
116 (most likely root, since you need privileged operations)
117EOF
118 ;
119$config_help{"BUILD_DIR"} = << "EOF"
120 The directory that contains the Linux source code (full path).
121EOF
122 ;
123$config_help{"OUTPUT_DIR"} = << "EOF"
124 The directory that the objects will be built (full path).
125 (can not be same as BUILD_DIR)
126EOF
127 ;
128$config_help{"BUILD_TARGET"} = << "EOF"
129 The location of the compiled file to copy to the target.
130 (relative to OUTPUT_DIR)
131EOF
132 ;
133$config_help{"TARGET_IMAGE"} = << "EOF"
134 The place to put your image on the test machine.
135EOF
136 ;
137$config_help{"POWER_CYCLE"} = << "EOF"
138 A script or command to reboot the box.
139
140 Here is a digital loggers power switch example
141 POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
142
143 Here is an example to reboot a virtual box on the current host
144 with the name "Guest".
145 POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
146EOF
147 ;
148$config_help{"CONSOLE"} = << "EOF"
149 The script or command that reads the console
150
151 If you use ttywatch server, something like the following would work.
152CONSOLE = nc -d localhost 3001
153
154 For a virtual machine with guest name "Guest".
155CONSOLE = virsh console Guest
156EOF
157 ;
158$config_help{"LOCALVERSION"} = << "EOF"
159 Required version ending to differentiate the test
160 from other linux builds on the system.
161EOF
162 ;
163$config_help{"REBOOT_TYPE"} = << "EOF"
164 Way to reboot the box to the test kernel.
165 Only valid options so far are "grub" and "script".
166
167 If you specify grub, it will assume grub version 1
168 and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
169 and select that target to reboot to the kernel. If this is not
170 your setup, then specify "script" and have a command or script
171 specified in REBOOT_SCRIPT to boot to the target.
172
173 The entry in /boot/grub/menu.lst must be entered in manually.
174 The test will not modify that file.
175EOF
176 ;
177$config_help{"GRUB_MENU"} = << "EOF"
178 The grub title name for the test kernel to boot
179 (Only mandatory if REBOOT_TYPE = grub)
180
181 Note, ktest.pl will not update the grub menu.lst, you need to
182 manually add an option for the test. ktest.pl will search
183 the grub menu.lst for this option to find what kernel to
184 reboot into.
185
186 For example, if in the /boot/grub/menu.lst the test kernel title has:
187 title Test Kernel
188 kernel vmlinuz-test
189 GRUB_MENU = Test Kernel
190EOF
191 ;
192$config_help{"REBOOT_SCRIPT"} = << "EOF"
193 A script to reboot the target into the test kernel
194 (Only mandatory if REBOOT_TYPE = script)
195EOF
196 ;
197
198
199sub get_ktest_config {
200 my ($config) = @_;
201
202 return if (defined($opt{$config}));
203
204 if (defined($config_help{$config})) {
205 print "\n";
206 print $config_help{$config};
207 }
208
209 for (;;) {
210 print "$config = ";
211 if (defined($default{$config})) {
212 print "\[$default{$config}\] ";
213 }
214 $entered_configs{$config} = <STDIN>;
215 $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
216 if ($entered_configs{$config} =~ /^\s*$/) {
217 if ($default{$config}) {
218 $entered_configs{$config} = $default{$config};
219 } else {
220 print "Your answer can not be blank\n";
221 next;
222 }
223 }
224 last;
225 }
226}
227
228sub get_ktest_configs {
229 get_ktest_config("MACHINE");
230 get_ktest_config("SSH_USER");
231 get_ktest_config("BUILD_DIR");
232 get_ktest_config("OUTPUT_DIR");
233 get_ktest_config("BUILD_TARGET");
234 get_ktest_config("TARGET_IMAGE");
235 get_ktest_config("POWER_CYCLE");
236 get_ktest_config("CONSOLE");
237 get_ktest_config("LOCALVERSION");
238
239 my $rtype = $opt{"REBOOT_TYPE"};
240
241 if (!defined($rtype)) {
242 if (!defined($opt{"GRUB_MENU"})) {
243 get_ktest_config("REBOOT_TYPE");
244 $rtype = $entered_configs{"REBOOT_TYPE"};
245 } else {
246 $rtype = "grub";
247 }
248 }
249
250 if ($rtype eq "grub") {
251 get_ktest_config("GRUB_MENU");
252 } else {
253 get_ktest_config("REBOOT_SCRIPT");
254 }
255}
256
257sub set_value {
258 my ($lvalue, $rvalue) = @_;
259
260 if (defined($opt{$lvalue})) {
261 die "Error: Option $lvalue defined more than once!\n";
262 }
263 if ($rvalue =~ /^\s*$/) {
264 delete $opt{$lvalue};
265 } else {
266 $opt{$lvalue} = $rvalue;
267 }
268}
269
270sub read_config {
271 my ($config) = @_;
272
273 open(IN, $config) || die "can't read file $config";
274
275 my $name = $config;
276 $name =~ s,.*/(.*),$1,;
277
278 my $test_num = 0;
279 my $default = 1;
280 my $repeat = 1;
281 my $num_tests_set = 0;
282 my $skip = 0;
283 my $rest;
284
285 while (<IN>) {
286
287 # ignore blank lines and comments
288 next if (/^\s*$/ || /\s*\#/);
289
290 if (/^\s*TEST_START(.*)/) {
291
292 $rest = $1;
293
294 if ($num_tests_set) {
295 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
296 }
297
298 my $old_test_num = $test_num;
299 my $old_repeat = $repeat;
300
301 $test_num += $repeat;
302 $default = 0;
303 $repeat = 1;
304
305 if ($rest =~ /\s+SKIP(.*)/) {
306 $rest = $1;
307 $skip = 1;
308 } else {
309 $skip = 0;
310 }
311
312 if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
313 $repeat = $1;
314 $rest = $2;
315 $repeat_tests{"$test_num"} = $repeat;
316 }
317
318 if ($rest =~ /\s+SKIP(.*)/) {
319 $rest = $1;
320 $skip = 1;
321 }
322
323 if ($rest !~ /^\s*$/) {
324 die "$name: $.: Gargbage found after TEST_START\n$_";
325 }
326
327 if ($skip) {
328 $test_num = $old_test_num;
329 $repeat = $old_repeat;
330 }
331
332 } elsif (/^\s*DEFAULTS(.*)$/) {
333 $default = 1;
334
335 $rest = $1;
336
337 if ($rest =~ /\s+SKIP(.*)/) {
338 $rest = $1;
339 $skip = 1;
340 } else {
341 $skip = 0;
342 }
343
344 if ($rest !~ /^\s*$/) {
345 die "$name: $.: Gargbage found after DEFAULTS\n$_";
346 }
347
348 } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
349
350 next if ($skip);
351
352 my $lvalue = $1;
353 my $rvalue = $2;
354
355 if (!$default &&
356 ($lvalue eq "NUM_TESTS" ||
357 $lvalue eq "LOG_FILE" ||
358 $lvalue eq "CLEAR_LOG")) {
359 die "$name: $.: $lvalue must be set in DEFAULTS section\n";
360 }
361
362 if ($lvalue eq "NUM_TESTS") {
363 if ($test_num) {
364 die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
365 }
366 if (!$default) {
367 die "$name: $.: NUM_TESTS must be set in default section\n";
368 }
369 $num_tests_set = 1;
370 }
371
372 if ($default || $lvalue =~ /\[\d+\]$/) {
373 set_value($lvalue, $rvalue);
374 } else {
375 my $val = "$lvalue\[$test_num\]";
376 set_value($val, $rvalue);
377
378 if ($repeat > 1) {
379 $repeats{$val} = $repeat;
380 }
381 }
382 } else {
383 die "$name: $.: Garbage found in config\n$_";
384 }
385 }
386
387 close(IN);
388
389 if ($test_num) {
390 $test_num += $repeat - 1;
391 $opt{"NUM_TESTS"} = $test_num;
392 }
393
394 # make sure we have all mandatory configs
395 get_ktest_configs;
396
397 # set any defaults
398
399 foreach my $default (keys %default) {
400 if (!defined($opt{$default})) {
401 $opt{$default} = $default{$default};
402 }
403 }
404}
405
406sub _logit {
407 if (defined($opt{"LOG_FILE"})) {
408 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
409 print OUT @_;
410 close(OUT);
411 }
412}
413
414sub logit {
415 if (defined($opt{"LOG_FILE"})) {
416 _logit @_;
417 } else {
418 print @_;
419 }
420}
421
422sub doprint {
423 print @_;
424 _logit @_;
425}
426
427sub run_command;
428
429sub reboot {
430 # try to reboot normally
431 if (run_command $reboot) {
432 if (defined($powercycle_after_reboot)) {
433 sleep $powercycle_after_reboot;
434 run_command "$power_cycle";
435 }
436 } else {
437 # nope? power cycle it.
438 run_command "$power_cycle";
439 }
440}
441
442sub do_not_reboot {
443 my $i = $iteration;
444
445 return $test_type eq "build" ||
446 ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
447 ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
448}
449
450sub dodie {
451 doprint "CRITICAL FAILURE... ", @_, "\n";
452
453 my $i = $iteration;
454
455 if ($reboot_on_error && !do_not_reboot) {
456
457 doprint "REBOOTING\n";
458 reboot;
459
460 } elsif ($poweroff_on_error && defined($power_off)) {
461 doprint "POWERING OFF\n";
462 `$power_off`;
463 }
464
465 die @_, "\n";
466}
467
468sub open_console {
469 my ($fp) = @_;
470
471 my $flags;
472
473 my $pid = open($fp, "$console|") or
474 dodie "Can't open console $console";
475
476 $flags = fcntl($fp, F_GETFL, 0) or
477 dodie "Can't get flags for the socket: $!";
478 $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
479 dodie "Can't set flags for the socket: $!";
480
481 return $pid;
482}
483
484sub close_console {
485 my ($fp, $pid) = @_;
486
487 doprint "kill child process $pid\n";
488 kill 2, $pid;
489
490 print "closing!\n";
491 close($fp);
492}
493
494sub start_monitor {
495 if ($monitor_cnt++) {
496 return;
497 }
498 $monitor_fp = \*MONFD;
499 $monitor_pid = open_console $monitor_fp;
500
501 return;
502
503 open(MONFD, "Stop perl from warning about single use of MONFD");
504}
505
506sub end_monitor {
507 if (--$monitor_cnt) {
508 return;
509 }
510 close_console($monitor_fp, $monitor_pid);
511}
512
513sub wait_for_monitor {
514 my ($time) = @_;
515 my $line;
516
517 doprint "** Wait for monitor to settle down **\n";
518
519 # read the monitor and wait for the system to calm down
520 do {
521 $line = wait_for_input($monitor_fp, $time);
522 print "$line" if (defined($line));
523 } while (defined($line));
524 print "** Monitor flushed **\n";
525}
526
527sub fail {
528
529 if ($die_on_failure) {
530 dodie @_;
531 }
532
533 doprint "FAILED\n";
534
535 my $i = $iteration;
536
537 # no need to reboot for just building.
538 if (!do_not_reboot) {
539 doprint "REBOOTING\n";
540 reboot;
541 start_monitor;
542 wait_for_monitor $sleep_time;
543 end_monitor;
544 }
545
546 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
547 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
548 doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n";
549 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
550 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
551
552 return 1 if (!defined($store_failures));
553
554 my @t = localtime;
555 my $date = sprintf "%04d%02d%02d%02d%02d%02d",
556 1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
557
558 my $type = $build_type;
559 if ($type =~ /useconfig/) {
560 $type = "useconfig";
561 }
562
563 my $dir = "$machine-$test_type-$type-fail-$date";
564 my $faildir = "$store_failures/$dir";
565
566 if (!-d $faildir) {
567 mkpath($faildir) or
568 die "can't create $faildir";
569 }
570 if (-f "$output_config") {
571 cp "$output_config", "$faildir/config" or
572 die "failed to copy .config";
573 }
574 if (-f $buildlog) {
575 cp $buildlog, "$faildir/buildlog" or
576 die "failed to move $buildlog";
577 }
578 if (-f $dmesg) {
579 cp $dmesg, "$faildir/dmesg" or
580 die "failed to move $dmesg";
581 }
582
583 doprint "*** Saved info to $faildir ***\n";
584
585 return 1;
586}
587
588sub run_command {
589 my ($command) = @_;
590 my $dolog = 0;
591 my $dord = 0;
592 my $pid;
593
594 $command =~ s/\$SSH_USER/$ssh_user/g;
595 $command =~ s/\$MACHINE/$machine/g;
596
597 doprint("$command ... ");
598
599 $pid = open(CMD, "$command 2>&1 |") or
600 (fail "unable to exec $command" and return 0);
601
602 if (defined($opt{"LOG_FILE"})) {
603 open(LOG, ">>$opt{LOG_FILE}") or
604 dodie "failed to write to log";
605 $dolog = 1;
606 }
607
608 if (defined($redirect)) {
609 open (RD, ">$redirect") or
610 dodie "failed to write to redirect $redirect";
611 $dord = 1;
612 }
613
614 while (<CMD>) {
615 print LOG if ($dolog);
616 print RD if ($dord);
617 }
618
619 waitpid($pid, 0);
620 my $failed = $?;
621
622 close(CMD);
623 close(LOG) if ($dolog);
624 close(RD) if ($dord);
625
626 if ($failed) {
627 doprint "FAILED!\n";
628 } else {
629 doprint "SUCCESS\n";
630 }
631
632 return !$failed;
633}
634
635sub run_ssh {
636 my ($cmd) = @_;
637 my $cp_exec = $ssh_exec;
638
639 $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
640 return run_command "$cp_exec";
641}
642
643sub run_scp {
644 my ($src, $dst) = @_;
645 my $cp_scp = $scp_to_target;
646
647 $cp_scp =~ s/\$SRC_FILE/$src/g;
648 $cp_scp =~ s/\$DST_FILE/$dst/g;
649
650 return run_command "$cp_scp";
651}
652
653sub get_grub_index {
654
655 if ($reboot_type ne "grub") {
656 return;
657 }
658 return if (defined($grub_number));
659
660 doprint "Find grub menu ... ";
661 $grub_number = -1;
662
663 my $ssh_grub = $ssh_exec;
664 $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
665
666 open(IN, "$ssh_grub |")
667 or die "unable to get menu.lst";
668
669 while (<IN>) {
670 if (/^\s*title\s+$grub_menu\s*$/) {
671 $grub_number++;
672 last;
673 } elsif (/^\s*title\s/) {
674 $grub_number++;
675 }
676 }
677 close(IN);
678
679 die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
680 if ($grub_number < 0);
681 doprint "$grub_number\n";
682}
683
684sub wait_for_input
685{
686 my ($fp, $time) = @_;
687 my $rin;
688 my $ready;
689 my $line;
690 my $ch;
691
692 if (!defined($time)) {
693 $time = $timeout;
694 }
695
696 $rin = '';
697 vec($rin, fileno($fp), 1) = 1;
698 $ready = select($rin, undef, undef, $time);
699
700 $line = "";
701
702 # try to read one char at a time
703 while (sysread $fp, $ch, 1) {
704 $line .= $ch;
705 last if ($ch eq "\n");
706 }
707
708 if (!length($line)) {
709 return undef;
710 }
711
712 return $line;
713}
714
715sub reboot_to {
716 if ($reboot_type eq "grub") {
717 run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
718 return;
719 }
720
721 run_command "$reboot_script";
722}
723
724sub get_sha1 {
725 my ($commit) = @_;
726
727 doprint "git rev-list --max-count=1 $commit ... ";
728 my $sha1 = `git rev-list --max-count=1 $commit`;
729 my $ret = $?;
730
731 logit $sha1;
732
733 if ($ret) {
734 doprint "FAILED\n";
735 dodie "Failed to get git $commit";
736 }
737
738 print "SUCCESS\n";
739
740 chomp $sha1;
741
742 return $sha1;
743}
744
745sub monitor {
746 my $booted = 0;
747 my $bug = 0;
748 my $skip_call_trace = 0;
749 my $loops;
750
751 wait_for_monitor 5;
752
753 my $line;
754 my $full_line = "";
755
756 open(DMESG, "> $dmesg") or
757 die "unable to write to $dmesg";
758
759 reboot_to;
760
761 my $success_start;
762 my $failure_start;
763
764 for (;;) {
765
766 if ($booted) {
767 $line = wait_for_input($monitor_fp, $booted_timeout);
768 } else {
769 $line = wait_for_input($monitor_fp);
770 }
771
772 last if (!defined($line));
773
774 doprint $line;
775 print DMESG $line;
776
777 # we are not guaranteed to get a full line
778 $full_line .= $line;
779
780 if ($full_line =~ /$success_line/) {
781 $booted = 1;
782 $success_start = time;
783 }
784
785 if ($booted && defined($stop_after_success) &&
786 $stop_after_success >= 0) {
787 my $now = time;
788 if ($now - $success_start >= $stop_after_success) {
789 doprint "Test forced to stop after $stop_after_success seconds after success\n";
790 last;
791 }
792 }
793
794 if ($full_line =~ /\[ backtrace testing \]/) {
795 $skip_call_trace = 1;
796 }
797
798 if ($full_line =~ /call trace:/i) {
799 if (!$skip_call_trace) {
800 $bug = 1;
801 $failure_start = time;
802 }
803 }
804
805 if ($bug && defined($stop_after_failure) &&
806 $stop_after_failure >= 0) {
807 my $now = time;
808 if ($now - $failure_start >= $stop_after_failure) {
809 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
810 last;
811 }
812 }
813
814 if ($full_line =~ /\[ end of backtrace testing \]/) {
815 $skip_call_trace = 0;
816 }
817
818 if ($full_line =~ /Kernel panic -/) {
819 $bug = 1;
820 }
821
822 if ($line =~ /\n/) {
823 $full_line = "";
824 }
825 }
826
827 close(DMESG);
828
829 if ($bug) {
830 return 0 if ($in_bisect);
831 fail "failed - got a bug report" and return 0;
832 }
833
834 if (!$booted) {
835 return 0 if ($in_bisect);
836 fail "failed - never got a boot prompt." and return 0;
837 }
838
839 return 1;
840}
841
842sub install {
843
844 run_scp "$outputdir/$build_target", "$target_image" or
845 dodie "failed to copy image";
846
847 my $install_mods = 0;
848
849 # should we process modules?
850 $install_mods = 0;
851 open(IN, "$output_config") or dodie("Can't read config file");
852 while (<IN>) {
853 if (/CONFIG_MODULES(=y)?/) {
854 $install_mods = 1 if (defined($1));
855 last;
856 }
857 }
858 close(IN);
859
860 if (!$install_mods) {
861 doprint "No modules needed\n";
862 return;
863 }
864
865 run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
866 dodie "Failed to install modules";
867
868 my $modlib = "/lib/modules/$version";
869 my $modtar = "ktest-mods.tar.bz2";
870
871 run_ssh "rm -rf $modlib" or
872 dodie "failed to remove old mods: $modlib";
873
874 # would be nice if scp -r did not follow symbolic links
875 run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
876 dodie "making tarball";
877
878 run_scp "$tmpdir/$modtar", "/tmp" or
879 dodie "failed to copy modules";
880
881 unlink "$tmpdir/$modtar";
882
883 run_ssh "'(cd / && tar xf /tmp/$modtar)'" or
884 dodie "failed to tar modules";
885
886 run_ssh "rm -f /tmp/$modtar";
887
888 return if (!defined($post_install));
889
890 my $cp_post_install = $post_install;
891 $cp_post_install = s/\$KERNEL_VERSION/$version/g;
892 run_command "$cp_post_install" or
893 dodie "Failed to run post install";
894}
895
896sub check_buildlog {
897 my ($patch) = @_;
898
899 my @files = `git show $patch | diffstat -l`;
900
901 open(IN, "git show $patch |") or
902 dodie "failed to show $patch";
903 while (<IN>) {
904 if (m,^--- a/(.*),) {
905 chomp $1;
906 $files[$#files] = $1;
907 }
908 }
909 close(IN);
910
911 open(IN, $buildlog) or dodie "Can't open $buildlog";
912 while (<IN>) {
913 if (/^\s*(.*?):.*(warning|error)/) {
914 my $err = $1;
915 foreach my $file (@files) {
916 my $fullpath = "$builddir/$file";
917 if ($file eq $err || $fullpath eq $err) {
918 fail "$file built with warnings" and return 0;
919 }
920 }
921 }
922 }
923 close(IN);
924
925 return 1;
926}
927
928sub build {
929 my ($type) = @_;
930 my $defconfig = "";
931
932 unlink $buildlog;
933
934 if ($type =~ /^useconfig:(.*)/) {
935 run_command "cp $1 $output_config" or
936 dodie "could not copy $1 to .config";
937
938 $type = "oldconfig";
939 }
940
941 # old config can ask questions
942 if ($type eq "oldconfig") {
943 $type = "oldnoconfig";
944
945 # allow for empty configs
946 run_command "touch $output_config";
947
948 run_command "mv $output_config $outputdir/config_temp" or
949 dodie "moving .config";
950
951 if (!$noclean && !run_command "$make mrproper") {
952 dodie "make mrproper";
953 }
954
955 run_command "mv $outputdir/config_temp $output_config" or
956 dodie "moving config_temp";
957
958 } elsif (!$noclean) {
959 unlink "$output_config";
960 run_command "$make mrproper" or
961 dodie "make mrproper";
962 }
963
964 # add something to distinguish this build
965 open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
966 print OUT "$localversion\n";
967 close(OUT);
968
969 if (defined($minconfig)) {
970 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
971 }
972
973 run_command "$defconfig $make $type" or
974 dodie "failed make config";
975
976 $redirect = "$buildlog";
977 if (!run_command "$make $build_options") {
978 undef $redirect;
979 # bisect may need this to pass
980 return 0 if ($in_bisect);
981 fail "failed build" and return 0;
982 }
983 undef $redirect;
984
985 return 1;
986}
987
988sub halt {
989 if (!run_ssh "halt" or defined($power_off)) {
990 if (defined($poweroff_after_halt)) {
991 sleep $poweroff_after_halt;
992 run_command "$power_off";
993 }
994 } else {
995 # nope? the zap it!
996 run_command "$power_off";
997 }
998}
999
1000sub success {
1001 my ($i) = @_;
1002
1003 $successes++;
1004
1005 doprint "\n\n*******************************************\n";
1006 doprint "*******************************************\n";
1007 doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n";
1008 doprint "*******************************************\n";
1009 doprint "*******************************************\n";
1010
1011 if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1012 doprint "Reboot and wait $sleep_time seconds\n";
1013 reboot;
1014 start_monitor;
1015 wait_for_monitor $sleep_time;
1016 end_monitor;
1017 }
1018}
1019
1020sub get_version {
1021 # get the release name
1022 doprint "$make kernelrelease ... ";
1023 $version = `$make kernelrelease | tail -1`;
1024 chomp($version);
1025 doprint "$version\n";
1026}
1027
1028sub child_run_test {
1029 my $failed = 0;
1030
1031 # child should have no power
1032 $reboot_on_error = 0;
1033 $poweroff_on_error = 0;
1034 $die_on_failure = 1;
1035
1036 run_command $run_test or $failed = 1;
1037 exit $failed;
1038}
1039
1040my $child_done;
1041
1042sub child_finished {
1043 $child_done = 1;
1044}
1045
1046sub do_run_test {
1047 my $child_pid;
1048 my $child_exit;
1049 my $line;
1050 my $full_line;
1051 my $bug = 0;
1052
1053 wait_for_monitor 1;
1054
1055 doprint "run test $run_test\n";
1056
1057 $child_done = 0;
1058
1059 $SIG{CHLD} = qw(child_finished);
1060
1061 $child_pid = fork;
1062
1063 child_run_test if (!$child_pid);
1064
1065 $full_line = "";
1066
1067 do {
1068 $line = wait_for_input($monitor_fp, 1);
1069 if (defined($line)) {
1070
1071 # we are not guaranteed to get a full line
1072 $full_line .= $line;
1073
1074 if ($full_line =~ /call trace:/i) {
1075 $bug = 1;
1076 }
1077
1078 if ($full_line =~ /Kernel panic -/) {
1079 $bug = 1;
1080 }
1081
1082 if ($line =~ /\n/) {
1083 $full_line = "";
1084 }
1085 }
1086 } while (!$child_done && !$bug);
1087
1088 if ($bug) {
1089 doprint "Detected kernel crash!\n";
1090 # kill the child with extreme prejudice
1091 kill 9, $child_pid;
1092 }
1093
1094 waitpid $child_pid, 0;
1095 $child_exit = $?;
1096
1097 if ($bug || $child_exit) {
1098 return 0 if $in_bisect;
1099 fail "test failed" and return 0;
1100 }
1101 return 1;
1102}
1103
1104sub run_git_bisect {
1105 my ($command) = @_;
1106
1107 doprint "$command ... ";
1108
1109 my $output = `$command 2>&1`;
1110 my $ret = $?;
1111
1112 logit $output;
1113
1114 if ($ret) {
1115 doprint "FAILED\n";
1116 dodie "Failed to git bisect";
1117 }
1118
1119 doprint "SUCCESS\n";
1120 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1121 doprint "$1 [$2]\n";
1122 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1123 $bisect_bad = $1;
1124 doprint "Found bad commit... $1\n";
1125 return 0;
1126 } else {
1127 # we already logged it, just print it now.
1128 print $output;
1129 }
1130
1131 return 1;
1132}
1133
1134# returns 1 on success, 0 on failure
1135sub run_bisect_test {
1136 my ($type, $buildtype) = @_;
1137
1138 my $failed = 0;
1139 my $result;
1140 my $output;
1141 my $ret;
1142
1143 $in_bisect = 1;
1144
1145 build $buildtype or $failed = 1;
1146
1147 if ($type ne "build") {
1148 dodie "Failed on build" if $failed;
1149
1150 # Now boot the box
1151 get_grub_index;
1152 get_version;
1153 install;
1154
1155 start_monitor;
1156 monitor or $failed = 1;
1157
1158 if ($type ne "boot") {
1159 dodie "Failed on boot" if $failed;
1160
1161 do_run_test or $failed = 1;
1162 }
1163 end_monitor;
1164 }
1165
1166 if ($failed) {
1167 $result = 0;
1168
1169 # reboot the box to a good kernel
1170 if ($type ne "build") {
1171 doprint "Reboot and sleep $bisect_sleep_time seconds\n";
1172 reboot;
1173 start_monitor;
1174 wait_for_monitor $bisect_sleep_time;
1175 end_monitor;
1176 }
1177 } else {
1178 $result = 1;
1179 }
1180 $in_bisect = 0;
1181
1182 return $result;
1183}
1184
1185sub run_bisect {
1186 my ($type) = @_;
1187 my $buildtype = "oldconfig";
1188
1189 # We should have a minconfig to use?
1190 if (defined($minconfig)) {
1191 $buildtype = "useconfig:$minconfig";
1192 }
1193
1194 my $ret = run_bisect_test $type, $buildtype;
1195
1196
1197 # Are we looking for where it worked, not failed?
1198 if ($reverse_bisect) {
1199 $ret = !$ret;
1200 }
1201
1202 if ($ret) {
1203 return "good";
1204 } else {
1205 return "bad";
1206 }
1207}
1208
1209sub bisect {
1210 my ($i) = @_;
1211
1212 my $result;
1213
1214 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
1215 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
1216 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
1217
1218 my $good = $opt{"BISECT_GOOD[$i]"};
1219 my $bad = $opt{"BISECT_BAD[$i]"};
1220 my $type = $opt{"BISECT_TYPE[$i]"};
1221 my $start = $opt{"BISECT_START[$i]"};
1222 my $replay = $opt{"BISECT_REPLAY[$i]"};
1223
1224 # convert to true sha1's
1225 $good = get_sha1($good);
1226 $bad = get_sha1($bad);
1227
1228 if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1229 $opt{"BISECT_REVERSE[$i]"} == 1) {
1230 doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1231 $reverse_bisect = 1;
1232 } else {
1233 $reverse_bisect = 0;
1234 }
1235
1236 # Can't have a test without having a test to run
1237 if ($type eq "test" && !defined($run_test)) {
1238 $type = "boot";
1239 }
1240
1241 my $check = $opt{"BISECT_CHECK[$i]"};
1242 if (defined($check) && $check ne "0") {
1243
1244 # get current HEAD
1245 my $head = get_sha1("HEAD");
1246
1247 if ($check ne "good") {
1248 doprint "TESTING BISECT BAD [$bad]\n";
1249 run_command "git checkout $bad" or
1250 die "Failed to checkout $bad";
1251
1252 $result = run_bisect $type;
1253
1254 if ($result ne "bad") {
1255 fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1256 }
1257 }
1258
1259 if ($check ne "bad") {
1260 doprint "TESTING BISECT GOOD [$good]\n";
1261 run_command "git checkout $good" or
1262 die "Failed to checkout $good";
1263
1264 $result = run_bisect $type;
1265
1266 if ($result ne "good") {
1267 fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1268 }
1269 }
1270
1271 # checkout where we started
1272 run_command "git checkout $head" or
1273 die "Failed to checkout $head";
1274 }
1275
1276 run_command "git bisect start" or
1277 dodie "could not start bisect";
1278
1279 run_command "git bisect good $good" or
1280 dodie "could not set bisect good to $good";
1281
1282 run_git_bisect "git bisect bad $bad" or
1283 dodie "could not set bisect bad to $bad";
1284
1285 if (defined($replay)) {
1286 run_command "git bisect replay $replay" or
1287 dodie "failed to run replay";
1288 }
1289
1290 if (defined($start)) {
1291 run_command "git checkout $start" or
1292 dodie "failed to checkout $start";
1293 }
1294
1295 my $test;
1296 do {
1297 $result = run_bisect $type;
1298 $test = run_git_bisect "git bisect $result";
1299 } while ($test);
1300
1301 run_command "git bisect log" or
1302 dodie "could not capture git bisect log";
1303
1304 run_command "git bisect reset" or
1305 dodie "could not reset git bisect";
1306
1307 doprint "Bad commit was [$bisect_bad]\n";
1308
1309 success $i;
1310}
1311
1312my %config_ignore;
1313my %config_set;
1314
1315my %config_list;
1316my %null_config;
1317
1318my %dependency;
1319
1320sub process_config_ignore {
1321 my ($config) = @_;
1322
1323 open (IN, $config)
1324 or dodie "Failed to read $config";
1325
1326 while (<IN>) {
1327 if (/^(.*?(CONFIG\S*)(=.*| is not set))/) {
1328 $config_ignore{$2} = $1;
1329 }
1330 }
1331
1332 close(IN);
1333}
1334
1335sub read_current_config {
1336 my ($config_ref) = @_;
1337
1338 %{$config_ref} = ();
1339 undef %{$config_ref};
1340
1341 my @key = keys %{$config_ref};
1342 if ($#key >= 0) {
1343 print "did not delete!\n";
1344 exit;
1345 }
1346 open (IN, "$output_config");
1347
1348 while (<IN>) {
1349 if (/^(CONFIG\S+)=(.*)/) {
1350 ${$config_ref}{$1} = $2;
1351 }
1352 }
1353 close(IN);
1354}
1355
1356sub get_dependencies {
1357 my ($config) = @_;
1358
1359 my $arr = $dependency{$config};
1360 if (!defined($arr)) {
1361 return ();
1362 }
1363
1364 my @deps = @{$arr};
1365
1366 foreach my $dep (@{$arr}) {
1367 print "ADD DEP $dep\n";
1368 @deps = (@deps, get_dependencies $dep);
1369 }
1370
1371 return @deps;
1372}
1373
1374sub create_config {
1375 my @configs = @_;
1376
1377 open(OUT, ">$output_config") or dodie "Can not write to $output_config";
1378
1379 foreach my $config (@configs) {
1380 print OUT "$config_set{$config}\n";
1381 my @deps = get_dependencies $config;
1382 foreach my $dep (@deps) {
1383 print OUT "$config_set{$dep}\n";
1384 }
1385 }
1386
1387 foreach my $config (keys %config_ignore) {
1388 print OUT "$config_ignore{$config}\n";
1389 }
1390 close(OUT);
1391
1392# exit;
1393 run_command "$make oldnoconfig" or
1394 dodie "failed make config oldconfig";
1395
1396}
1397
1398sub compare_configs {
1399 my (%a, %b) = @_;
1400
1401 foreach my $item (keys %a) {
1402 if (!defined($b{$item})) {
1403 print "diff $item\n";
1404 return 1;
1405 }
1406 delete $b{$item};
1407 }
1408
1409 my @keys = keys %b;
1410 if ($#keys) {
1411 print "diff2 $keys[0]\n";
1412 }
1413 return -1 if ($#keys >= 0);
1414
1415 return 0;
1416}
1417
1418sub run_config_bisect_test {
1419 my ($type) = @_;
1420
1421 return run_bisect_test $type, "oldconfig";
1422}
1423
1424sub process_passed {
1425 my (%configs) = @_;
1426
1427 doprint "These configs had no failure: (Enabling them for further compiles)\n";
1428 # Passed! All these configs are part of a good compile.
1429 # Add them to the min options.
1430 foreach my $config (keys %configs) {
1431 if (defined($config_list{$config})) {
1432 doprint " removing $config\n";
1433 $config_ignore{$config} = $config_list{$config};
1434 delete $config_list{$config};
1435 }
1436 }
1437 doprint "config copied to $outputdir/config_good\n";
1438 run_command "cp -f $output_config $outputdir/config_good";
1439}
1440
1441sub process_failed {
1442 my ($config) = @_;
1443
1444 doprint "\n\n***************************************\n";
1445 doprint "Found bad config: $config\n";
1446 doprint "***************************************\n\n";
1447}
1448
1449sub run_config_bisect {
1450
1451 my @start_list = keys %config_list;
1452
1453 if ($#start_list < 0) {
1454 doprint "No more configs to test!!!\n";
1455 return -1;
1456 }
1457
1458 doprint "***** RUN TEST ***\n";
1459 my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
1460 my $ret;
1461 my %current_config;
1462
1463 my $count = $#start_list + 1;
1464 doprint " $count configs to test\n";
1465
1466 my $half = int($#start_list / 2);
1467
1468 do {
1469 my @tophalf = @start_list[0 .. $half];
1470
1471 create_config @tophalf;
1472 read_current_config \%current_config;
1473
1474 $count = $#tophalf + 1;
1475 doprint "Testing $count configs\n";
1476 my $found = 0;
1477 # make sure we test something
1478 foreach my $config (@tophalf) {
1479 if (defined($current_config{$config})) {
1480 logit " $config\n";
1481 $found = 1;
1482 }
1483 }
1484 if (!$found) {
1485 # try the other half
1486 doprint "Top half produced no set configs, trying bottom half\n";
1487 @tophalf = @start_list[$half .. $#start_list];
1488 create_config @tophalf;
1489 read_current_config \%current_config;
1490 foreach my $config (@tophalf) {
1491 if (defined($current_config{$config})) {
1492 logit " $config\n";
1493 $found = 1;
1494 }
1495 }
1496 if (!$found) {
1497 doprint "Failed: Can't make new config with current configs\n";
1498 foreach my $config (@start_list) {
1499 doprint " CONFIG: $config\n";
1500 }
1501 return -1;
1502 }
1503 $count = $#tophalf + 1;
1504 doprint "Testing $count configs\n";
1505 }
1506
1507 $ret = run_config_bisect_test $type;
1508
1509 if ($ret) {
1510 process_passed %current_config;
1511 return 0;
1512 }
1513
1514 doprint "This config had a failure.\n";
1515 doprint "Removing these configs that were not set in this config:\n";
1516 doprint "config copied to $outputdir/config_bad\n";
1517 run_command "cp -f $output_config $outputdir/config_bad";
1518
1519 # A config exists in this group that was bad.
1520 foreach my $config (keys %config_list) {
1521 if (!defined($current_config{$config})) {
1522 doprint " removing $config\n";
1523 delete $config_list{$config};
1524 }
1525 }
1526
1527 @start_list = @tophalf;
1528
1529 if ($#start_list == 0) {
1530 process_failed $start_list[0];
1531 return 1;
1532 }
1533
1534 # remove half the configs we are looking at and see if
1535 # they are good.
1536 $half = int($#start_list / 2);
1537 } while ($half > 0);
1538
1539 # we found a single config, try it again
1540 my @tophalf = @start_list[0 .. 0];
1541
1542 $ret = run_config_bisect_test $type;
1543 if ($ret) {
1544 process_passed %current_config;
1545 return 0;
1546 }
1547
1548 process_failed $start_list[0];
1549 return 1;
1550}
1551
1552sub config_bisect {
1553 my ($i) = @_;
1554
1555 my $start_config = $opt{"CONFIG_BISECT[$i]"};
1556
1557 my $tmpconfig = "$tmpdir/use_config";
1558
1559 # Make the file with the bad config and the min config
1560 if (defined($minconfig)) {
1561 # read the min config for things to ignore
1562 run_command "cp $minconfig $tmpconfig" or
1563 dodie "failed to copy $minconfig to $tmpconfig";
1564 } else {
1565 unlink $tmpconfig;
1566 }
1567
1568 # Add other configs
1569 if (defined($addconfig)) {
1570 run_command "cat $addconfig >> $tmpconfig" or
1571 dodie "failed to append $addconfig";
1572 }
1573
1574 my $defconfig = "";
1575 if (-f $tmpconfig) {
1576 $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig";
1577 process_config_ignore $tmpconfig;
1578 }
1579
1580 # now process the start config
1581 run_command "cp $start_config $output_config" or
1582 dodie "failed to copy $start_config to $output_config";
1583
1584 # read directly what we want to check
1585 my %config_check;
1586 open (IN, $output_config)
1587 or dodie "faied to open $output_config";
1588
1589 while (<IN>) {
1590 if (/^((CONFIG\S*)=.*)/) {
1591 $config_check{$2} = $1;
1592 }
1593 }
1594 close(IN);
1595
1596 # Now run oldconfig with the minconfig (and addconfigs)
1597 run_command "$defconfig $make oldnoconfig" or
1598 dodie "failed make config oldconfig";
1599
1600 # check to see what we lost (or gained)
1601 open (IN, $output_config)
1602 or dodie "Failed to read $start_config";
1603
1604 my %removed_configs;
1605 my %added_configs;
1606
1607 while (<IN>) {
1608 if (/^((CONFIG\S*)=.*)/) {
1609 # save off all options
1610 $config_set{$2} = $1;
1611 if (defined($config_check{$2})) {
1612 if (defined($config_ignore{$2})) {
1613 $removed_configs{$2} = $1;
1614 } else {
1615 $config_list{$2} = $1;
1616 }
1617 } elsif (!defined($config_ignore{$2})) {
1618 $added_configs{$2} = $1;
1619 $config_list{$2} = $1;
1620 }
1621 }
1622 }
1623 close(IN);
1624
1625 my @confs = keys %removed_configs;
1626 if ($#confs >= 0) {
1627 doprint "Configs overridden by default configs and removed from check:\n";
1628 foreach my $config (@confs) {
1629 doprint " $config\n";
1630 }
1631 }
1632 @confs = keys %added_configs;
1633 if ($#confs >= 0) {
1634 doprint "Configs appearing in make oldconfig and added:\n";
1635 foreach my $config (@confs) {
1636 doprint " $config\n";
1637 }
1638 }
1639
1640 my %config_test;
1641 my $once = 0;
1642
1643 # Sometimes kconfig does weird things. We must make sure
1644 # that the config we autocreate has everything we need
1645 # to test, otherwise we may miss testing configs, or
1646 # may not be able to create a new config.
1647 # Here we create a config with everything set.
1648 create_config (keys %config_list);
1649 read_current_config \%config_test;
1650 foreach my $config (keys %config_list) {
1651 if (!defined($config_test{$config})) {
1652 if (!$once) {
1653 $once = 1;
1654 doprint "Configs not produced by kconfig (will not be checked):\n";
1655 }
1656 doprint " $config\n";
1657 delete $config_list{$config};
1658 }
1659 }
1660 my $ret;
1661 do {
1662 $ret = run_config_bisect;
1663 } while (!$ret);
1664
1665 return $ret if ($ret < 0);
1666
1667 success $i;
1668}
1669
1670sub patchcheck {
1671 my ($i) = @_;
1672
1673 die "PATCHCHECK_START[$i] not defined\n"
1674 if (!defined($opt{"PATCHCHECK_START[$i]"}));
1675 die "PATCHCHECK_TYPE[$i] not defined\n"
1676 if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
1677
1678 my $start = $opt{"PATCHCHECK_START[$i]"};
1679
1680 my $end = "HEAD";
1681 if (defined($opt{"PATCHCHECK_END[$i]"})) {
1682 $end = $opt{"PATCHCHECK_END[$i]"};
1683 }
1684
1685 # Get the true sha1's since we can use things like HEAD~3
1686 $start = get_sha1($start);
1687 $end = get_sha1($end);
1688
1689 my $type = $opt{"PATCHCHECK_TYPE[$i]"};
1690
1691 # Can't have a test without having a test to run
1692 if ($type eq "test" && !defined($run_test)) {
1693 $type = "boot";
1694 }
1695
1696 open (IN, "git log --pretty=oneline $end|") or
1697 dodie "could not get git list";
1698
1699 my @list;
1700
1701 while (<IN>) {
1702 chomp;
1703 $list[$#list+1] = $_;
1704 last if (/^$start/);
1705 }
1706 close(IN);
1707
1708 if ($list[$#list] !~ /^$start/) {
1709 fail "SHA1 $start not found";
1710 }
1711
1712 # go backwards in the list
1713 @list = reverse @list;
1714
1715 my $save_clean = $noclean;
1716
1717 $in_patchcheck = 1;
1718 foreach my $item (@list) {
1719 my $sha1 = $item;
1720 $sha1 =~ s/^([[:xdigit:]]+).*/$1/;
1721
1722 doprint "\nProcessing commit $item\n\n";
1723
1724 run_command "git checkout $sha1" or
1725 die "Failed to checkout $sha1";
1726
1727 # only clean on the first and last patch
1728 if ($item eq $list[0] ||
1729 $item eq $list[$#list]) {
1730 $noclean = $save_clean;
1731 } else {
1732 $noclean = 1;
1733 }
1734
1735 if (defined($minconfig)) {
1736 build "useconfig:$minconfig" or return 0;
1737 } else {
1738 # ?? no config to use?
1739 build "oldconfig" or return 0;
1740 }
1741
1742 check_buildlog $sha1 or return 0;
1743
1744 next if ($type eq "build");
1745
1746 get_grub_index;
1747 get_version;
1748 install;
1749
1750 my $failed = 0;
1751
1752 start_monitor;
1753 monitor or $failed = 1;
1754
1755 if (!$failed && $type ne "boot"){
1756 do_run_test or $failed = 1;
1757 }
1758 end_monitor;
1759 return 0 if ($failed);
1760
1761 }
1762 $in_patchcheck = 0;
1763 success $i;
1764
1765 return 1;
1766}
1767
1768$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n";
1769
1770if ($#ARGV == 0) {
1771 $ktest_config = $ARGV[0];
1772 if (! -f $ktest_config) {
1773 print "$ktest_config does not exist.\n";
1774 my $ans;
1775 for (;;) {
1776 print "Create it? [Y/n] ";
1777 $ans = <STDIN>;
1778 chomp $ans;
1779 if ($ans =~ /^\s*$/) {
1780 $ans = "y";
1781 }
1782 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
1783 print "Please answer either 'y' or 'n'.\n";
1784 }
1785 if ($ans !~ /^y$/i) {
1786 exit 0;
1787 }
1788 }
1789} else {
1790 $ktest_config = "ktest.conf";
1791}
1792
1793if (! -f $ktest_config) {
1794 open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
1795 print OUT << "EOF"
1796# Generated by ktest.pl
1797#
1798# Define each test with TEST_START
1799# The config options below it will override the defaults
1800TEST_START
1801
1802DEFAULTS
1803EOF
1804;
1805 close(OUT);
1806}
1807read_config $ktest_config;
1808
1809# Append any configs entered in manually to the config file.
1810my @new_configs = keys %entered_configs;
1811if ($#new_configs >= 0) {
1812 print "\nAppending entered in configs to $ktest_config\n";
1813 open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
1814 foreach my $config (@new_configs) {
1815 print OUT "$config = $entered_configs{$config}\n";
1816 $opt{$config} = $entered_configs{$config};
1817 }
1818}
1819
1820if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
1821 unlink $opt{"LOG_FILE"};
1822}
1823
1824doprint "\n\nSTARTING AUTOMATED TESTS\n\n";
1825
1826for (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
1827
1828 if (!$i) {
1829 doprint "DEFAULT OPTIONS:\n";
1830 } else {
1831 doprint "\nTEST $i OPTIONS";
1832 if (defined($repeat_tests{$i})) {
1833 $repeat = $repeat_tests{$i};
1834 doprint " ITERATE $repeat";
1835 }
1836 doprint "\n";
1837 }
1838
1839 foreach my $option (sort keys %opt) {
1840
1841 if ($option =~ /\[(\d+)\]$/) {
1842 next if ($i != $1);
1843 } else {
1844 next if ($i);
1845 }
1846
1847 doprint "$option = $opt{$option}\n";
1848 }
1849}
1850
1851sub set_test_option {
1852 my ($name, $i) = @_;
1853
1854 my $option = "$name\[$i\]";
1855
1856 if (defined($opt{$option})) {
1857 return $opt{$option};
1858 }
1859
1860 foreach my $test (keys %repeat_tests) {
1861 if ($i >= $test &&
1862 $i < $test + $repeat_tests{$test}) {
1863 $option = "$name\[$test\]";
1864 if (defined($opt{$option})) {
1865 return $opt{$option};
1866 }
1867 }
1868 }
1869
1870 if (defined($opt{$name})) {
1871 return $opt{$name};
1872 }
1873
1874 return undef;
1875}
1876
1877# First we need to do is the builds
1878for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
1879
1880 $iteration = $i;
1881
1882 my $makecmd = set_test_option("MAKE_CMD", $i);
1883
1884 $machine = set_test_option("MACHINE", $i);
1885 $ssh_user = set_test_option("SSH_USER", $i);
1886 $tmpdir = set_test_option("TMP_DIR", $i);
1887 $outputdir = set_test_option("OUTPUT_DIR", $i);
1888 $builddir = set_test_option("BUILD_DIR", $i);
1889 $test_type = set_test_option("TEST_TYPE", $i);
1890 $build_type = set_test_option("BUILD_TYPE", $i);
1891 $build_options = set_test_option("BUILD_OPTIONS", $i);
1892 $power_cycle = set_test_option("POWER_CYCLE", $i);
1893 $reboot = set_test_option("REBOOT", $i);
1894 $noclean = set_test_option("BUILD_NOCLEAN", $i);
1895 $minconfig = set_test_option("MIN_CONFIG", $i);
1896 $run_test = set_test_option("TEST", $i);
1897 $addconfig = set_test_option("ADD_CONFIG", $i);
1898 $reboot_type = set_test_option("REBOOT_TYPE", $i);
1899 $grub_menu = set_test_option("GRUB_MENU", $i);
1900 $post_install = set_test_option("POST_INSTALL", $i);
1901 $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
1902 $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
1903 $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
1904 $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
1905 $power_off = set_test_option("POWER_OFF", $i);
1906 $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
1907 $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
1908 $sleep_time = set_test_option("SLEEP_TIME", $i);
1909 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
1910 $store_failures = set_test_option("STORE_FAILURES", $i);
1911 $timeout = set_test_option("TIMEOUT", $i);
1912 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
1913 $console = set_test_option("CONSOLE", $i);
1914 $success_line = set_test_option("SUCCESS_LINE", $i);
1915 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
1916 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
1917 $build_target = set_test_option("BUILD_TARGET", $i);
1918 $ssh_exec = set_test_option("SSH_EXEC", $i);
1919 $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
1920 $target_image = set_test_option("TARGET_IMAGE", $i);
1921 $localversion = set_test_option("LOCALVERSION", $i);
1922
1923 chdir $builddir || die "can't change directory to $builddir";
1924
1925 if (!-d $tmpdir) {
1926 mkpath($tmpdir) or
1927 die "can't create $tmpdir";
1928 }
1929
1930 $ENV{"SSH_USER"} = $ssh_user;
1931 $ENV{"MACHINE"} = $machine;
1932
1933 $target = "$ssh_user\@$machine";
1934
1935 $buildlog = "$tmpdir/buildlog-$machine";
1936 $dmesg = "$tmpdir/dmesg-$machine";
1937 $make = "$makecmd O=$outputdir";
1938 $output_config = "$outputdir/.config";
1939
1940 if ($reboot_type eq "grub") {
1941 dodie "GRUB_MENU not defined" if (!defined($grub_menu));
1942 } elsif (!defined($reboot_script)) {
1943 dodie "REBOOT_SCRIPT not defined"
1944 }
1945
1946 my $run_type = $build_type;
1947 if ($test_type eq "patchcheck") {
1948 $run_type = $opt{"PATCHCHECK_TYPE[$i]"};
1949 } elsif ($test_type eq "bisect") {
1950 $run_type = $opt{"BISECT_TYPE[$i]"};
1951 } elsif ($test_type eq "config_bisect") {
1952 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
1953 }
1954
1955 # mistake in config file?
1956 if (!defined($run_type)) {
1957 $run_type = "ERROR";
1958 }
1959
1960 doprint "\n\n";
1961 doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
1962
1963 unlink $dmesg;
1964 unlink $buildlog;
1965
1966 if (!defined($minconfig)) {
1967 $minconfig = $addconfig;
1968
1969 } elsif (defined($addconfig)) {
1970 run_command "cat $addconfig $minconfig > $tmpdir/add_config" or
1971 dodie "Failed to create temp config";
1972 $minconfig = "$tmpdir/add_config";
1973 }
1974
1975 my $checkout = $opt{"CHECKOUT[$i]"};
1976 if (defined($checkout)) {
1977 run_command "git checkout $checkout" or
1978 die "failed to checkout $checkout";
1979 }
1980
1981 if ($test_type eq "bisect") {
1982 bisect $i;
1983 next;
1984 } elsif ($test_type eq "config_bisect") {
1985 config_bisect $i;
1986 next;
1987 } elsif ($test_type eq "patchcheck") {
1988 patchcheck $i;
1989 next;
1990 }
1991
1992 if ($build_type ne "nobuild") {
1993 build $build_type or next;
1994 }
1995
1996 if ($test_type ne "build") {
1997 get_grub_index;
1998 get_version;
1999 install;
2000
2001 my $failed = 0;
2002 start_monitor;
2003 monitor or $failed = 1;;
2004
2005 if (!$failed && $test_type ne "boot" && defined($run_test)) {
2006 do_run_test or $failed = 1;
2007 }
2008 end_monitor;
2009 next if ($failed);
2010 }
2011
2012 success $i;
2013}
2014
2015if ($opt{"POWEROFF_ON_SUCCESS"}) {
2016 halt;
2017} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
2018 reboot;
2019}
2020
2021doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n";
2022
2023exit 0;
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
new file mode 100644
index 000000000000..3408c594b2de
--- /dev/null
+++ b/tools/testing/ktest/sample.conf
@@ -0,0 +1,622 @@
1#
2# Config file for ktest.pl
3#
4# Note, all paths must be absolute
5#
6
7# Options set in the beginning of the file are considered to be
8# default options. These options can be overriden by test specific
9# options, with the following exceptions:
10#
11# LOG_FILE
12# CLEAR_LOG
13# POWEROFF_ON_SUCCESS
14# REBOOT_ON_SUCCESS
15#
16# Test specific options are set after the label:
17#
18# TEST_START
19#
20# The options after a TEST_START label are specific to that test.
21# Each TEST_START label will set up a new test. If you want to
22# perform a test more than once, you can add the ITERATE label
23# to it followed by the number of times you want that test
24# to iterate. If the ITERATE is left off, the test will only
25# be performed once.
26#
27# TEST_START ITERATE 10
28#
29# You can skip a test by adding SKIP (before or after the ITERATE
30# and number)
31#
32# TEST_START SKIP
33#
34# TEST_START SKIP ITERATE 10
35#
36# TEST_START ITERATE 10 SKIP
37#
38# The SKIP label causes the options and the test itself to be ignored.
39# This is useful to set up several different tests in one config file, and
40# only enabling the ones you want to use for a current test run.
41#
42# You can add default options anywhere in the file as well
43# with the DEFAULTS tag. This allows you to have default options
44# after the test options to keep the test options at the top
45# of the file. You can even place the DEFAULTS tag between
46# test cases (but not in the middle of a single test case)
47#
48# TEST_START
49# MIN_CONFIG = /home/test/config-test1
50#
51# DEFAULTS
52# MIN_CONFIG = /home/test/config-default
53#
54# TEST_START ITERATE 10
55#
56# The above will run the first test with MIN_CONFIG set to
57# /home/test/config-test-1. Then 10 tests will be executed
58# with MIN_CONFIG with /home/test/config-default.
59#
60# You can also disable defaults with the SKIP option
61#
62# DEFAULTS SKIP
63# MIN_CONFIG = /home/test/config-use-sometimes
64#
65# DEFAULTS
66# MIN_CONFIG = /home/test/config-most-times
67#
68# The above will ignore the first MIN_CONFIG. If you want to
69# use the first MIN_CONFIG, remove the SKIP from the first
70# DEFAULTS tag and add it to the second. Be careful, options
71# may only be declared once per test or default. If you have
72# the same option name under the same test or as default
73# ktest will fail to execute, and no tests will run.
74#
75
76
77#### Mandatory Default Options ####
78
79# These options must be in the default section, although most
80# may be overridden by test options.
81
82# The machine hostname that you will test
83#MACHINE = target
84
85# The box is expected to have ssh on normal bootup, provide the user
86# (most likely root, since you need privileged operations)
87#SSH_USER = root
88
89# The directory that contains the Linux source code
90#BUILD_DIR = /home/test/linux.git
91
92# The directory that the objects will be built
93# (can not be same as BUILD_DIR)
94#OUTPUT_DIR = /home/test/build/target
95
96# The location of the compiled file to copy to the target
97# (relative to OUTPUT_DIR)
98#BUILD_TARGET = arch/x86/boot/bzImage
99
100# The place to put your image on the test machine
101#TARGET_IMAGE = /boot/vmlinuz-test
102
103# A script or command to reboot the box
104#
105# Here is a digital loggers power switch example
106#POWER_CYCLE = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin@power/outlet?5=CCL'
107#
108# Here is an example to reboot a virtual box on the current host
109# with the name "Guest".
110#POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
111
112# The script or command that reads the console
113#
114# If you use ttywatch server, something like the following would work.
115#CONSOLE = nc -d localhost 3001
116#
117# For a virtual machine with guest name "Guest".
118#CONSOLE = virsh console Guest
119
120# Required version ending to differentiate the test
121# from other linux builds on the system.
122#LOCALVERSION = -test
123
124# The grub title name for the test kernel to boot
125# (Only mandatory if REBOOT_TYPE = grub)
126#
127# Note, ktest.pl will not update the grub menu.lst, you need to
128# manually add an option for the test. ktest.pl will search
129# the grub menu.lst for this option to find what kernel to
130# reboot into.
131#
132# For example, if in the /boot/grub/menu.lst the test kernel title has:
133# title Test Kernel
134# kernel vmlinuz-test
135#GRUB_MENU = Test Kernel
136
137# A script to reboot the target into the test kernel
138# (Only mandatory if REBOOT_TYPE = script)
139#REBOOT_SCRIPT =
140
141#### Optional Config Options (all have defaults) ####
142
143# Start a test setup. If you leave this off, all options
144# will be default and the test will run once.
145# This is a label and not really an option (it takes no value).
146# You can append ITERATE and a number after it to iterate the
147# test a number of times, or SKIP to ignore this test.
148#
149#TEST_START
150#TEST_START ITERATE 5
151#TEST_START SKIP
152
153# Have the following options as default again. Used after tests
154# have already been defined by TEST_START. Optionally, you can
155# just define all default options before the first TEST_START
156# and you do not need this option.
157#
158# This is a label and not really an option (it takes no value).
159# You can append SKIP to this label and the options within this
160# section will be ignored.
161#
162# DEFAULTS
163# DEFAULTS SKIP
164
165# The default test type (default test)
166# The test types may be:
167# build - only build the kernel, do nothing else
168# boot - build and boot the kernel
169# test - build, boot and if TEST is set, run the test script
170# (If TEST is not set, it defaults back to boot)
171# bisect - Perform a bisect on the kernel (see BISECT_TYPE below)
172# patchcheck - Do a test on a series of commits in git (see PATCHCHECK below)
173#TEST_TYPE = test
174
175# Test to run if there is a successful boot and TEST_TYPE is test.
176# Must exit with 0 on success and non zero on error
177# default (undefined)
178#TEST = ssh user@machine /root/run_test
179
180# The build type is any make config type or special command
181# (default randconfig)
182# nobuild - skip the clean and build step
183# useconfig:/path/to/config - use the given config and run
184# oldconfig on it.
185# This option is ignored if TEST_TYPE is patchcheck or bisect
186#BUILD_TYPE = randconfig
187
188# The make command (default make)
189# If you are building a 32bit x86 on a 64 bit host
190#MAKE_CMD = CC=i386-gcc AS=i386-as make ARCH=i386
191
192# Any build options for the make of the kernel (not for other makes, like configs)
193# (default "")
194#BUILD_OPTIONS = -j20
195
196# If you need an initrd, you can add a script or code here to install
197# it. The environment variable KERNEL_VERSION will be set to the
198# kernel version that is used. Remember to add the initrd line
199# to your grub menu.lst file.
200#
201# Here's a couple of examples to use:
202#POST_INSTALL = ssh user@target /sbin/mkinitrd --allow-missing -f /boot/initramfs-test.img $KERNEL_VERSION
203#
204# or on some systems:
205#POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
206
207# Way to reboot the box to the test kernel.
208# Only valid options so far are "grub" and "script"
209# (default grub)
210# If you specify grub, it will assume grub version 1
211# and will search in /boot/grub/menu.lst for the title $GRUB_MENU
212# and select that target to reboot to the kernel. If this is not
213# your setup, then specify "script" and have a command or script
214# specified in REBOOT_SCRIPT to boot to the target.
215#
216# The entry in /boot/grub/menu.lst must be entered in manually.
217# The test will not modify that file.
218#REBOOT_TYPE = grub
219
220# The min config that is needed to build for the machine
221# A nice way to create this is with the following:
222#
223# $ ssh target
224# $ lsmod > mymods
225# $ scp mymods host:/tmp
226# $ exit
227# $ cd linux.git
228# $ rm .config
229# $ make LSMOD=mymods localyesconfig
230# $ grep '^CONFIG' .config > /home/test/config-min
231#
232# If you want even less configs:
233#
234# log in directly to target (do not ssh)
235#
236# $ su
237# # lsmod | cut -d' ' -f1 | xargs rmmod
238#
239# repeat the above several times
240#
241# # lsmod > mymods
242# # reboot
243#
244# May need to reboot to get your network back to copy the mymods
245# to the host, and then remove the previous .config and run the
246# localyesconfig again. The CONFIG_MIN generated like this will
247# not guarantee network activity to the box so the TEST_TYPE of
248# test may fail.
249#
250# You might also want to set:
251# CONFIG_CMDLINE="<your options here>"
252# randconfig may set the above and override your real command
253# line options.
254# (default undefined)
255#MIN_CONFIG = /home/test/config-min
256
257# Sometimes there's options that just break the boot and
258# you do not care about. Here are a few:
259# # CONFIG_STAGING is not set
260# Staging drivers are horrible, and can break the build.
261# # CONFIG_SCSI_DEBUG is not set
262# SCSI_DEBUG may change your root partition
263# # CONFIG_KGDB_SERIAL_CONSOLE is not set
264# KGDB may cause oops waiting for a connection that's not there.
265# This option points to the file containing config options that will be prepended
266# to the MIN_CONFIG (or be the MIN_CONFIG if it is not set)
267#
268# Note, config options in MIN_CONFIG will override these options.
269#
270# (default undefined)
271#ADD_CONFIG = /home/test/config-broken
272
273# The location on the host where to write temp files
274# (default /tmp/ktest)
275#TMP_DIR = /tmp/ktest
276
277# Optional log file to write the status (recommended)
278# Note, this is a DEFAULT section only option.
279# (default undefined)
280#LOG_FILE = /home/test/logfiles/target.log
281
282# Remove old logfile if it exists before starting all tests.
283# Note, this is a DEFAULT section only option.
284# (default 0)
285#CLEAR_LOG = 0
286
287# Line to define a successful boot up in console output.
288# This is what the line contains, not the entire line. If you need
289# the entire line to match, then use regural expression syntax like:
290# (do not add any quotes around it)
291#
292# SUCCESS_LINE = ^MyBox Login:$
293#
294# (default "login:")
295#SUCCESS_LINE = login:
296
297# In case the console constantly fills the screen, having
298# a specified time to stop the test after success is recommended.
299# (in seconds)
300# (default 10)
301#STOP_AFTER_SUCCESS = 10
302
303# In case the console constantly fills the screen, having
304# a specified time to stop the test after failure is recommended.
305# (in seconds)
306# (default 60)
307#STOP_AFTER_FAILURE = 60
308
309# Stop testing if a build fails. If set, the script will end if
310# a failure is detected, otherwise it will save off the .config,
311# dmesg and bootlog in a directory called
312# MACHINE-TEST_TYPE_BUILD_TYPE-fail-yyyymmddhhmmss
313# if the STORE_FAILURES directory is set.
314# (default 1)
315# Note, even if this is set to zero, there are some errors that still
316# stop the tests.
317#DIE_ON_FAILURE = 1
318
319# Directory to store failure directories on failure. If this is not
320# set, DIE_ON_FAILURE=0 will not save off the .config, dmesg and
321# bootlog. This option is ignored if DIE_ON_FAILURE is not set.
322# (default undefined)
323#STORE_FAILURES = /home/test/failures
324
325# Build without doing a make mrproper, or removing .config
326# (default 0)
327#BUILD_NOCLEAN = 0
328
329# As the test reads the console, after it hits the SUCCESS_LINE
330# the time it waits for the monitor to settle down between reads
331# can usually be lowered.
332# (in seconds) (default 1)
333#BOOTED_TIMEOUT = 1
334
335# The timeout in seconds when we consider the box hung after
336# the console stop producing output. Be sure to leave enough
337# time here to get pass a reboot. Some machines may not produce
338# any console output for a long time during a reboot. You do
339# not want the test to fail just because the system was in
340# the process of rebooting to the test kernel.
341# (default 120)
342#TIMEOUT = 120
343
344# In between tests, a reboot of the box may occur, and this
345# is the time to wait for the console after it stops producing
346# output. Some machines may not produce a large lag on reboot
347# so this should accommodate it.
348# The difference between this and TIMEOUT, is that TIMEOUT happens
349# when rebooting to the test kernel. This sleep time happens
350# after a test has completed and we are about to start running
351# another test. If a reboot to the reliable kernel happens,
352# we wait SLEEP_TIME for the console to stop producing output
353# before starting the next test.
354# (default 60)
355#SLEEP_TIME = 60
356
357# The time in between bisects to sleep (in seconds)
358# (default 60)
359#BISECT_SLEEP_TIME = 60
360
361# Reboot the target box on error (default 0)
362#REBOOT_ON_ERROR = 0
363
364# Power off the target on error (ignored if REBOOT_ON_ERROR is set)
365# Note, this is a DEFAULT section only option.
366# (default 0)
367#POWEROFF_ON_ERROR = 0
368
369# Power off the target after all tests have completed successfully
370# Note, this is a DEFAULT section only option.
371# (default 0)
372#POWEROFF_ON_SUCCESS = 0
373
374# Reboot the target after all test completed successfully (default 1)
375# (ignored if POWEROFF_ON_SUCCESS is set)
376#REBOOT_ON_SUCCESS = 1
377
378# In case there are isses with rebooting, you can specify this
379# to always powercycle after this amount of time after calling
380# reboot.
381# Note, POWERCYCLE_AFTER_REBOOT = 0 does NOT disable it. It just
382# makes it powercycle immediately after rebooting. Do not define
383# it if you do not want it.
384# (default undefined)
385#POWERCYCLE_AFTER_REBOOT = 5
386
387# In case there's isses with halting, you can specify this
388# to always poweroff after this amount of time after calling
389# halt.
390# Note, POWEROFF_AFTER_HALT = 0 does NOT disable it. It just
391# makes it poweroff immediately after halting. Do not define
392# it if you do not want it.
393# (default undefined)
394#POWEROFF_AFTER_HALT = 20
395
396# A script or command to power off the box (default undefined)
397# Needed for POWEROFF_ON_ERROR and SUCCESS
398#
399# Example for digital loggers power switch:
400#POWER_OFF = wget --no-proxy -O /dev/null -q --auth-no-challenge 'http://admin:admin@power/outlet?5=OFF'
401#
402# Example for a virtual guest call "Guest".
403#POWER_OFF = virsh destroy Guest
404
405# The way to execute a command on the target
406# (default ssh $SSH_USER@$MACHINE $SSH_COMMAND";)
407# The variables SSH_USER, MACHINE and SSH_COMMAND are defined
408#SSH_EXEC = ssh $SSH_USER@$MACHINE $SSH_COMMAND";
409
410# The way to copy a file to the target
411# (default scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE)
412# The variables SSH_USER, MACHINE, SRC_FILE and DST_FILE are defined.
413#SCP_TO_TARGET = scp $SRC_FILE $SSH_USER@$MACHINE:$DST_FILE
414
415# The nice way to reboot the target
416# (default ssh $SSH_USER@$MACHINE reboot)
417# The variables SSH_USER and MACHINE are defined.
418#REBOOT = ssh $SSH_USER@$MACHINE reboot
419
420#### Per test run options ####
421# The following options are only allowed in TEST_START sections.
422# They are ignored in the DEFAULTS sections.
423#
424# All of these are optional and undefined by default, although
425# some of these options are required for TEST_TYPE of patchcheck
426# and bisect.
427#
428#
429# CHECKOUT = branch
430#
431# If the BUILD_DIR is a git repository, then you can set this option
432# to checkout the given branch before running the TEST. If you
433# specify this for the first run, that branch will be used for
434# all preceding tests until a new CHECKOUT is set.
435#
436#
437#
438# For TEST_TYPE = patchcheck
439#
440# This expects the BUILD_DIR to be a git repository, and
441# will checkout the PATCHCHECK_START commit.
442#
443# The option BUILD_TYPE will be ignored.
444#
445# The MIN_CONFIG will be used for all builds of the patchcheck. The build type
446# used for patchcheck is oldconfig.
447#
448# PATCHCHECK_START is required and is the first patch to
449# test (the SHA1 of the commit). You may also specify anything
450# that git checkout allows (branch name, tage, HEAD~3).
451#
452# PATCHCHECK_END is the last patch to check (default HEAD)
453#
454# PATCHCHECK_TYPE is required and is the type of test to run:
455# build, boot, test.
456#
457# Note, the build test will look for warnings, if a warning occurred
458# in a file that a commit touches, the build will fail.
459#
460# If BUILD_NOCLEAN is set, then make mrproper will not be run on
461# any of the builds, just like all other TEST_TYPE tests. But
462# what makes patchcheck different from the other tests, is if
463# BUILD_NOCLEAN is not set, only the first and last patch run
464# make mrproper. This helps speed up the test.
465#
466# Example:
467# TEST_START
468# TEST_TYPE = patchcheck
469# CHECKOUT = mybranch
470# PATCHCHECK_TYPE = boot
471# PATCHCHECK_START = 747e94ae3d1b4c9bf5380e569f614eb9040b79e7
472# PATCHCHECK_END = HEAD~2
473#
474#
475#
476# For TEST_TYPE = bisect
477#
478# You can specify a git bisect if the BUILD_DIR is a git repository.
479# The MIN_CONFIG will be used for all builds of the bisect. The build type
480# used for bisecting is oldconfig.
481#
482# The option BUILD_TYPE will be ignored.
483#
484# BISECT_TYPE is the type of test to perform:
485# build - bad fails to build
486# boot - bad builds but fails to boot
487# test - bad boots but fails a test
488#
489# BISECT_GOOD is the commit (SHA1) to label as good (accepts all git good commit types)
490# BISECT_BAD is the commit to label as bad (accepts all git bad commit types)
491#
492# The above three options are required for a bisect operation.
493#
494# BISECT_REPLAY = /path/to/replay/file (optional, default undefined)
495#
496# If an operation failed in the bisect that was not expected to
497# fail. Then the test ends. The state of the BUILD_DIR will be
498# left off at where the failure occurred. You can examine the
499# reason for the failure, and perhaps even find a git commit
500# that would work to continue with. You can run:
501#
502# git bisect log > /path/to/replay/file
503#
504# The adding:
505#
506# BISECT_REPLAY= /path/to/replay/file
507#
508# And running the test again. The test will perform the initial
509# git bisect start, git bisect good, and git bisect bad, and
510# then it will run git bisect replay on this file, before
511# continuing with the bisect.
512#
513# BISECT_START = commit (optional, default undefined)
514#
515# As with BISECT_REPLAY, if the test failed on a commit that
516# just happen to have a bad commit in the middle of the bisect,
517# and you need to skip it. If BISECT_START is defined, it
518# will checkout that commit after doing the initial git bisect start,
519# git bisect good, git bisect bad, and running the git bisect replay
520# if the BISECT_REPLAY is set.
521#
522# BISECT_REVERSE = 1 (optional, default 0)
523#
524# In those strange instances where it was broken forever
525# and you are trying to find where it started to work!
526# Set BISECT_GOOD to the commit that was last known to fail
527# Set BISECT_BAD to the commit that is known to start working.
528# With BISECT_REVERSE = 1, The test will consider failures as
529# good, and success as bad.
530#
531# BISECT_CHECK = 1 (optional, default 0)
532#
533# Just to be sure the good is good and bad is bad, setting
534# BISECT_CHECK to 1 will start the bisect by first checking
535# out BISECT_BAD and makes sure it fails, then it will check
536# out BISECT_GOOD and makes sure it succeeds before starting
537# the bisect (it works for BISECT_REVERSE too).
538#
539# You can limit the test to just check BISECT_GOOD or
540# BISECT_BAD with BISECT_CHECK = good or
541# BISECT_CHECK = bad, respectively.
542#
543# Example:
544# TEST_START
545# TEST_TYPE = bisect
546# BISECT_GOOD = v2.6.36
547# BISECT_BAD = b5153163ed580e00c67bdfecb02b2e3843817b3e
548# BISECT_TYPE = build
549# MIN_CONFIG = /home/test/config-bisect
550#
551#
552#
553# For TEST_TYPE = config_bisect
554#
555# In those cases that you have two different configs. One of them
556# work, the other does not, and you do not know what config causes
557# the problem.
558# The TEST_TYPE config_bisect will bisect the bad config looking for
559# what config causes the failure.
560#
561# The way it works is this:
562#
563# First it finds a config to work with. Since a different version, or
564# MIN_CONFIG may cause different dependecies, it must run through this
565# preparation.
566#
567# Overwrites any config set in the bad config with a config set in
568# either the MIN_CONFIG or ADD_CONFIG. Thus, make sure these configs
569# are minimal and do not disable configs you want to test:
570# (ie. # CONFIG_FOO is not set).
571#
572# An oldconfig is run on the bad config and any new config that
573# appears will be added to the configs to test.
574#
575# Finally, it generates a config with the above result and runs it
576# again through make oldconfig to produce a config that should be
577# satisfied by kconfig.
578#
579# Then it starts the bisect.
580#
581# The configs to test are cut in half. If all the configs in this
582# half depend on a config in the other half, then the other half
583# is tested instead. If no configs are enabled by either half, then
584# this means a circular dependency exists and the test fails.
585#
586# A config is created with the test half, and the bisect test is run.
587#
588# If the bisect succeeds, then all configs in the generated config
589# are removed from the configs to test and added to the configs that
590# will be enabled for all builds (they will be enabled, but not be part
591# of the configs to examine).
592#
593# If the bisect fails, then all test configs that were not enabled by
594# the config file are removed from the test. These configs will not
595# be enabled in future tests. Since current config failed, we consider
596# this to be a subset of the config that we started with.
597#
598# When we are down to one config, it is considered the bad config.
599#
600# Note, the config chosen may not be the true bad config. Due to
601# dependencies and selections of the kbuild system, mulitple
602# configs may be needed to cause a failure. If you disable the
603# config that was found and restart the test, if the test fails
604# again, it is recommended to rerun the config_bisect with a new
605# bad config without the found config enabled.
606#
607# The option BUILD_TYPE will be ignored.
608#
609# CONFIG_BISECT_TYPE is the type of test to perform:
610# build - bad fails to build
611# boot - bad builds but fails to boot
612# test - bad boots but fails a test
613#
614# CONFIG_BISECT is the config that failed to boot
615#
616# Example:
617# TEST_START
618# TEST_TYPE = config_bisect
619# CONFIG_BISECT_TYPE = build
620# CONFIG_BISECT = /home/test/¢onfig-bad
621# MIN_CONFIG = /home/test/config-min
622#
diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
new file mode 100644
index 000000000000..d1d442ed106a
--- /dev/null
+++ b/tools/virtio/Makefile
@@ -0,0 +1,12 @@
1all: test mod
2test: virtio_test
3virtio_test: virtio_ring.o virtio_test.o
4CFLAGS += -g -O2 -Wall -I. -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -MMD
5vpath %.c ../../drivers/virtio
6mod:
7 ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test
8.PHONY: all test mod clean
9clean:
10 ${RM} *.o vhost_test/*.o vhost_test/.*.cmd \
11 vhost_test/Module.symvers vhost_test/modules.order *.d
12-include *.d
diff --git a/tools/virtio/linux/device.h b/tools/virtio/linux/device.h
new file mode 100644
index 000000000000..4ad7e1df0db5
--- /dev/null
+++ b/tools/virtio/linux/device.h
@@ -0,0 +1,2 @@
1#ifndef LINUX_DEVICE_H
2#endif
diff --git a/tools/virtio/linux/slab.h b/tools/virtio/linux/slab.h
new file mode 100644
index 000000000000..81baeac8ae40
--- /dev/null
+++ b/tools/virtio/linux/slab.h
@@ -0,0 +1,2 @@
1#ifndef LINUX_SLAB_H
2#endif
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
new file mode 100644
index 000000000000..669bcdd45805
--- /dev/null
+++ b/tools/virtio/linux/virtio.h
@@ -0,0 +1,223 @@
1#ifndef LINUX_VIRTIO_H
2#define LINUX_VIRTIO_H
3
4#include <stdbool.h>
5#include <stdlib.h>
6#include <stddef.h>
7#include <stdio.h>
8#include <string.h>
9#include <assert.h>
10
11#include <linux/types.h>
12#include <errno.h>
13
14typedef unsigned long long dma_addr_t;
15
16struct scatterlist {
17 unsigned long page_link;
18 unsigned int offset;
19 unsigned int length;
20 dma_addr_t dma_address;
21};
22
23struct page {
24 unsigned long long dummy;
25};
26
27#define BUG_ON(__BUG_ON_cond) assert(!(__BUG_ON_cond))
28
29/* Physical == Virtual */
30#define virt_to_phys(p) ((unsigned long)p)
31#define phys_to_virt(a) ((void *)(unsigned long)(a))
32/* Page address: Virtual / 4K */
33#define virt_to_page(p) ((struct page*)((virt_to_phys(p) / 4096) * \
34 sizeof(struct page)))
35#define offset_in_page(p) (((unsigned long)p) % 4096)
36#define sg_phys(sg) ((sg->page_link & ~0x3) / sizeof(struct page) * 4096 + \
37 sg->offset)
38static inline void sg_mark_end(struct scatterlist *sg)
39{
40 /*
41 * Set termination bit, clear potential chain bit
42 */
43 sg->page_link |= 0x02;
44 sg->page_link &= ~0x01;
45}
46static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
47{
48 memset(sgl, 0, sizeof(*sgl) * nents);
49 sg_mark_end(&sgl[nents - 1]);
50}
51static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
52{
53 unsigned long page_link = sg->page_link & 0x3;
54
55 /*
56 * In order for the low bit stealing approach to work, pages
57 * must be aligned at a 32-bit boundary as a minimum.
58 */
59 BUG_ON((unsigned long) page & 0x03);
60 sg->page_link = page_link | (unsigned long) page;
61}
62
63static inline void sg_set_page(struct scatterlist *sg, struct page *page,
64 unsigned int len, unsigned int offset)
65{
66 sg_assign_page(sg, page);
67 sg->offset = offset;
68 sg->length = len;
69}
70
71static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
72 unsigned int buflen)
73{
74 sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
75}
76
77static inline void sg_init_one(struct scatterlist *sg, const void *buf, unsigned int buflen)
78{
79 sg_init_table(sg, 1);
80 sg_set_buf(sg, buf, buflen);
81}
82
83typedef __u16 u16;
84
85typedef enum {
86 GFP_KERNEL,
87 GFP_ATOMIC,
88} gfp_t;
89typedef enum {
90 IRQ_NONE,
91 IRQ_HANDLED
92} irqreturn_t;
93
94static inline void *kmalloc(size_t s, gfp_t gfp)
95{
96 return malloc(s);
97}
98
99static inline void kfree(void *p)
100{
101 free(p);
102}
103
104#define container_of(ptr, type, member) ({ \
105 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
106 (type *)( (char *)__mptr - offsetof(type,member) );})
107
108#define uninitialized_var(x) x = x
109
110# ifndef likely
111# define likely(x) (__builtin_expect(!!(x), 1))
112# endif
113# ifndef unlikely
114# define unlikely(x) (__builtin_expect(!!(x), 0))
115# endif
116
117#define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
118#ifdef DEBUG
119#define pr_debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
120#else
121#define pr_debug(format, ...) do {} while (0)
122#endif
123#define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
124#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
125
126/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
127#define list_add_tail(a, b) do {} while (0)
128#define list_del(a) do {} while (0)
129
130#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
131#define BITS_PER_BYTE 8
132#define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE)
133#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
134/* TODO: Not atomic as it should be:
135 * we don't use this for anything important. */
136static inline void clear_bit(int nr, volatile unsigned long *addr)
137{
138 unsigned long mask = BIT_MASK(nr);
139 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
140
141 *p &= ~mask;
142}
143
144static inline int test_bit(int nr, const volatile unsigned long *addr)
145{
146 return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
147}
148
149/* The only feature we care to support */
150#define virtio_has_feature(dev, feature) \
151 test_bit((feature), (dev)->features)
152/* end of stubs */
153
154struct virtio_device {
155 void *dev;
156 unsigned long features[1];
157};
158
159struct virtqueue {
160 /* TODO: commented as list macros are empty stubs for now.
161 * Broken but enough for virtio_ring.c
162 * struct list_head list; */
163 void (*callback)(struct virtqueue *vq);
164 const char *name;
165 struct virtio_device *vdev;
166 void *priv;
167};
168
169#define EXPORT_SYMBOL_GPL(__EXPORT_SYMBOL_GPL_name) \
170 void __EXPORT_SYMBOL_GPL##__EXPORT_SYMBOL_GPL_name() { \
171}
172#define MODULE_LICENSE(__MODULE_LICENSE_value) \
173 const char *__MODULE_LICENSE_name = __MODULE_LICENSE_value
174
175#define CONFIG_SMP
176
177#if defined(__i386__) || defined(__x86_64__)
178#define barrier() asm volatile("" ::: "memory")
179#define mb() __sync_synchronize()
180
181#define smp_mb() mb()
182# define smp_rmb() barrier()
183# define smp_wmb() barrier()
184#else
185#error Please fill in barrier macros
186#endif
187
188/* Interfaces exported by virtio_ring. */
189int virtqueue_add_buf_gfp(struct virtqueue *vq,
190 struct scatterlist sg[],
191 unsigned int out_num,
192 unsigned int in_num,
193 void *data,
194 gfp_t gfp);
195
196static inline int virtqueue_add_buf(struct virtqueue *vq,
197 struct scatterlist sg[],
198 unsigned int out_num,
199 unsigned int in_num,
200 void *data)
201{
202 return virtqueue_add_buf_gfp(vq, sg, out_num, in_num, data, GFP_ATOMIC);
203}
204
205void virtqueue_kick(struct virtqueue *vq);
206
207void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
208
209void virtqueue_disable_cb(struct virtqueue *vq);
210
211bool virtqueue_enable_cb(struct virtqueue *vq);
212
213void *virtqueue_detach_unused_buf(struct virtqueue *vq);
214struct virtqueue *vring_new_virtqueue(unsigned int num,
215 unsigned int vring_align,
216 struct virtio_device *vdev,
217 void *pages,
218 void (*notify)(struct virtqueue *vq),
219 void (*callback)(struct virtqueue *vq),
220 const char *name);
221void vring_del_virtqueue(struct virtqueue *vq);
222
223#endif
diff --git a/tools/virtio/vhost_test/Makefile b/tools/virtio/vhost_test/Makefile
new file mode 100644
index 000000000000..a1d35b81b314
--- /dev/null
+++ b/tools/virtio/vhost_test/Makefile
@@ -0,0 +1,2 @@
1obj-m += vhost_test.o
2EXTRA_CFLAGS += -Idrivers/vhost
diff --git a/tools/virtio/vhost_test/vhost_test.c b/tools/virtio/vhost_test/vhost_test.c
new file mode 100644
index 000000000000..18735189e62b
--- /dev/null
+++ b/tools/virtio/vhost_test/vhost_test.c
@@ -0,0 +1 @@
#include "test.c"
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
new file mode 100644
index 000000000000..df0c6d2c3860
--- /dev/null
+++ b/tools/virtio/virtio_test.c
@@ -0,0 +1,248 @@
1#define _GNU_SOURCE
2#include <getopt.h>
3#include <string.h>
4#include <poll.h>
5#include <sys/eventfd.h>
6#include <stdlib.h>
7#include <assert.h>
8#include <unistd.h>
9#include <sys/ioctl.h>
10#include <sys/stat.h>
11#include <sys/types.h>
12#include <fcntl.h>
13#include <linux/vhost.h>
14#include <linux/virtio.h>
15#include <linux/virtio_ring.h>
16#include "../../drivers/vhost/test.h"
17
18struct vq_info {
19 int kick;
20 int call;
21 int num;
22 int idx;
23 void *ring;
24 /* copy used for control */
25 struct vring vring;
26 struct virtqueue *vq;
27};
28
29struct vdev_info {
30 struct virtio_device vdev;
31 int control;
32 struct pollfd fds[1];
33 struct vq_info vqs[1];
34 int nvqs;
35 void *buf;
36 size_t buf_size;
37 struct vhost_memory *mem;
38};
39
40void vq_notify(struct virtqueue *vq)
41{
42 struct vq_info *info = vq->priv;
43 unsigned long long v = 1;
44 int r;
45 r = write(info->kick, &v, sizeof v);
46 assert(r == sizeof v);
47}
48
49void vq_callback(struct virtqueue *vq)
50{
51}
52
53
54void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info)
55{
56 struct vhost_vring_state state = { .index = info->idx };
57 struct vhost_vring_file file = { .index = info->idx };
58 unsigned long long features = dev->vdev.features[0];
59 struct vhost_vring_addr addr = {
60 .index = info->idx,
61 .desc_user_addr = (uint64_t)(unsigned long)info->vring.desc,
62 .avail_user_addr = (uint64_t)(unsigned long)info->vring.avail,
63 .used_user_addr = (uint64_t)(unsigned long)info->vring.used,
64 };
65 int r;
66 r = ioctl(dev->control, VHOST_SET_FEATURES, &features);
67 assert(r >= 0);
68 state.num = info->vring.num;
69 r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state);
70 assert(r >= 0);
71 state.num = 0;
72 r = ioctl(dev->control, VHOST_SET_VRING_BASE, &state);
73 assert(r >= 0);
74 r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr);
75 assert(r >= 0);
76 file.fd = info->kick;
77 r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file);
78 assert(r >= 0);
79 file.fd = info->call;
80 r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file);
81 assert(r >= 0);
82}
83
84static void vq_info_add(struct vdev_info *dev, int num)
85{
86 struct vq_info *info = &dev->vqs[dev->nvqs];
87 int r;
88 info->idx = dev->nvqs;
89 info->kick = eventfd(0, EFD_NONBLOCK);
90 info->call = eventfd(0, EFD_NONBLOCK);
91 r = posix_memalign(&info->ring, 4096, vring_size(num, 4096));
92 assert(r >= 0);
93 memset(info->ring, 0, vring_size(num, 4096));
94 vring_init(&info->vring, num, info->ring, 4096);
95 info->vq = vring_new_virtqueue(info->vring.num, 4096, &dev->vdev, info->ring,
96 vq_notify, vq_callback, "test");
97 assert(info->vq);
98 info->vq->priv = info;
99 vhost_vq_setup(dev, info);
100 dev->fds[info->idx].fd = info->call;
101 dev->fds[info->idx].events = POLLIN;
102 dev->nvqs++;
103}
104
105static void vdev_info_init(struct vdev_info* dev, unsigned long long features)
106{
107 int r;
108 memset(dev, 0, sizeof *dev);
109 dev->vdev.features[0] = features;
110 dev->vdev.features[1] = features >> 32;
111 dev->buf_size = 1024;
112 dev->buf = malloc(dev->buf_size);
113 assert(dev->buf);
114 dev->control = open("/dev/vhost-test", O_RDWR);
115 assert(dev->control >= 0);
116 r = ioctl(dev->control, VHOST_SET_OWNER, NULL);
117 assert(r >= 0);
118 dev->mem = malloc(offsetof(struct vhost_memory, regions) +
119 sizeof dev->mem->regions[0]);
120 assert(dev->mem);
121 memset(dev->mem, 0, offsetof(struct vhost_memory, regions) +
122 sizeof dev->mem->regions[0]);
123 dev->mem->nregions = 1;
124 dev->mem->regions[0].guest_phys_addr = (long)dev->buf;
125 dev->mem->regions[0].userspace_addr = (long)dev->buf;
126 dev->mem->regions[0].memory_size = dev->buf_size;
127 r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
128 assert(r >= 0);
129}
130
131/* TODO: this is pretty bad: we get a cache line bounce
132 * for the wait queue on poll and another one on read,
133 * plus the read which is there just to clear the
134 * current state. */
135static void wait_for_interrupt(struct vdev_info *dev)
136{
137 int i;
138 unsigned long long val;
139 poll(dev->fds, dev->nvqs, -1);
140 for (i = 0; i < dev->nvqs; ++i)
141 if (dev->fds[i].revents & POLLIN) {
142 read(dev->fds[i].fd, &val, sizeof val);
143 }
144}
145
146static void run_test(struct vdev_info *dev, struct vq_info *vq, int bufs)
147{
148 struct scatterlist sl;
149 long started = 0, completed = 0;
150 long completed_before;
151 int r, test = 1;
152 unsigned len;
153 long long spurious = 0;
154 r = ioctl(dev->control, VHOST_TEST_RUN, &test);
155 assert(r >= 0);
156 for (;;) {
157 virtqueue_disable_cb(vq->vq);
158 completed_before = completed;
159 do {
160 if (started < bufs) {
161 sg_init_one(&sl, dev->buf, dev->buf_size);
162 r = virtqueue_add_buf(vq->vq, &sl, 1, 0,
163 dev->buf + started);
164 if (likely(r >= 0)) {
165 ++started;
166 virtqueue_kick(vq->vq);
167 }
168 } else
169 r = -1;
170
171 /* Flush out completed bufs if any */
172 if (virtqueue_get_buf(vq->vq, &len)) {
173 ++completed;
174 r = 0;
175 }
176
177 } while (r >= 0);
178 if (completed == completed_before)
179 ++spurious;
180 assert(completed <= bufs);
181 assert(started <= bufs);
182 if (completed == bufs)
183 break;
184 if (virtqueue_enable_cb(vq->vq)) {
185 wait_for_interrupt(dev);
186 }
187 }
188 test = 0;
189 r = ioctl(dev->control, VHOST_TEST_RUN, &test);
190 assert(r >= 0);
191 fprintf(stderr, "spurious wakeus: 0x%llx\n", spurious);
192}
193
194const char optstring[] = "h";
195const struct option longopts[] = {
196 {
197 .name = "help",
198 .val = 'h',
199 },
200 {
201 .name = "indirect",
202 .val = 'I',
203 },
204 {
205 .name = "no-indirect",
206 .val = 'i',
207 },
208 {
209 }
210};
211
212static void help()
213{
214 fprintf(stderr, "Usage: virtio_test [--help] [--no-indirect]\n");
215}
216
217int main(int argc, char **argv)
218{
219 struct vdev_info dev;
220 unsigned long long features = 1ULL << VIRTIO_RING_F_INDIRECT_DESC;
221 int o;
222
223 for (;;) {
224 o = getopt_long(argc, argv, optstring, longopts, NULL);
225 switch (o) {
226 case -1:
227 goto done;
228 case '?':
229 help();
230 exit(2);
231 case 'h':
232 help();
233 goto done;
234 case 'i':
235 features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC);
236 break;
237 default:
238 assert(0);
239 break;
240 }
241 }
242
243done:
244 vdev_info_init(&dev, features);
245 vq_info_add(&dev, 256);
246 run_test(&dev, &dev.vqs[0], 0x100000);
247 return 0;
248}