aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
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.txt22
-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.txt (renamed from tools/perf/Documentation/perf-trace.txt)61
-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/MANIFEST1
-rw-r--r--tools/perf/Makefile25
-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.c10
-rw-r--r--tools/perf/builtin-buildid-list.c3
-rw-r--r--tools/perf/builtin-diff.c21
-rw-r--r--tools/perf/builtin-inject.c41
-rw-r--r--tools/perf/builtin-kmem.c27
-rw-r--r--tools/perf/builtin-lock.c23
-rw-r--r--tools/perf/builtin-record.c213
-rw-r--r--tools/perf/builtin-report.c23
-rw-r--r--tools/perf/builtin-sched.c36
-rw-r--r--tools/perf/builtin-script.c (renamed from tools/perf/builtin-trace.c)135
-rw-r--r--tools/perf/builtin-stat.c532
-rw-r--r--tools/perf/builtin-test.c224
-rw-r--r--tools/perf/builtin-timechart.c132
-rw-r--r--tools/perf/builtin-top.c239
-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.c4
-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-report2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-report5
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-report5
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-report5
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-report5
-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-report2
-rw-r--r--tools/perf/scripts/python/bin/futex-contention-report2
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-report2
-rw-r--r--tools/perf/scripts/python/bin/sched-migration-report2
-rw-r--r--tools/perf/scripts/python/bin/sctop-report2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-report2
-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.c358
-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.c58
-rw-r--r--tools/perf/util/header.h5
-rw-r--r--tools/perf/util/hist.c23
-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.h5
-rw-r--r--tools/perf/util/include/linux/linkage.h13
-rw-r--r--tools/perf/util/parse-events.c179
-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.c234
-rw-r--r--tools/perf/util/probe-finder.c42
-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.c579
-rw-r--r--tools/perf/util/session.h26
-rw-r--r--tools/perf/util/sort.c6
-rw-r--r--tools/perf/util/symbol.c139
-rw-r--r--tools/perf/util/symbol.h4
-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/ui/util.c16
-rw-r--r--tools/perf/util/util.c17
-rw-r--r--tools/perf/util/util.h1
-rw-r--r--tools/perf/util/xyarray.c20
-rw-r--r--tools/perf/util/xyarray.h20
-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
124 files changed, 7962 insertions, 1480 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..52462ae26455 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -39,15 +39,24 @@ 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=::
@@ -99,6 +108,11 @@ OPTIONS
99--data:: 108--data::
100 Sample addresses. 109 Sample addresses.
101 110
111-T::
112--timestamp::
113 Sample timestamps. Use it with 'perf report -D' to see the timestamps,
114 for instance.
115
102-n:: 116-n::
103--no-samples:: 117--no-samples::
104 Don't sample. 118 Don't sample.
@@ -109,8 +123,8 @@ Collect raw sample records from all opened counters (default for tracepoint coun
109 123
110-C:: 124-C::
111--cpu:: 125--cpu::
112Collect samples only on the list of cpus provided. Multiple CPUs can be provided as a 126Collect 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. 127comma-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 128In 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. 129the thread executes on the designated CPUs. Default is to monitor all CPUs.
116 130
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-trace.txt b/tools/perf/Documentation/perf-script.txt
index 26aff6bf9e50..29ad94293cd2 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -1,71 +1,71 @@
1perf-trace(1) 1perf-script(1)
2============= 2=============
3 3
4NAME 4NAME
5---- 5----
6perf-trace - Read perf.data (created by perf record) and display trace output 6perf-script - Read perf.data (created by perf record) and display trace output
7 7
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf trace' [<options>] 11'perf script' [<options>]
12'perf trace' [<options>] record <script> [<record-options>] <command> 12'perf script' [<options>] record <script> [<record-options>] <command>
13'perf trace' [<options>] report <script> [script-args] 13'perf script' [<options>] report <script> [script-args]
14'perf trace' [<options>] <script> <required-script-args> [<record-options>] <command> 14'perf script' [<options>] <script> <required-script-args> [<record-options>] <command>
15'perf trace' [<options>] <top-script> [script-args] 15'perf script' [<options>] <top-script> [script-args]
16 16
17DESCRIPTION 17DESCRIPTION
18----------- 18-----------
19This command reads the input file and displays the trace recorded. 19This command reads the input file and displays the trace recorded.
20 20
21There are several variants of perf trace: 21There are several variants of perf script:
22 22
23 'perf trace' to see a detailed trace of the workload that was 23 'perf script' to see a detailed trace of the workload that was
24 recorded. 24 recorded.
25 25
26 You can also run a set of pre-canned scripts that aggregate and 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 27 summarize the raw trace data in various ways (the list of scripts is
28 available via 'perf trace -l'). The following variants allow you to 28 available via 'perf script -l'). The following variants allow you to
29 record and run those scripts: 29 record and run those scripts:
30 30
31 'perf trace record <script> <command>' to record the events required 31 'perf script record <script> <command>' to record the events required
32 for 'perf trace report'. <script> is the name displayed in the 32 for 'perf script report'. <script> is the name displayed in the
33 output of 'perf trace --list' i.e. the actual script name minus any 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 34 language extension. If <command> is not specified, the events are
35 recorded using the -a (system-wide) 'perf record' option. 35 recorded using the -a (system-wide) 'perf record' option.
36 36
37 'perf trace report <script> [args]' to run and display the results 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 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 39 trace --list' i.e. the actual script name minus any language
40 extension. The perf.data output from a previous run of 'perf trace 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 41 record <script>' is used and should be present for this command to
42 succeed. [args] refers to the (mainly optional) args expected by 42 succeed. [args] refers to the (mainly optional) args expected by
43 the script. 43 the script.
44 44
45 'perf trace <script> <required-script-args> <command>' to both 45 'perf script <script> <required-script-args> <command>' to both
46 record the events required for <script> and to run the <script> 46 record the events required for <script> and to run the <script>
47 using 'live-mode' i.e. without writing anything to disk. <script> 47 using 'live-mode' i.e. without writing anything to disk. <script>
48 is the name displayed in the output of 'perf trace --list' i.e. the 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 49 actual script name minus any language extension. If <command> is
50 not specified, the events are recorded using the -a (system-wide) 50 not specified, the events are recorded using the -a (system-wide)
51 'perf record' option. If <script> has any required args, they 51 'perf record' option. If <script> has any required args, they
52 should be specified before <command>. This mode doesn't allow for 52 should be specified before <command>. This mode doesn't allow for
53 optional script args to be specified; if optional script args are 53 optional script args to be specified; if optional script args are
54 desired, they can be specified using separate 'perf trace record' 54 desired, they can be specified using separate 'perf script record'
55 and 'perf trace report' commands, with the stdout of the record step 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 -' 56 piped to the stdin of the report script, using the '-o -' and '-i -'
57 options of the corresponding commands. 57 options of the corresponding commands.
58 58
59 'perf trace <top-script>' to both record the events required for 59 'perf script <top-script>' to both record the events required for
60 <top-script> and to run the <top-script> using 'live-mode' 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 61 i.e. without writing anything to disk. <top-script> is the name
62 displayed in the output of 'perf trace --list' i.e. the actual 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 63 script name minus any language extension; a <top-script> is defined
64 as any script name ending with the string 'top'. 64 as any script name ending with the string 'top'.
65 65
66 [<record-options>] can be passed to the record steps of 'perf trace 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 67 record' and 'live-mode' variants; this isn't possible however for
68 <top-script> 'live-mode' or 'perf trace report' variants. 68 <top-script> 'live-mode' or 'perf script report' variants.
69 69
70 See the 'SEE ALSO' section for links to language-specific 70 See the 'SEE ALSO' section for links to language-specific
71 information on how to write and run your own trace scripts. 71 information on how to write and run your own trace scripts.
@@ -76,7 +76,7 @@ OPTIONS
76 Any command you can specify in a shell. 76 Any command you can specify in a shell.
77 77
78-D:: 78-D::
79--dump-raw-trace=:: 79--dump-raw-script=::
80 Display verbose dump of the trace data. 80 Display verbose dump of the trace data.
81 81
82-L:: 82-L::
@@ -95,7 +95,7 @@ OPTIONS
95 95
96-g:: 96-g::
97--gen-script=:: 97--gen-script=::
98 Generate perf-trace.[ext] starter script for given language, 98 Generate perf-script.[ext] starter script for given language,
99 using current perf.data. 99 using current perf.data.
100 100
101-a:: 101-a::
@@ -104,8 +104,15 @@ OPTIONS
104 normally don't - this option allows the latter to be run in 104 normally don't - this option allows the latter to be run in
105 system-wide mode. 105 system-wide mode.
106 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.
107 114
108SEE ALSO 115SEE ALSO
109-------- 116--------
110linkperf:perf-record[1], linkperf:perf-trace-perl[1], 117linkperf:perf-record[1], linkperf:perf-script-perl[1],
111linkperf:perf-trace-python[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/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..2b5387d53ba5 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.
@@ -224,7 +227,7 @@ ifndef PERF_DEBUG
224 CFLAGS_OPTIMIZE = -O6 227 CFLAGS_OPTIMIZE = -O6
225endif 228endif
226 229
227CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 230CFLAGS = -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 231EXTLIBS = -lpthread -lrt -lelf -lm
229ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 232ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
230ALL_LDFLAGS = $(LDFLAGS) 233ALL_LDFLAGS = $(LDFLAGS)
@@ -375,6 +378,7 @@ LIB_H += util/include/linux/prefetch.h
375LIB_H += util/include/linux/rbtree.h 378LIB_H += util/include/linux/rbtree.h
376LIB_H += util/include/linux/string.h 379LIB_H += util/include/linux/string.h
377LIB_H += util/include/linux/types.h 380LIB_H += util/include/linux/types.h
381LIB_H += util/include/linux/linkage.h
378LIB_H += util/include/asm/asm-offsets.h 382LIB_H += util/include/asm/asm-offsets.h
379LIB_H += util/include/asm/bug.h 383LIB_H += util/include/asm/bug.h
380LIB_H += util/include/asm/byteorder.h 384LIB_H += util/include/asm/byteorder.h
@@ -383,6 +387,8 @@ LIB_H += util/include/asm/swab.h
383LIB_H += util/include/asm/system.h 387LIB_H += util/include/asm/system.h
384LIB_H += util/include/asm/uaccess.h 388LIB_H += util/include/asm/uaccess.h
385LIB_H += util/include/dwarf-regs.h 389LIB_H += util/include/dwarf-regs.h
390LIB_H += util/include/asm/dwarf2.h
391LIB_H += util/include/asm/cpufeature.h
386LIB_H += perf.h 392LIB_H += perf.h
387LIB_H += util/cache.h 393LIB_H += util/cache.h
388LIB_H += util/callchain.h 394LIB_H += util/callchain.h
@@ -390,6 +396,7 @@ LIB_H += util/build-id.h
390LIB_H += util/debug.h 396LIB_H += util/debug.h
391LIB_H += util/debugfs.h 397LIB_H += util/debugfs.h
392LIB_H += util/event.h 398LIB_H += util/event.h
399LIB_H += util/evsel.h
393LIB_H += util/exec_cmd.h 400LIB_H += util/exec_cmd.h
394LIB_H += util/types.h 401LIB_H += util/types.h
395LIB_H += util/levenshtein.h 402LIB_H += util/levenshtein.h
@@ -398,6 +405,7 @@ LIB_H += util/parse-options.h
398LIB_H += util/parse-events.h 405LIB_H += util/parse-events.h
399LIB_H += util/quote.h 406LIB_H += util/quote.h
400LIB_H += util/util.h 407LIB_H += util/util.h
408LIB_H += util/xyarray.h
401LIB_H += util/header.h 409LIB_H += util/header.h
402LIB_H += util/help.h 410LIB_H += util/help.h
403LIB_H += util/session.h 411LIB_H += util/session.h
@@ -417,6 +425,7 @@ LIB_H += util/probe-finder.h
417LIB_H += util/probe-event.h 425LIB_H += util/probe-event.h
418LIB_H += util/pstack.h 426LIB_H += util/pstack.h
419LIB_H += util/cpumap.h 427LIB_H += util/cpumap.h
428LIB_H += $(ARCH_INCLUDE)
420 429
421LIB_OBJS += $(OUTPUT)util/abspath.o 430LIB_OBJS += $(OUTPUT)util/abspath.o
422LIB_OBJS += $(OUTPUT)util/alias.o 431LIB_OBJS += $(OUTPUT)util/alias.o
@@ -426,6 +435,7 @@ LIB_OBJS += $(OUTPUT)util/ctype.o
426LIB_OBJS += $(OUTPUT)util/debugfs.o 435LIB_OBJS += $(OUTPUT)util/debugfs.o
427LIB_OBJS += $(OUTPUT)util/environment.o 436LIB_OBJS += $(OUTPUT)util/environment.o
428LIB_OBJS += $(OUTPUT)util/event.o 437LIB_OBJS += $(OUTPUT)util/event.o
438LIB_OBJS += $(OUTPUT)util/evsel.o
429LIB_OBJS += $(OUTPUT)util/exec_cmd.o 439LIB_OBJS += $(OUTPUT)util/exec_cmd.o
430LIB_OBJS += $(OUTPUT)util/help.o 440LIB_OBJS += $(OUTPUT)util/help.o
431LIB_OBJS += $(OUTPUT)util/levenshtein.o 441LIB_OBJS += $(OUTPUT)util/levenshtein.o
@@ -463,6 +473,7 @@ LIB_OBJS += $(OUTPUT)util/sort.o
463LIB_OBJS += $(OUTPUT)util/hist.o 473LIB_OBJS += $(OUTPUT)util/hist.o
464LIB_OBJS += $(OUTPUT)util/probe-event.o 474LIB_OBJS += $(OUTPUT)util/probe-event.o
465LIB_OBJS += $(OUTPUT)util/util.o 475LIB_OBJS += $(OUTPUT)util/util.o
476LIB_OBJS += $(OUTPUT)util/xyarray.o
466LIB_OBJS += $(OUTPUT)util/cpumap.o 477LIB_OBJS += $(OUTPUT)util/cpumap.o
467 478
468BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 479BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
@@ -472,6 +483,9 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
472# Benchmark modules 483# Benchmark modules
473BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o 484BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
474BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o 485BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
486ifeq ($(RAW_ARCH),x86_64)
487BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
488endif
475BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 489BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
476 490
477BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 491BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
@@ -485,7 +499,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-report.o
485BUILTIN_OBJS += $(OUTPUT)builtin-stat.o 499BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
486BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o 500BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
487BUILTIN_OBJS += $(OUTPUT)builtin-top.o 501BUILTIN_OBJS += $(OUTPUT)builtin-top.o
488BUILTIN_OBJS += $(OUTPUT)builtin-trace.o 502BUILTIN_OBJS += $(OUTPUT)builtin-script.o
489BUILTIN_OBJS += $(OUTPUT)builtin-probe.o 503BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
490BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o 504BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
491BUILTIN_OBJS += $(OUTPUT)builtin-lock.o 505BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
@@ -507,7 +521,7 @@ PERFLIBS = $(LIB_FILE)
507-include config.mak 521-include config.mak
508 522
509ifndef NO_DWARF 523ifndef NO_DWARF
510FLAGS_DWARF=$(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) 524FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
511ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) 525ifneq ($(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); 526 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 527 NO_DWARF := 1
@@ -554,7 +568,7 @@ ifndef NO_DWARF
554ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 568ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
555 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 569 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
556else 570else
557 BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT 571 BASIC_CFLAGS += -DDWARF_SUPPORT
558 EXTLIBS += -lelf -ldw 572 EXTLIBS += -lelf -ldw
559 LIB_OBJS += $(OUTPUT)util/probe-finder.o 573 LIB_OBJS += $(OUTPUT)util/probe-finder.o
560endif # PERF_HAVE_DWARF_REGS 574endif # PERF_HAVE_DWARF_REGS
@@ -891,13 +905,14 @@ prefix_SQ = $(subst ','\'',$(prefix))
891SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) 905SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
892PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) 906PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
893 907
894LIBS = $(PERFLIBS) $(EXTLIBS) 908LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS)
895 909
896BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \ 910BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
897 $(COMPAT_CFLAGS) 911 $(COMPAT_CFLAGS)
898LIB_OBJS += $(COMPAT_OBJS) 912LIB_OBJS += $(COMPAT_OBJS)
899 913
900ALL_CFLAGS += $(BASIC_CFLAGS) 914ALL_CFLAGS += $(BASIC_CFLAGS)
915ALL_CFLAGS += $(ARCH_CFLAGS)
901ALL_LDFLAGS += $(BASIC_LDFLAGS) 916ALL_LDFLAGS += $(BASIC_LDFLAGS)
902 917
903export TAR INSTALL DESTDIR SHELL_PATH 918export 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..c056cdc06912 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;
@@ -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 c49837de7d3f..5af32ae9031e 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -38,7 +38,8 @@ static int __cmd_buildid_list(void)
38{ 38{
39 struct perf_session *session; 39 struct perf_session *session;
40 40
41 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);
42 if (session == NULL) 43 if (session == NULL)
43 return -1; 44 return -1;
44 45
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..def7ddc2fd4f 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}
@@ -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..b9c6e5432971 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -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-record.c b/tools/perf/builtin-record.c
index 564491fa18b2..7069bd3e90b3 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;
@@ -48,11 +50,11 @@ static const char *output_name = "perf.data";
48static int group = 0; 50static int group = 0;
49static int realtime_prio = 0; 51static int realtime_prio = 0;
50static bool raw_samples = false; 52static bool raw_samples = false;
53static bool sample_id_all_avail = true;
51static bool system_wide = false; 54static bool system_wide = false;
52static pid_t target_pid = -1; 55static pid_t target_pid = -1;
53static pid_t target_tid = -1; 56static pid_t target_tid = -1;
54static pid_t *all_tids = NULL; 57static struct thread_map *threads;
55static int thread_num = 0;
56static pid_t child_pid = -1; 58static pid_t child_pid = -1;
57static bool no_inherit = false; 59static bool no_inherit = false;
58static enum write_mode_t write_mode = WRITE_FORCE; 60static enum write_mode_t write_mode = WRITE_FORCE;
@@ -60,7 +62,9 @@ static bool call_graph = false;
60static bool inherit_stat = false; 62static bool inherit_stat = false;
61static bool no_samples = false; 63static bool no_samples = false;
62static bool sample_address = false; 64static bool sample_address = false;
65static bool sample_time = false;
63static bool no_buildid = false; 66static bool no_buildid = false;
67static bool no_buildid_cache = false;
64 68
65static long samples = 0; 69static long samples = 0;
66static u64 bytes_written = 0; 70static u64 bytes_written = 0;
@@ -77,7 +81,6 @@ static struct perf_session *session;
77static const char *cpu_list; 81static const char *cpu_list;
78 82
79struct mmap_data { 83struct mmap_data {
80 int counter;
81 void *base; 84 void *base;
82 unsigned int mask; 85 unsigned int mask;
83 unsigned int prev; 86 unsigned int prev;
@@ -128,6 +131,7 @@ static void write_output(void *buf, size_t size)
128} 131}
129 132
130static int process_synthesized_event(event_t *event, 133static int process_synthesized_event(event_t *event,
134 struct sample_data *sample __used,
131 struct perf_session *self __used) 135 struct perf_session *self __used)
132{ 136{
133 write_output(event, event->header.size); 137 write_output(event, event->header.size);
@@ -224,12 +228,12 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
224 return h_attr; 228 return h_attr;
225} 229}
226 230
227static void create_counter(int counter, int cpu) 231static void create_counter(struct perf_evsel *evsel, int cpu)
228{ 232{
229 char *filter = filters[counter]; 233 char *filter = evsel->filter;
230 struct perf_event_attr *attr = attrs + counter; 234 struct perf_event_attr *attr = &evsel->attr;
231 struct perf_header_attr *h_attr; 235 struct perf_header_attr *h_attr;
232 int track = !counter; /* only the first counter needs these */ 236 int track = !evsel->idx; /* only the first counter needs these */
233 int thread_index; 237 int thread_index;
234 int ret; 238 int ret;
235 struct { 239 struct {
@@ -238,6 +242,19 @@ static void create_counter(int counter, int cpu)
238 u64 time_running; 242 u64 time_running;
239 u64 id; 243 u64 id;
240 } read_data; 244 } read_data;
245 /*
246 * Check if parse_single_tracepoint_event has already asked for
247 * PERF_SAMPLE_TIME.
248 *
249 * XXX this is kludgy but short term fix for problems introduced by
250 * eac23d1c that broke 'perf script' by having different sample_types
251 * when using multiple tracepoint events when we use a perf binary
252 * that tries to use sample_id_all on an older kernel.
253 *
254 * We need to move counter creation to perf_session, support
255 * different sample_types, etc.
256 */
257 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
241 258
242 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 259 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
243 PERF_FORMAT_TOTAL_TIME_RUNNING | 260 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -280,6 +297,10 @@ static void create_counter(int counter, int cpu)
280 if (system_wide) 297 if (system_wide)
281 attr->sample_type |= PERF_SAMPLE_CPU; 298 attr->sample_type |= PERF_SAMPLE_CPU;
282 299
300 if (sample_id_all_avail &&
301 (sample_time || system_wide || !no_inherit || cpu_list))
302 attr->sample_type |= PERF_SAMPLE_TIME;
303
283 if (raw_samples) { 304 if (raw_samples) {
284 attr->sample_type |= PERF_SAMPLE_TIME; 305 attr->sample_type |= PERF_SAMPLE_TIME;
285 attr->sample_type |= PERF_SAMPLE_RAW; 306 attr->sample_type |= PERF_SAMPLE_RAW;
@@ -293,13 +314,14 @@ static void create_counter(int counter, int cpu)
293 attr->disabled = 1; 314 attr->disabled = 1;
294 attr->enable_on_exec = 1; 315 attr->enable_on_exec = 1;
295 } 316 }
317retry_sample_id:
318 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
296 319
297 for (thread_index = 0; thread_index < thread_num; thread_index++) { 320 for (thread_index = 0; thread_index < threads->nr; thread_index++) {
298try_again: 321try_again:
299 fd[nr_cpu][counter][thread_index] = sys_perf_event_open(attr, 322 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 323
302 if (fd[nr_cpu][counter][thread_index] < 0) { 324 if (FD(evsel, nr_cpu, thread_index) < 0) {
303 int err = errno; 325 int err = errno;
304 326
305 if (err == EPERM || err == EACCES) 327 if (err == EPERM || err == EACCES)
@@ -309,6 +331,18 @@ try_again:
309 else if (err == ENODEV && cpu_list) { 331 else if (err == ENODEV && cpu_list) {
310 die("No such device - did you specify" 332 die("No such device - did you specify"
311 " an out-of-range profile CPU?\n"); 333 " an out-of-range profile CPU?\n");
334 } else if (err == ENOENT) {
335 die("%s event is not supported. ",
336 event_name(evsel));
337 } else if (err == EINVAL && sample_id_all_avail) {
338 /*
339 * Old kernel, no attr->sample_id_type_all field
340 */
341 sample_id_all_avail = false;
342 if (!sample_time && !raw_samples && !time_needed)
343 attr->sample_type &= ~PERF_SAMPLE_TIME;
344
345 goto retry_sample_id;
312 } 346 }
313 347
314 /* 348 /*
@@ -326,8 +360,8 @@ try_again:
326 goto try_again; 360 goto try_again;
327 } 361 }
328 printf("\n"); 362 printf("\n");
329 error("perfcounter syscall returned with %d (%s)\n", 363 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)); 364 FD(evsel, nr_cpu, thread_index), strerror(err));
331 365
332#if defined(__i386__) || defined(__x86_64__) 366#if defined(__i386__) || defined(__x86_64__)
333 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 367 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
@@ -341,7 +375,7 @@ try_again:
341 exit(-1); 375 exit(-1);
342 } 376 }
343 377
344 h_attr = get_header_attr(attr, counter); 378 h_attr = get_header_attr(attr, evsel->idx);
345 if (h_attr == NULL) 379 if (h_attr == NULL)
346 die("nomem\n"); 380 die("nomem\n");
347 381
@@ -352,7 +386,7 @@ try_again:
352 } 386 }
353 } 387 }
354 388
355 if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) { 389 if (read(FD(evsel, nr_cpu, thread_index), &read_data, sizeof(read_data)) == -1) {
356 perror("Unable to read perf file descriptor"); 390 perror("Unable to read perf file descriptor");
357 exit(-1); 391 exit(-1);
358 } 392 }
@@ -362,43 +396,44 @@ try_again:
362 exit(-1); 396 exit(-1);
363 } 397 }
364 398
365 assert(fd[nr_cpu][counter][thread_index] >= 0); 399 assert(FD(evsel, nr_cpu, thread_index) >= 0);
366 fcntl(fd[nr_cpu][counter][thread_index], F_SETFL, O_NONBLOCK); 400 fcntl(FD(evsel, nr_cpu, thread_index), F_SETFL, O_NONBLOCK);
367 401
368 /* 402 /*
369 * First counter acts as the group leader: 403 * First counter acts as the group leader:
370 */ 404 */
371 if (group && group_fd == -1) 405 if (group && group_fd == -1)
372 group_fd = fd[nr_cpu][counter][thread_index]; 406 group_fd = FD(evsel, nr_cpu, thread_index);
373 407
374 if (counter || thread_index) { 408 if (evsel->idx || thread_index) {
375 ret = ioctl(fd[nr_cpu][counter][thread_index], 409 struct perf_evsel *first;
376 PERF_EVENT_IOC_SET_OUTPUT, 410 first = list_entry(evsel_list.next, struct perf_evsel, node);
377 fd[nr_cpu][0][0]); 411 ret = ioctl(FD(evsel, nr_cpu, thread_index),
412 PERF_EVENT_IOC_SET_OUTPUT,
413 FD(first, nr_cpu, 0));
378 if (ret) { 414 if (ret) {
379 error("failed to set output: %d (%s)\n", errno, 415 error("failed to set output: %d (%s)\n", errno,
380 strerror(errno)); 416 strerror(errno));
381 exit(-1); 417 exit(-1);
382 } 418 }
383 } else { 419 } else {
384 mmap_array[nr_cpu].counter = counter;
385 mmap_array[nr_cpu].prev = 0; 420 mmap_array[nr_cpu].prev = 0;
386 mmap_array[nr_cpu].mask = mmap_pages*page_size - 1; 421 mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
387 mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size, 422 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); 423 PROT_READ | PROT_WRITE, MAP_SHARED, FD(evsel, nr_cpu, thread_index), 0);
389 if (mmap_array[nr_cpu].base == MAP_FAILED) { 424 if (mmap_array[nr_cpu].base == MAP_FAILED) {
390 error("failed to mmap with %d (%s)\n", errno, strerror(errno)); 425 error("failed to mmap with %d (%s)\n", errno, strerror(errno));
391 exit(-1); 426 exit(-1);
392 } 427 }
393 428
394 event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index]; 429 event_array[nr_poll].fd = FD(evsel, nr_cpu, thread_index);
395 event_array[nr_poll].events = POLLIN; 430 event_array[nr_poll].events = POLLIN;
396 nr_poll++; 431 nr_poll++;
397 } 432 }
398 433
399 if (filter != NULL) { 434 if (filter != NULL) {
400 ret = ioctl(fd[nr_cpu][counter][thread_index], 435 ret = ioctl(FD(evsel, nr_cpu, thread_index),
401 PERF_EVENT_IOC_SET_FILTER, filter); 436 PERF_EVENT_IOC_SET_FILTER, filter);
402 if (ret) { 437 if (ret) {
403 error("failed to set filter with %d (%s)\n", errno, 438 error("failed to set filter with %d (%s)\n", errno,
404 strerror(errno)); 439 strerror(errno));
@@ -406,15 +441,19 @@ try_again:
406 } 441 }
407 } 442 }
408 } 443 }
444
445 if (!sample_type)
446 sample_type = attr->sample_type;
409} 447}
410 448
411static void open_counters(int cpu) 449static void open_counters(int cpu)
412{ 450{
413 int counter; 451 struct perf_evsel *pos;
414 452
415 group_fd = -1; 453 group_fd = -1;
416 for (counter = 0; counter < nr_counters; counter++) 454
417 create_counter(counter, cpu); 455 list_for_each_entry(pos, &evsel_list, node)
456 create_counter(pos, cpu);
418 457
419 nr_cpu++; 458 nr_cpu++;
420} 459}
@@ -437,7 +476,8 @@ static void atexit_header(void)
437 if (!pipe_output) { 476 if (!pipe_output) {
438 session->header.data_size += bytes_written; 477 session->header.data_size += bytes_written;
439 478
440 process_buildids(); 479 if (!no_buildid)
480 process_buildids();
441 perf_header__write(&session->header, output, true); 481 perf_header__write(&session->header, output, true);
442 perf_session__delete(session); 482 perf_session__delete(session);
443 symbol__exit(); 483 symbol__exit();
@@ -500,7 +540,7 @@ static void mmap_read_all(void)
500 540
501static int __cmd_record(int argc, const char **argv) 541static int __cmd_record(int argc, const char **argv)
502{ 542{
503 int i, counter; 543 int i;
504 struct stat st; 544 struct stat st;
505 int flags; 545 int flags;
506 int err; 546 int err;
@@ -552,19 +592,22 @@ static int __cmd_record(int argc, const char **argv)
552 } 592 }
553 593
554 session = perf_session__new(output_name, O_WRONLY, 594 session = perf_session__new(output_name, O_WRONLY,
555 write_mode == WRITE_FORCE, false); 595 write_mode == WRITE_FORCE, false, NULL);
556 if (session == NULL) { 596 if (session == NULL) {
557 pr_err("Not enough memory for reading perf file header\n"); 597 pr_err("Not enough memory for reading perf file header\n");
558 return -1; 598 return -1;
559 } 599 }
560 600
601 if (!no_buildid)
602 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
603
561 if (!file_new) { 604 if (!file_new) {
562 err = perf_header__read(session, output); 605 err = perf_header__read(session, output);
563 if (err < 0) 606 if (err < 0)
564 goto out_delete_session; 607 goto out_delete_session;
565 } 608 }
566 609
567 if (have_tracepoints(attrs, nr_counters)) 610 if (have_tracepoints(&evsel_list))
568 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 611 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
569 612
570 /* 613 /*
@@ -612,7 +655,7 @@ static int __cmd_record(int argc, const char **argv)
612 } 655 }
613 656
614 if (!system_wide && target_tid == -1 && target_pid == -1) 657 if (!system_wide && target_tid == -1 && target_pid == -1)
615 all_tids[0] = child_pid; 658 threads->map[0] = child_pid;
616 659
617 close(child_ready_pipe[1]); 660 close(child_ready_pipe[1]);
618 close(go_pipe[0]); 661 close(go_pipe[0]);
@@ -626,19 +669,15 @@ static int __cmd_record(int argc, const char **argv)
626 close(child_ready_pipe[0]); 669 close(child_ready_pipe[0]);
627 } 670 }
628 671
629 nr_cpus = read_cpu_map(cpu_list);
630 if (nr_cpus < 1) {
631 perror("failed to collect number of CPUs");
632 return -1;
633 }
634
635 if (!system_wide && no_inherit && !cpu_list) { 672 if (!system_wide && no_inherit && !cpu_list) {
636 open_counters(-1); 673 open_counters(-1);
637 } else { 674 } else {
638 for (i = 0; i < nr_cpus; i++) 675 for (i = 0; i < cpus->nr; i++)
639 open_counters(cpumap[i]); 676 open_counters(cpus->map[i]);
640 } 677 }
641 678
679 perf_session__set_sample_type(session, sample_type);
680
642 if (pipe_output) { 681 if (pipe_output) {
643 err = perf_header__write_pipe(output); 682 err = perf_header__write_pipe(output);
644 if (err < 0) 683 if (err < 0)
@@ -651,6 +690,8 @@ static int __cmd_record(int argc, const char **argv)
651 690
652 post_processing_offset = lseek(output, 0, SEEK_CUR); 691 post_processing_offset = lseek(output, 0, SEEK_CUR);
653 692
693 perf_session__set_sample_id_all(session, sample_id_all_avail);
694
654 if (pipe_output) { 695 if (pipe_output) {
655 err = event__synthesize_attrs(&session->header, 696 err = event__synthesize_attrs(&session->header,
656 process_synthesized_event, 697 process_synthesized_event,
@@ -667,7 +708,7 @@ static int __cmd_record(int argc, const char **argv)
667 return err; 708 return err;
668 } 709 }
669 710
670 if (have_tracepoints(attrs, nr_counters)) { 711 if (have_tracepoints(&evsel_list)) {
671 /* 712 /*
672 * FIXME err <= 0 here actually means that 713 * FIXME err <= 0 here actually means that
673 * there were no tracepoints so its not really 714 * there were no tracepoints so its not really
@@ -676,8 +717,7 @@ static int __cmd_record(int argc, const char **argv)
676 * return this more properly and also 717 * return this more properly and also
677 * propagate errors that now are calling die() 718 * propagate errors that now are calling die()
678 */ 719 */
679 err = event__synthesize_tracing_data(output, attrs, 720 err = event__synthesize_tracing_data(output, &evsel_list,
680 nr_counters,
681 process_synthesized_event, 721 process_synthesized_event,
682 session); 722 session);
683 if (err <= 0) { 723 if (err <= 0) {
@@ -751,13 +791,13 @@ static int __cmd_record(int argc, const char **argv)
751 791
752 if (done) { 792 if (done) {
753 for (i = 0; i < nr_cpu; i++) { 793 for (i = 0; i < nr_cpu; i++) {
754 for (counter = 0; 794 struct perf_evsel *pos;
755 counter < nr_counters; 795
756 counter++) { 796 list_for_each_entry(pos, &evsel_list, node) {
757 for (thread = 0; 797 for (thread = 0;
758 thread < thread_num; 798 thread < threads->nr;
759 thread++) 799 thread++)
760 ioctl(fd[i][counter][thread], 800 ioctl(FD(pos, i, thread),
761 PERF_EVENT_IOC_DISABLE); 801 PERF_EVENT_IOC_DISABLE);
762 } 802 }
763 } 803 }
@@ -831,16 +871,20 @@ const struct option record_options[] = {
831 "per thread counts"), 871 "per thread counts"),
832 OPT_BOOLEAN('d', "data", &sample_address, 872 OPT_BOOLEAN('d', "data", &sample_address,
833 "Sample addresses"), 873 "Sample addresses"),
874 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
834 OPT_BOOLEAN('n', "no-samples", &no_samples, 875 OPT_BOOLEAN('n', "no-samples", &no_samples,
835 "don't sample"), 876 "don't sample"),
836 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid, 877 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
837 "do not update the buildid cache"), 878 "do not update the buildid cache"),
879 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
880 "do not collect buildids in perf.data"),
838 OPT_END() 881 OPT_END()
839}; 882};
840 883
841int cmd_record(int argc, const char **argv, const char *prefix __used) 884int cmd_record(int argc, const char **argv, const char *prefix __used)
842{ 885{
843 int i, j, err = -ENOMEM; 886 int err = -ENOMEM;
887 struct perf_evsel *pos;
844 888
845 argc = parse_options(argc, argv, record_options, record_usage, 889 argc = parse_options(argc, argv, record_options, record_usage,
846 PARSE_OPT_STOP_AT_NON_OPTION); 890 PARSE_OPT_STOP_AT_NON_OPTION);
@@ -859,41 +903,36 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
859 } 903 }
860 904
861 symbol__init(); 905 symbol__init();
862 if (no_buildid) 906
907 if (no_buildid_cache || no_buildid)
863 disable_buildid_cache(); 908 disable_buildid_cache();
864 909
865 if (!nr_counters) { 910 if (list_empty(&evsel_list) && perf_evsel_list__create_default() < 0) {
866 nr_counters = 1; 911 pr_err("Not enough memory for event selector list\n");
867 attrs[0].type = PERF_TYPE_HARDWARE; 912 goto out_symbol_exit;
868 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
869 } 913 }
870 914
871 if (target_pid != -1) { 915 if (target_pid != -1)
872 target_tid = target_pid; 916 target_tid = target_pid;
873 thread_num = find_all_tid(target_pid, &all_tids);
874 if (thread_num <= 0) {
875 fprintf(stderr, "Can't find all threads of pid %d\n",
876 target_pid);
877 usage_with_options(record_usage, record_options);
878 }
879 } else {
880 all_tids=malloc(sizeof(pid_t));
881 if (!all_tids)
882 goto out_symbol_exit;
883 917
884 all_tids[0] = target_tid; 918 threads = thread_map__new(target_pid, target_tid);
885 thread_num = 1; 919 if (threads == NULL) {
920 pr_err("Problems finding threads of monitor\n");
921 usage_with_options(record_usage, record_options);
886 } 922 }
887 923
888 for (i = 0; i < MAX_NR_CPUS; i++) { 924 cpus = cpu_map__new(cpu_list);
889 for (j = 0; j < MAX_COUNTERS; j++) { 925 if (cpus == NULL) {
890 fd[i][j] = malloc(sizeof(int)*thread_num); 926 perror("failed to parse CPUs map");
891 if (!fd[i][j]) 927 return -1;
892 goto out_free_fd;
893 }
894 } 928 }
895 event_array = malloc( 929
896 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num); 930 list_for_each_entry(pos, &evsel_list, node) {
931 if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
932 goto out_free_fd;
933 }
934 event_array = malloc((sizeof(struct pollfd) * MAX_NR_CPUS *
935 MAX_COUNTERS * threads->nr));
897 if (!event_array) 936 if (!event_array)
898 goto out_free_fd; 937 goto out_free_fd;
899 938
@@ -920,12 +959,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
920out_free_event_array: 959out_free_event_array:
921 free(event_array); 960 free(event_array);
922out_free_fd: 961out_free_fd:
923 for (i = 0; i < MAX_NR_CPUS; i++) { 962 thread_map__delete(threads);
924 for (j = 0; j < MAX_COUNTERS; j++) 963 threads = NULL;
925 free(fd[i][j]);
926 }
927 free(all_tids);
928 all_tids = NULL;
929out_symbol_exit: 964out_symbol_exit:
930 symbol__exit(); 965 symbol__exit();
931 return err; 966 return err;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5de405d45230..75183a4518e6 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
@@ -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..abd4b8497bc4 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -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);
@@ -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
@@ -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 86cfe3800e6b..150a606002eb 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-script.c
@@ -56,29 +56,18 @@ static void setup_scripting(void)
56 56
57static int cleanup_scripting(void) 57static int cleanup_scripting(void)
58{ 58{
59 pr_debug("\nperf trace script stopped\n"); 59 pr_debug("\nperf script stopped\n");
60 60
61 return scripting_ops->stop_script(); 61 return scripting_ops->stop_script();
62} 62}
63 63
64static char const *input_name = "perf.data"; 64static char const *input_name = "perf.data";
65 65
66static 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)
67{ 68{
68 struct sample_data data; 69 struct thread *thread = perf_session__findnew(session, event->ip.pid);
69 struct thread *thread;
70 70
71 memset(&data, 0, sizeof(data));
72 data.time = -1;
73 data.cpu = -1;
74 data.period = 1;
75
76 event__parse_sample(event, session->sample_type, &data);
77
78 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
79 data.pid, data.tid, data.ip, data.period);
80
81 thread = perf_session__findnew(session, event->ip.pid);
82 if (thread == NULL) { 71 if (thread == NULL) {
83 pr_debug("problem processing %d event, skipping it.\n", 72 pr_debug("problem processing %d event, skipping it.\n",
84 event->header.type); 73 event->header.type);
@@ -87,13 +76,13 @@ static int process_sample_event(event_t *event, struct perf_session *session)
87 76
88 if (session->sample_type & PERF_SAMPLE_RAW) { 77 if (session->sample_type & PERF_SAMPLE_RAW) {
89 if (debug_mode) { 78 if (debug_mode) {
90 if (data.time < last_timestamp) { 79 if (sample->time < last_timestamp) {
91 pr_err("Samples misordered, previous: %llu " 80 pr_err("Samples misordered, previous: %llu "
92 "this: %llu\n", last_timestamp, 81 "this: %llu\n", last_timestamp,
93 data.time); 82 sample->time);
94 nr_unordered++; 83 nr_unordered++;
95 } 84 }
96 last_timestamp = data.time; 85 last_timestamp = sample->time;
97 return 0; 86 return 0;
98 } 87 }
99 /* 88 /*
@@ -101,21 +90,12 @@ static int process_sample_event(event_t *event, struct perf_session *session)
101 * field, although it should be the same than this perf 90 * field, although it should be the same than this perf
102 * event pid 91 * event pid
103 */ 92 */
104 scripting_ops->process_event(data.cpu, data.raw_data, 93 scripting_ops->process_event(sample->cpu, sample->raw_data,
105 data.raw_size, 94 sample->raw_size,
106 data.time, thread->comm); 95 sample->time, thread->comm);
107 } 96 }
108 97
109 session->hists.stats.total_period += data.period; 98 session->hists.stats.total_period += sample->period;
110 return 0;
111}
112
113static u64 nr_lost;
114
115static int process_lost_event(event_t *event, struct perf_session *session __used)
116{
117 nr_lost += event->lost.lost;
118
119 return 0; 99 return 0;
120} 100}
121 101
@@ -126,7 +106,7 @@ static struct perf_event_ops event_ops = {
126 .event_type = event__process_event_type, 106 .event_type = event__process_event_type,
127 .tracing_data = event__process_tracing_data, 107 .tracing_data = event__process_tracing_data,
128 .build_id = event__process_build_id, 108 .build_id = event__process_build_id,
129 .lost = process_lost_event, 109 .ordering_requires_timestamps = true,
130 .ordered_samples = true, 110 .ordered_samples = true,
131}; 111};
132 112
@@ -137,7 +117,7 @@ static void sig_handler(int sig __unused)
137 session_done = 1; 117 session_done = 1;
138} 118}
139 119
140static int __cmd_trace(struct perf_session *session) 120static int __cmd_script(struct perf_session *session)
141{ 121{
142 int ret; 122 int ret;
143 123
@@ -145,10 +125,8 @@ static int __cmd_trace(struct perf_session *session)
145 125
146 ret = perf_session__process_events(session, &event_ops); 126 ret = perf_session__process_events(session, &event_ops);
147 127
148 if (debug_mode) { 128 if (debug_mode)
149 pr_err("Misordered timestamps: %llu\n", nr_unordered); 129 pr_err("Misordered timestamps: %llu\n", nr_unordered);
150 pr_err("Lost events: %llu\n", nr_lost);
151 }
152 130
153 return ret; 131 return ret;
154} 132}
@@ -159,7 +137,7 @@ struct script_spec {
159 char spec[0]; 137 char spec[0];
160}; 138};
161 139
162LIST_HEAD(script_specs); 140static LIST_HEAD(script_specs);
163 141
164static struct script_spec *script_spec__new(const char *spec, 142static struct script_spec *script_spec__new(const char *spec,
165 struct scripting_ops *ops) 143 struct scripting_ops *ops)
@@ -247,7 +225,7 @@ static void list_available_languages(void)
247 225
248 fprintf(stderr, "\n"); 226 fprintf(stderr, "\n");
249 fprintf(stderr, "Scripting language extensions (used in " 227 fprintf(stderr, "Scripting language extensions (used in "
250 "perf trace -s [spec:]script.[spec]):\n\n"); 228 "perf script -s [spec:]script.[spec]):\n\n");
251 229
252 list_for_each_entry(s, &script_specs, node) 230 list_for_each_entry(s, &script_specs, node)
253 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name); 231 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name);
@@ -301,17 +279,34 @@ static int parse_scriptname(const struct option *opt __used,
301 return 0; 279 return 0;
302} 280}
303 281
304#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)\
305 while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \ 296 while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \
306 lang_next) \ 297 lang_next) \
307 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))) && \
308 (strcmp(lang_dirent.d_name, ".")) && \ 301 (strcmp(lang_dirent.d_name, ".")) && \
309 (strcmp(lang_dirent.d_name, ".."))) 302 (strcmp(lang_dirent.d_name, "..")))
310 303
311#define for_each_script(lang_dir, script_dirent, script_next) \ 304#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\
312 while (!readdir_r(lang_dir, &script_dirent, &script_next) && \ 305 while (!readdir_r(lang_dir, &script_dirent, &script_next) && \
313 script_next) \ 306 script_next) \
314 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)))
315 310
316 311
317#define RECORD_SUFFIX "-record" 312#define RECORD_SUFFIX "-record"
@@ -324,7 +319,7 @@ struct script_desc {
324 char *args; 319 char *args;
325}; 320};
326 321
327LIST_HEAD(script_descs); 322static LIST_HEAD(script_descs);
328 323
329static struct script_desc *script_desc__new(const char *name) 324static struct script_desc *script_desc__new(const char *name)
330{ 325{
@@ -380,10 +375,10 @@ out_delete_desc:
380 return NULL; 375 return NULL;
381} 376}
382 377
383static char *ends_with(char *str, const char *suffix) 378static const char *ends_with(const char *str, const char *suffix)
384{ 379{
385 size_t suffix_len = strlen(suffix); 380 size_t suffix_len = strlen(suffix);
386 char *p = str; 381 const char *p = str;
387 382
388 if (strlen(str) > suffix_len) { 383 if (strlen(str) > suffix_len) {
389 p = str + strlen(str) - suffix_len; 384 p = str + strlen(str) - suffix_len;
@@ -466,16 +461,16 @@ static int list_available_scripts(const struct option *opt __used,
466 if (!scripts_dir) 461 if (!scripts_dir)
467 return -1; 462 return -1;
468 463
469 for_each_lang(scripts_dir, lang_dirent, lang_next) { 464 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
470 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 465 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
471 lang_dirent.d_name); 466 lang_dirent.d_name);
472 lang_dir = opendir(lang_path); 467 lang_dir = opendir(lang_path);
473 if (!lang_dir) 468 if (!lang_dir)
474 continue; 469 continue;
475 470
476 for_each_script(lang_dir, script_dirent, script_next) { 471 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
477 script_root = strdup(script_dirent.d_name); 472 script_root = strdup(script_dirent.d_name);
478 str = ends_with(script_root, REPORT_SUFFIX); 473 str = (char *)ends_with(script_root, REPORT_SUFFIX);
479 if (str) { 474 if (str) {
480 *str = '\0'; 475 *str = '\0';
481 desc = script_desc__findnew(script_root); 476 desc = script_desc__findnew(script_root);
@@ -514,16 +509,16 @@ static char *get_script_path(const char *script_root, const char *suffix)
514 if (!scripts_dir) 509 if (!scripts_dir)
515 return NULL; 510 return NULL;
516 511
517 for_each_lang(scripts_dir, lang_dirent, lang_next) { 512 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
518 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 513 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
519 lang_dirent.d_name); 514 lang_dirent.d_name);
520 lang_dir = opendir(lang_path); 515 lang_dir = opendir(lang_path);
521 if (!lang_dir) 516 if (!lang_dir)
522 continue; 517 continue;
523 518
524 for_each_script(lang_dir, script_dirent, script_next) { 519 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
525 __script_root = strdup(script_dirent.d_name); 520 __script_root = strdup(script_dirent.d_name);
526 str = ends_with(__script_root, suffix); 521 str = (char *)ends_with(__script_root, suffix);
527 if (str) { 522 if (str) {
528 *str = '\0'; 523 *str = '\0';
529 if (strcmp(__script_root, script_root)) 524 if (strcmp(__script_root, script_root))
@@ -543,7 +538,7 @@ static char *get_script_path(const char *script_root, const char *suffix)
543 538
544static bool is_top_script(const char *script_path) 539static bool is_top_script(const char *script_path)
545{ 540{
546 return ends_with((char *)script_path, "top") == NULL ? false : true; 541 return ends_with(script_path, "top") == NULL ? false : true;
547} 542}
548 543
549static int has_required_arg(char *script_path) 544static int has_required_arg(char *script_path)
@@ -569,12 +564,12 @@ out:
569 return n_args; 564 return n_args;
570} 565}
571 566
572static const char * const trace_usage[] = { 567static const char * const script_usage[] = {
573 "perf trace [<options>]", 568 "perf script [<options>]",
574 "perf trace [<options>] record <script> [<record-options>] <command>", 569 "perf script [<options>] record <script> [<record-options>] <command>",
575 "perf trace [<options>] report <script> [script-args]", 570 "perf script [<options>] report <script> [script-args]",
576 "perf trace [<options>] <script> [<record-options>] <command>", 571 "perf script [<options>] <script> [<record-options>] <command>",
577 "perf trace [<options>] <top-script> [script-args]", 572 "perf script [<options>] <top-script> [script-args]",
578 NULL 573 NULL
579}; 574};
580 575
@@ -591,7 +586,7 @@ static const struct option options[] = {
591 "script file name (lang:script name, script name, or *)", 586 "script file name (lang:script name, script name, or *)",
592 parse_scriptname), 587 parse_scriptname),
593 OPT_STRING('g', "gen-script", &generate_script_lang, "lang", 588 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
594 "generate perf-trace.xx script in specified language"), 589 "generate perf-script.xx script in specified language"),
595 OPT_STRING('i', "input", &input_name, "file", 590 OPT_STRING('i', "input", &input_name, "file",
596 "input file name"), 591 "input file name"),
597 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 592 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
@@ -614,7 +609,7 @@ static bool have_cmd(int argc, const char **argv)
614 return argc != 0; 609 return argc != 0;
615} 610}
616 611
617int cmd_trace(int argc, const char **argv, const char *prefix __used) 612int cmd_script(int argc, const char **argv, const char *prefix __used)
618{ 613{
619 char *rec_script_path = NULL; 614 char *rec_script_path = NULL;
620 char *rep_script_path = NULL; 615 char *rep_script_path = NULL;
@@ -626,7 +621,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
626 621
627 setup_scripting(); 622 setup_scripting();
628 623
629 argc = parse_options(argc, argv, options, trace_usage, 624 argc = parse_options(argc, argv, options, script_usage,
630 PARSE_OPT_STOP_AT_NON_OPTION); 625 PARSE_OPT_STOP_AT_NON_OPTION);
631 626
632 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 627 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
@@ -640,7 +635,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
640 if (!rep_script_path) { 635 if (!rep_script_path) {
641 fprintf(stderr, 636 fprintf(stderr,
642 "Please specify a valid report script" 637 "Please specify a valid report script"
643 "(see 'perf trace -l' for listing)\n"); 638 "(see 'perf script -l' for listing)\n");
644 return -1; 639 return -1;
645 } 640 }
646 } 641 }
@@ -658,8 +653,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
658 653
659 if (!rec_script_path && !rep_script_path) { 654 if (!rec_script_path && !rep_script_path) {
660 fprintf(stderr, " Couldn't find script %s\n\n See perf" 655 fprintf(stderr, " Couldn't find script %s\n\n See perf"
661 " trace -l for available scripts.\n", argv[0]); 656 " script -l for available scripts.\n", argv[0]);
662 usage_with_options(trace_usage, options); 657 usage_with_options(script_usage, options);
663 } 658 }
664 659
665 if (is_top_script(argv[0])) { 660 if (is_top_script(argv[0])) {
@@ -671,9 +666,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
671 rec_args = (argc - 1) - rep_args; 666 rec_args = (argc - 1) - rep_args;
672 if (rec_args < 0) { 667 if (rec_args < 0) {
673 fprintf(stderr, " %s script requires options." 668 fprintf(stderr, " %s script requires options."
674 "\n\n See perf trace -l for available " 669 "\n\n See perf script -l for available "
675 "scripts and options.\n", argv[0]); 670 "scripts and options.\n", argv[0]);
676 usage_with_options(trace_usage, options); 671 usage_with_options(script_usage, options);
677 } 672 }
678 } 673 }
679 674
@@ -772,7 +767,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
772 if (!script_name) 767 if (!script_name)
773 setup_pager(); 768 setup_pager();
774 769
775 session = perf_session__new(input_name, O_RDONLY, 0, false); 770 session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
776 if (session == NULL) 771 if (session == NULL)
777 return -ENOMEM; 772 return -ENOMEM;
778 773
@@ -806,7 +801,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
806 return -1; 801 return -1;
807 } 802 }
808 803
809 err = scripting_ops->generate_script("perf-trace"); 804 err = scripting_ops->generate_script("perf-script");
810 goto out; 805 goto out;
811 } 806 }
812 807
@@ -814,10 +809,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
814 err = scripting_ops->start_script(script_name, argc, argv); 809 err = scripting_ops->start_script(script_name, argc, argv);
815 if (err) 810 if (err)
816 goto out; 811 goto out;
817 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);
818 } 813 }
819 814
820 err = __cmd_trace(session); 815 err = __cmd_script(session);
821 816
822 perf_session__delete(session); 817 perf_session__delete(session);
823 cleanup_scripting(); 818 cleanup_scripting();
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a6b4d44f9502..c385a63ebfd1 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,55 +191,19 @@ 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
217 count[0] = count[1] = count[2] = 0;
218
219 nv = scale ? 3 : 1;
220 for (cpu = 0; cpu < nr_cpus; cpu++) {
221 for (thread = 0; thread < thread_num; thread++) {
222 if (fd[cpu][counter][thread] < 0)
223 continue;
224
225 res = read(fd[cpu][counter][thread],
226 single_count, nv * sizeof(u64));
227 assert(res == nv * sizeof(u64));
228
229 close(fd[cpu][counter][thread]);
230 fd[cpu][counter][thread] = -1;
231
232 count[0] += single_count[0];
233 if (scale) {
234 count[1] += single_count[1];
235 count[2] += single_count[2];
236 }
237 }
238 }
239
240 scaled = 0;
241 if (scale) {
242 if (count[2] == 0) {
243 event_scaled[counter] = -1;
244 count[0] = 0;
245 return;
246 }
247 201
248 if (count[2] < count[1]) { 202 if (__perf_evsel__read(counter, cpus->nr, threads->nr, scale) < 0)
249 event_scaled[counter] = 1; 203 return -1;
250 count[0] = (unsigned long long)
251 ((double)count[0] * count[1] / count[2] + 0.5);
252 }
253 }
254 204
255 for (i = 0; i < 3; i++) 205 for (i = 0; i < 3; i++)
256 update_stats(&event_res_stats[counter][i], count[i]); 206 update_stats(&ps->res_stats[i], count[i]);
257 207
258 if (verbose) { 208 if (verbose) {
259 fprintf(stderr, "%s: %Ld %Ld %Ld\n", event_name(counter), 209 fprintf(stderr, "%s: %Ld %Ld %Ld\n", event_name(counter),
@@ -263,26 +213,51 @@ static void read_counter(int counter)
263 /* 213 /*
264 * Save the full runtime - to allow normalization during printout: 214 * Save the full runtime - to allow normalization during printout:
265 */ 215 */
266 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) 216 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
267 update_stats(&runtime_nsecs_stats, count[0]); 217 update_stats(&runtime_nsecs_stats[0], count[0]);
268 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter)) 218 if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
269 update_stats(&runtime_cycles_stats, count[0]); 219 update_stats(&runtime_cycles_stats[0], count[0]);
270 if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter)) 220 if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
271 update_stats(&runtime_branches_stats, count[0]); 221 update_stats(&runtime_branches_stats[0], count[0]);
222
223 return 0;
224}
225
226/*
227 * Read out the results of a single counter:
228 * do not aggregate counts across CPUs in system-wide mode
229 */
230static int read_counter(struct perf_evsel *counter)
231{
232 u64 *count;
233 int cpu;
234
235 for (cpu = 0; cpu < cpus->nr; cpu++) {
236 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
237 return -1;
238
239 count = counter->counts->cpu[cpu].values;
240
241 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
242 update_stats(&runtime_nsecs_stats[cpu], count[0]);
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]);
247 }
248
249 return 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";
383 381
384 fprintf(stderr, " %18.6f %-24s", msecs, event_name(counter)); 382 if (no_aggr)
383 sprintf(cpustr, "CPU%*d%s",
384 csv_output ? 0 : -4,
385 cpus->map[cpu], csv_sep);
386
387 fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
388
389 if (csv_output)
390 return;
385 391
386 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { 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;
402
403 if (csv_output)
404 fmt = "%s%.0f%s%s";
405 else if (big_num)
406 fmt = "%s%'18.0f%s%-24s";
407 else
408 fmt = "%s%18.0f%s%-24s";
395 409
396 if (big_num) 410 if (no_aggr)
397 fprintf(stderr, " %'18.0f %-24s", avg, event_name(counter)); 411 sprintf(cpustr, "CPU%*d%s",
412 csv_output ? 0 : -4,
413 cpus->map[cpu], csv_sep);
398 else 414 else
399 fprintf(stderr, " %18.0f %-24s", avg, event_name(counter)); 415 cpu = 0;
416
417 fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
400 418
401 if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { 419 if (csv_output)
402 total = avg_stats(&runtime_cycles_stats); 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,11 @@ 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);
746out:
747 thread_map__delete(threads);
748 threads = NULL;
625 return status; 749 return status;
626} 750}
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 035b9fa063a9..ed5696198d3d 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:
@@ -143,8 +149,10 @@ next_pair:
143 pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\n", 149 pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\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,6 +161,13 @@ next_pair:
153 goto next_pair; 161 goto next_pair;
154 } 162 }
155 } 163 }
164
165 if (backwards) {
166 backwards = false;
167 pair = first_pair;
168 goto detour;
169 }
170
156 pr_debug("%#Lx: diff name v: %s k: %s\n", 171 pr_debug("%#Lx: diff name v: %s k: %s\n",
157 sym->start, sym->name, pair->name); 172 sym->start, sym->name, pair->name);
158 } 173 }
@@ -219,6 +234,199 @@ 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 %Ld\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 size_t cpu_set_size;
337 int id = trace_event__id("sys_enter_open");
338
339 if (id < 0) {
340 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
341 return -1;
342 }
343
344 threads = thread_map__new(-1, getpid());
345 if (threads == NULL) {
346 pr_debug("thread_map__new\n");
347 return -1;
348 }
349
350 cpus = cpu_map__new(NULL);
351 if (threads == NULL) {
352 pr_debug("thread_map__new\n");
353 return -1;
354 }
355
356 cpu_set = CPU_ALLOC(cpus->nr);
357
358 if (cpu_set == NULL)
359 goto out_thread_map_delete;
360
361 cpu_set_size = CPU_ALLOC_SIZE(cpus->nr);
362 CPU_ZERO_S(cpu_set_size, cpu_set);
363
364 memset(&attr, 0, sizeof(attr));
365 attr.type = PERF_TYPE_TRACEPOINT;
366 attr.config = id;
367 evsel = perf_evsel__new(&attr, 0);
368 if (evsel == NULL) {
369 pr_debug("perf_evsel__new\n");
370 goto out_cpu_free;
371 }
372
373 if (perf_evsel__open(evsel, cpus, threads) < 0) {
374 pr_debug("failed to open counter: %s, "
375 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
376 strerror(errno));
377 goto out_evsel_delete;
378 }
379
380 for (cpu = 0; cpu < cpus->nr; ++cpu) {
381 unsigned int ncalls = nr_open_calls + cpu;
382
383 CPU_SET(cpu, cpu_set);
384 sched_setaffinity(0, cpu_set_size, cpu_set);
385 for (i = 0; i < ncalls; ++i) {
386 fd = open("/etc/passwd", O_RDONLY);
387 close(fd);
388 }
389 CPU_CLR(cpu, cpu_set);
390 }
391
392 /*
393 * Here we need to explicitely preallocate the counts, as if
394 * we use the auto allocation it will allocate just for 1 cpu,
395 * as we start by cpu 0.
396 */
397 if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) {
398 pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
399 goto out_close_fd;
400 }
401
402 for (cpu = 0; cpu < cpus->nr; ++cpu) {
403 unsigned int expected;
404
405 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
406 pr_debug("perf_evsel__open_read_on_cpu\n");
407 goto out_close_fd;
408 }
409
410 expected = nr_open_calls + cpu;
411 if (evsel->counts->cpu[cpu].val != expected) {
412 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %Ld\n",
413 expected, cpu, evsel->counts->cpu[cpu].val);
414 goto out_close_fd;
415 }
416 }
417
418 err = 0;
419out_close_fd:
420 perf_evsel__close_fd(evsel, 1, threads->nr);
421out_evsel_delete:
422 perf_evsel__delete(evsel);
423out_cpu_free:
424 CPU_FREE(cpu_set);
425out_thread_map_delete:
426 thread_map__delete(threads);
427 return err;
428}
429
222static struct test { 430static struct test {
223 const char *desc; 431 const char *desc;
224 int (*func)(void); 432 int (*func)(void);
@@ -228,6 +436,14 @@ static struct test {
228 .func = test__vmlinux_matches_kallsyms, 436 .func = test__vmlinux_matches_kallsyms,
229 }, 437 },
230 { 438 {
439 .desc = "detect open syscall event",
440 .func = test__open_syscall_event,
441 },
442 {
443 .desc = "detect open syscall event on all cpus",
444 .func = test__open_syscall_event_on_all_cpus,
445 },
446 {
231 .func = NULL, 447 .func = NULL,
232 }, 448 },
233}; 449};
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 dd625808c2a5..6ce4042421bd 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
@@ -55,7 +57,7 @@
55#include <linux/unistd.h> 57#include <linux/unistd.h>
56#include <linux/types.h> 58#include <linux/types.h>
57 59
58static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; 60#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
59 61
60static bool system_wide = false; 62static bool system_wide = false;
61 63
@@ -66,10 +68,9 @@ static int print_entries;
66 68
67static int target_pid = -1; 69static int target_pid = -1;
68static int target_tid = -1; 70static int target_tid = -1;
69static pid_t *all_tids = NULL; 71static struct thread_map *threads;
70static int thread_num = 0;
71static bool inherit = false; 72static bool inherit = false;
72static int nr_cpus = 0; 73static struct cpu_map *cpus;
73static int realtime_prio = 0; 74static int realtime_prio = 0;
74static bool group = false; 75static bool group = false;
75static unsigned int page_size; 76static unsigned int page_size;
@@ -100,6 +101,7 @@ struct sym_entry *sym_filter_entry = NULL;
100struct sym_entry *sym_filter_entry_sched = NULL; 101struct sym_entry *sym_filter_entry_sched = NULL;
101static int sym_pcnt_filter = 5; 102static int sym_pcnt_filter = 5;
102static int sym_counter = 0; 103static int sym_counter = 0;
104static struct perf_evsel *sym_evsel = NULL;
103static int display_weighted = -1; 105static int display_weighted = -1;
104static const char *cpu_list; 106static const char *cpu_list;
105 107
@@ -353,7 +355,7 @@ static void show_details(struct sym_entry *syme)
353 return; 355 return;
354 356
355 symbol = sym_entry__symbol(syme); 357 symbol = sym_entry__symbol(syme);
356 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name); 358 printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name);
357 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 359 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
358 360
359 pthread_mutex_lock(&syme->src->lock); 361 pthread_mutex_lock(&syme->src->lock);
@@ -460,7 +462,8 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
460static void print_sym_table(void) 462static void print_sym_table(void)
461{ 463{
462 int printed = 0, j; 464 int printed = 0, j;
463 int counter, snap = !display_weighted ? sym_counter : 0; 465 struct perf_evsel *counter;
466 int snap = !display_weighted ? sym_counter : 0;
464 float samples_per_sec = samples/delay_secs; 467 float samples_per_sec = samples/delay_secs;
465 float ksamples_per_sec = kernel_samples/delay_secs; 468 float ksamples_per_sec = kernel_samples/delay_secs;
466 float us_samples_per_sec = (us_samples)/delay_secs; 469 float us_samples_per_sec = (us_samples)/delay_secs;
@@ -532,7 +535,9 @@ static void print_sym_table(void)
532 } 535 }
533 536
534 if (nr_counters == 1 || !display_weighted) { 537 if (nr_counters == 1 || !display_weighted) {
535 printf("%Ld", (u64)attrs[0].sample_period); 538 struct perf_evsel *first;
539 first = list_entry(evsel_list.next, struct perf_evsel, node);
540 printf("%Ld", first->attr.sample_period);
536 if (freq) 541 if (freq)
537 printf("Hz "); 542 printf("Hz ");
538 else 543 else
@@ -540,9 +545,9 @@ static void print_sym_table(void)
540 } 545 }
541 546
542 if (!display_weighted) 547 if (!display_weighted)
543 printf("%s", event_name(sym_counter)); 548 printf("%s", event_name(sym_evsel));
544 else for (counter = 0; counter < nr_counters; counter++) { 549 else list_for_each_entry(counter, &evsel_list, node) {
545 if (counter) 550 if (counter->idx)
546 printf("/"); 551 printf("/");
547 552
548 printf("%s", event_name(counter)); 553 printf("%s", event_name(counter));
@@ -558,12 +563,12 @@ static void print_sym_table(void)
558 printf(" (all"); 563 printf(" (all");
559 564
560 if (cpu_list) 565 if (cpu_list)
561 printf(", CPU%s: %s)\n", nr_cpus > 1 ? "s" : "", cpu_list); 566 printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
562 else { 567 else {
563 if (target_tid != -1) 568 if (target_tid != -1)
564 printf(")\n"); 569 printf(")\n");
565 else 570 else
566 printf(", %d CPU%s)\n", nr_cpus, nr_cpus > 1 ? "s" : ""); 571 printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
567 } 572 }
568 573
569 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 574 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
@@ -739,7 +744,7 @@ static void print_mapped_keys(void)
739 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); 744 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
740 745
741 if (nr_counters > 1) 746 if (nr_counters > 1)
742 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter)); 747 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel));
743 748
744 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 749 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
745 750
@@ -826,19 +831,23 @@ static void handle_keypress(struct perf_session *session, int c)
826 break; 831 break;
827 case 'E': 832 case 'E':
828 if (nr_counters > 1) { 833 if (nr_counters > 1) {
829 int i;
830
831 fprintf(stderr, "\nAvailable events:"); 834 fprintf(stderr, "\nAvailable events:");
832 for (i = 0; i < nr_counters; i++) 835
833 fprintf(stderr, "\n\t%d %s", i, event_name(i)); 836 list_for_each_entry(sym_evsel, &evsel_list, node)
837 fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
834 838
835 prompt_integer(&sym_counter, "Enter details event counter"); 839 prompt_integer(&sym_counter, "Enter details event counter");
836 840
837 if (sym_counter >= nr_counters) { 841 if (sym_counter >= nr_counters) {
838 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(0)); 842 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
839 sym_counter = 0; 843 sym_counter = 0;
844 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
840 sleep(1); 845 sleep(1);
846 break;
841 } 847 }
848 list_for_each_entry(sym_evsel, &evsel_list, node)
849 if (sym_evsel->idx == sym_counter)
850 break;
842 } else sym_counter = 0; 851 } else sym_counter = 0;
843 break; 852 break;
844 case 'f': 853 case 'f':
@@ -977,12 +986,13 @@ static int symbol_filter(struct map *map, struct symbol *sym)
977} 986}
978 987
979static void event__process_sample(const event_t *self, 988static void event__process_sample(const event_t *self,
980 struct perf_session *session, int counter) 989 struct sample_data *sample,
990 struct perf_session *session,
991 struct perf_evsel *evsel)
981{ 992{
982 u64 ip = self->ip.ip; 993 u64 ip = self->ip.ip;
983 struct sym_entry *syme; 994 struct sym_entry *syme;
984 struct addr_location al; 995 struct addr_location al;
985 struct sample_data data;
986 struct machine *machine; 996 struct machine *machine;
987 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 997 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
988 998
@@ -1025,7 +1035,7 @@ static void event__process_sample(const event_t *self,
1025 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) 1035 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
1026 exact_samples++; 1036 exact_samples++;
1027 1037
1028 if (event__preprocess_sample(self, session, &al, &data, 1038 if (event__preprocess_sample(self, session, &al, sample,
1029 symbol_filter) < 0 || 1039 symbol_filter) < 0 ||
1030 al.filtered) 1040 al.filtered)
1031 return; 1041 return;
@@ -1071,9 +1081,9 @@ static void event__process_sample(const event_t *self,
1071 1081
1072 syme = symbol__priv(al.sym); 1082 syme = symbol__priv(al.sym);
1073 if (!syme->skip) { 1083 if (!syme->skip) {
1074 syme->count[counter]++; 1084 syme->count[evsel->idx]++;
1075 syme->origin = origin; 1085 syme->origin = origin;
1076 record_precise_ip(syme, counter, ip); 1086 record_precise_ip(syme, evsel->idx, ip);
1077 pthread_mutex_lock(&active_symbols_lock); 1087 pthread_mutex_lock(&active_symbols_lock);
1078 if (list_empty(&syme->node) || !syme->node.next) 1088 if (list_empty(&syme->node) || !syme->node.next)
1079 __list_insert_active_sym(syme); 1089 __list_insert_active_sym(syme);
@@ -1082,12 +1092,24 @@ static void event__process_sample(const event_t *self,
1082} 1092}
1083 1093
1084struct mmap_data { 1094struct mmap_data {
1085 int counter;
1086 void *base; 1095 void *base;
1087 int mask; 1096 int mask;
1088 unsigned int prev; 1097 unsigned int prev;
1089}; 1098};
1090 1099
1100static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel,
1101 int ncpus, int nthreads)
1102{
1103 evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data));
1104 return evsel->priv != NULL ? 0 : -ENOMEM;
1105}
1106
1107static void perf_evsel__free_mmap(struct perf_evsel *evsel)
1108{
1109 xyarray__delete(evsel->priv);
1110 evsel->priv = NULL;
1111}
1112
1091static unsigned int mmap_read_head(struct mmap_data *md) 1113static unsigned int mmap_read_head(struct mmap_data *md)
1092{ 1114{
1093 struct perf_event_mmap_page *pc = md->base; 1115 struct perf_event_mmap_page *pc = md->base;
@@ -1100,11 +1122,15 @@ static unsigned int mmap_read_head(struct mmap_data *md)
1100} 1122}
1101 1123
1102static void perf_session__mmap_read_counter(struct perf_session *self, 1124static void perf_session__mmap_read_counter(struct perf_session *self,
1103 struct mmap_data *md) 1125 struct perf_evsel *evsel,
1126 int cpu, int thread_idx)
1104{ 1127{
1128 struct xyarray *mmap_array = evsel->priv;
1129 struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx);
1105 unsigned int head = mmap_read_head(md); 1130 unsigned int head = mmap_read_head(md);
1106 unsigned int old = md->prev; 1131 unsigned int old = md->prev;
1107 unsigned char *data = md->base + page_size; 1132 unsigned char *data = md->base + page_size;
1133 struct sample_data sample;
1108 int diff; 1134 int diff;
1109 1135
1110 /* 1136 /*
@@ -1152,10 +1178,11 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1152 event = &event_copy; 1178 event = &event_copy;
1153 } 1179 }
1154 1180
1181 event__parse_sample(event, self, &sample);
1155 if (event->header.type == PERF_RECORD_SAMPLE) 1182 if (event->header.type == PERF_RECORD_SAMPLE)
1156 event__process_sample(event, self, md->counter); 1183 event__process_sample(event, &sample, self, evsel);
1157 else 1184 else
1158 event__process(event, self); 1185 event__process(event, &sample, self);
1159 old += size; 1186 old += size;
1160 } 1187 }
1161 1188
@@ -1163,36 +1190,39 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1163} 1190}
1164 1191
1165static struct pollfd *event_array; 1192static struct pollfd *event_array;
1166static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
1167 1193
1168static void perf_session__mmap_read(struct perf_session *self) 1194static void perf_session__mmap_read(struct perf_session *self)
1169{ 1195{
1170 int i, counter, thread_index; 1196 struct perf_evsel *counter;
1197 int i, thread_index;
1171 1198
1172 for (i = 0; i < nr_cpus; i++) { 1199 for (i = 0; i < cpus->nr; i++) {
1173 for (counter = 0; counter < nr_counters; counter++) 1200 list_for_each_entry(counter, &evsel_list, node) {
1174 for (thread_index = 0; 1201 for (thread_index = 0;
1175 thread_index < thread_num; 1202 thread_index < threads->nr;
1176 thread_index++) { 1203 thread_index++) {
1177 perf_session__mmap_read_counter(self, 1204 perf_session__mmap_read_counter(self,
1178 &mmap_array[i][counter][thread_index]); 1205 counter, i, thread_index);
1179 } 1206 }
1207 }
1180 } 1208 }
1181} 1209}
1182 1210
1183int nr_poll; 1211int nr_poll;
1184int group_fd; 1212int group_fd;
1185 1213
1186static void start_counter(int i, int counter) 1214static void start_counter(int i, struct perf_evsel *evsel)
1187{ 1215{
1216 struct xyarray *mmap_array = evsel->priv;
1217 struct mmap_data *mm;
1188 struct perf_event_attr *attr; 1218 struct perf_event_attr *attr;
1189 int cpu = -1; 1219 int cpu = -1;
1190 int thread_index; 1220 int thread_index;
1191 1221
1192 if (target_tid == -1) 1222 if (target_tid == -1)
1193 cpu = cpumap[i]; 1223 cpu = cpus->map[i];
1194 1224
1195 attr = attrs + counter; 1225 attr = &evsel->attr;
1196 1226
1197 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1227 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1198 1228
@@ -1205,16 +1235,20 @@ static void start_counter(int i, int counter)
1205 attr->inherit = (cpu < 0) && inherit; 1235 attr->inherit = (cpu < 0) && inherit;
1206 attr->mmap = 1; 1236 attr->mmap = 1;
1207 1237
1208 for (thread_index = 0; thread_index < thread_num; thread_index++) { 1238 for (thread_index = 0; thread_index < threads->nr; thread_index++) {
1209try_again: 1239try_again:
1210 fd[i][counter][thread_index] = sys_perf_event_open(attr, 1240 FD(evsel, i, thread_index) = sys_perf_event_open(attr,
1211 all_tids[thread_index], cpu, group_fd, 0); 1241 threads->map[thread_index], cpu, group_fd, 0);
1212 1242
1213 if (fd[i][counter][thread_index] < 0) { 1243 if (FD(evsel, i, thread_index) < 0) {
1214 int err = errno; 1244 int err = errno;
1215 1245
1216 if (err == EPERM || err == EACCES) 1246 if (err == EPERM || err == EACCES)
1217 die("No permission - are you root?\n"); 1247 die("Permission error - are you root?\n"
1248 "\t Consider tweaking"
1249 " /proc/sys/kernel/perf_event_paranoid.\n");
1250 if (err == ENOENT)
1251 die("%s event is not supported. ", event_name(evsel));
1218 /* 1252 /*
1219 * If it's cycles then fall back to hrtimer 1253 * If it's cycles then fall back to hrtimer
1220 * based cpu-clock-tick sw counter, which 1254 * based cpu-clock-tick sw counter, which
@@ -1231,30 +1265,30 @@ try_again:
1231 goto try_again; 1265 goto try_again;
1232 } 1266 }
1233 printf("\n"); 1267 printf("\n");
1234 error("perfcounter syscall returned with %d (%s)\n", 1268 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
1235 fd[i][counter][thread_index], strerror(err)); 1269 FD(evsel, i, thread_index), strerror(err));
1236 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 1270 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
1237 exit(-1); 1271 exit(-1);
1238 } 1272 }
1239 assert(fd[i][counter][thread_index] >= 0); 1273 assert(FD(evsel, i, thread_index) >= 0);
1240 fcntl(fd[i][counter][thread_index], F_SETFL, O_NONBLOCK); 1274 fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
1241 1275
1242 /* 1276 /*
1243 * First counter acts as the group leader: 1277 * First counter acts as the group leader:
1244 */ 1278 */
1245 if (group && group_fd == -1) 1279 if (group && group_fd == -1)
1246 group_fd = fd[i][counter][thread_index]; 1280 group_fd = FD(evsel, i, thread_index);
1247 1281
1248 event_array[nr_poll].fd = fd[i][counter][thread_index]; 1282 event_array[nr_poll].fd = FD(evsel, i, thread_index);
1249 event_array[nr_poll].events = POLLIN; 1283 event_array[nr_poll].events = POLLIN;
1250 nr_poll++; 1284 nr_poll++;
1251 1285
1252 mmap_array[i][counter][thread_index].counter = counter; 1286 mm = xyarray__entry(mmap_array, i, thread_index);
1253 mmap_array[i][counter][thread_index].prev = 0; 1287 mm->prev = 0;
1254 mmap_array[i][counter][thread_index].mask = mmap_pages*page_size - 1; 1288 mm->mask = mmap_pages*page_size - 1;
1255 mmap_array[i][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size, 1289 mm->base = mmap(NULL, (mmap_pages+1)*page_size,
1256 PROT_READ, MAP_SHARED, fd[i][counter][thread_index], 0); 1290 PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
1257 if (mmap_array[i][counter][thread_index].base == MAP_FAILED) 1291 if (mm->base == MAP_FAILED)
1258 die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 1292 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1259 } 1293 }
1260} 1294}
@@ -1262,13 +1296,13 @@ try_again:
1262static int __cmd_top(void) 1296static int __cmd_top(void)
1263{ 1297{
1264 pthread_t thread; 1298 pthread_t thread;
1265 int i, counter; 1299 struct perf_evsel *counter;
1266 int ret; 1300 int i, ret;
1267 /* 1301 /*
1268 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1302 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1269 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1303 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
1270 */ 1304 */
1271 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false); 1305 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
1272 if (session == NULL) 1306 if (session == NULL)
1273 return -ENOMEM; 1307 return -ENOMEM;
1274 1308
@@ -1277,9 +1311,9 @@ static int __cmd_top(void)
1277 else 1311 else
1278 event__synthesize_threads(event__process, session); 1312 event__synthesize_threads(event__process, session);
1279 1313
1280 for (i = 0; i < nr_cpus; i++) { 1314 for (i = 0; i < cpus->nr; i++) {
1281 group_fd = -1; 1315 group_fd = -1;
1282 for (counter = 0; counter < nr_counters; counter++) 1316 list_for_each_entry(counter, &evsel_list, node)
1283 start_counter(i, counter); 1317 start_counter(i, counter);
1284 } 1318 }
1285 1319
@@ -1368,8 +1402,8 @@ static const struct option options[] = {
1368 1402
1369int cmd_top(int argc, const char **argv, const char *prefix __used) 1403int cmd_top(int argc, const char **argv, const char *prefix __used)
1370{ 1404{
1371 int counter; 1405 struct perf_evsel *pos;
1372 int i,j; 1406 int status = -ENOMEM;
1373 1407
1374 page_size = sysconf(_SC_PAGE_SIZE); 1408 page_size = sysconf(_SC_PAGE_SIZE);
1375 1409
@@ -1377,34 +1411,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1377 if (argc) 1411 if (argc)
1378 usage_with_options(top_usage, options); 1412 usage_with_options(top_usage, options);
1379 1413
1380 if (target_pid != -1) { 1414 if (target_pid != -1)
1381 target_tid = target_pid; 1415 target_tid = target_pid;
1382 thread_num = find_all_tid(target_pid, &all_tids);
1383 if (thread_num <= 0) {
1384 fprintf(stderr, "Can't find all threads of pid %d\n",
1385 target_pid);
1386 usage_with_options(top_usage, options);
1387 }
1388 } else {
1389 all_tids=malloc(sizeof(pid_t));
1390 if (!all_tids)
1391 return -ENOMEM;
1392 1416
1393 all_tids[0] = target_tid; 1417 threads = thread_map__new(target_pid, target_tid);
1394 thread_num = 1; 1418 if (threads == NULL) {
1419 pr_err("Problems finding threads of monitor\n");
1420 usage_with_options(top_usage, options);
1395 } 1421 }
1396 1422
1397 for (i = 0; i < MAX_NR_CPUS; i++) { 1423 event_array = malloc((sizeof(struct pollfd) *
1398 for (j = 0; j < MAX_COUNTERS; j++) { 1424 MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
1399 fd[i][j] = malloc(sizeof(int)*thread_num);
1400 mmap_array[i][j] = zalloc(
1401 sizeof(struct mmap_data)*thread_num);
1402 if (!fd[i][j] || !mmap_array[i][j])
1403 return -ENOMEM;
1404 }
1405 }
1406 event_array = malloc(
1407 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
1408 if (!event_array) 1425 if (!event_array)
1409 return -ENOMEM; 1426 return -ENOMEM;
1410 1427
@@ -1415,15 +1432,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1415 cpu_list = NULL; 1432 cpu_list = NULL;
1416 } 1433 }
1417 1434
1418 if (!nr_counters) 1435 if (!nr_counters && perf_evsel_list__create_default() < 0) {
1419 nr_counters = 1; 1436 pr_err("Not enough memory for event selector list\n");
1420 1437 return -ENOMEM;
1421 symbol_conf.priv_size = (sizeof(struct sym_entry) + 1438 }
1422 (nr_counters + 1) * sizeof(unsigned long));
1423
1424 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1425 if (symbol__init() < 0)
1426 return -1;
1427 1439
1428 if (delay_secs < 1) 1440 if (delay_secs < 1)
1429 delay_secs = 1; 1441 delay_secs = 1;
@@ -1440,23 +1452,33 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1440 exit(EXIT_FAILURE); 1452 exit(EXIT_FAILURE);
1441 } 1453 }
1442 1454
1443 /* 1455 if (target_tid != -1)
1444 * Fill in the ones not specifically initialized via -c: 1456 cpus = cpu_map__dummy_new();
1445 */ 1457 else
1446 for (counter = 0; counter < nr_counters; counter++) { 1458 cpus = cpu_map__new(cpu_list);
1447 if (attrs[counter].sample_period) 1459
1460 if (cpus == NULL)
1461 usage_with_options(top_usage, options);
1462
1463 list_for_each_entry(pos, &evsel_list, node) {
1464 if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
1465 perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
1466 goto out_free_fd;
1467 /*
1468 * Fill in the ones not specifically initialized via -c:
1469 */
1470 if (pos->attr.sample_period)
1448 continue; 1471 continue;
1449 1472
1450 attrs[counter].sample_period = default_interval; 1473 pos->attr.sample_period = default_interval;
1451 } 1474 }
1452 1475
1453 if (target_tid != -1) 1476 symbol_conf.priv_size = (sizeof(struct sym_entry) +
1454 nr_cpus = 1; 1477 (nr_counters + 1) * sizeof(unsigned long));
1455 else
1456 nr_cpus = read_cpu_map(cpu_list);
1457 1478
1458 if (nr_cpus < 1) 1479 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1459 usage_with_options(top_usage, options); 1480 if (symbol__init() < 0)
1481 return -1;
1460 1482
1461 get_term_dimensions(&winsize); 1483 get_term_dimensions(&winsize);
1462 if (print_entries == 0) { 1484 if (print_entries == 0) {
@@ -1464,5 +1486,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1464 signal(SIGWINCH, sig_winch_handler); 1486 signal(SIGWINCH, sig_winch_handler);
1465 } 1487 }
1466 1488
1467 return __cmd_top(); 1489 status = __cmd_top();
1490out_free_fd:
1491 list_for_each_entry(pos, &evsel_list, node)
1492 perf_evsel__free_mmap(pos);
1493
1494 return status;
1468} 1495}
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..5b1ecd66bb36 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -286,6 +286,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
286 status = p->fn(argc, argv, prefix); 286 status = p->fn(argc, argv, prefix);
287 exit_browser(status); 287 exit_browser(status);
288 288
289 perf_evsel_list__delete();
290
289 if (status) 291 if (status)
290 return status & 0xff; 292 return status & 0xff;
291 293
@@ -323,7 +325,7 @@ static void handle_internal_command(int argc, const char **argv)
323 { "top", cmd_top, 0 }, 325 { "top", cmd_top, 0 },
324 { "annotate", cmd_annotate, 0 }, 326 { "annotate", cmd_annotate, 0 },
325 { "version", cmd_version, 0 }, 327 { "version", cmd_version, 0 },
326 { "trace", cmd_trace, 0 }, 328 { "script", cmd_script, 0 },
327 { "sched", cmd_sched, 0 }, 329 { "sched", cmd_sched, 0 },
328 { "probe", cmd_probe, 0 }, 330 { "probe", cmd_probe, 0 },
329 { "kmem", cmd_kmem, 0 }, 331 { "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-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-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-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-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-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-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-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-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-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-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-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-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-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..2302ec051bb4 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,7 +456,8 @@ 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:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost);
382 session->hists.stats.total_lost += self->lost.lost; 463 session->hists.stats.total_lost += self->lost.lost;
@@ -392,7 +473,7 @@ static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
392 * a zero sized synthesized MMAP event for the kernel. 473 * a zero sized synthesized MMAP event for the kernel.
393 */ 474 */
394 if (maps[MAP__FUNCTION]->end == 0) 475 if (maps[MAP__FUNCTION]->end == 0)
395 maps[MAP__FUNCTION]->end = ~0UL; 476 maps[MAP__FUNCTION]->end = ~0ULL;
396} 477}
397 478
398static int event__process_kernel_mmap(event_t *self, 479static int event__process_kernel_mmap(event_t *self,
@@ -485,7 +566,8 @@ out_problem:
485 return -1; 566 return -1;
486} 567}
487 568
488int event__process_mmap(event_t *self, struct perf_session *session) 569int event__process_mmap(event_t *self, struct sample_data *sample __used,
570 struct perf_session *session)
489{ 571{
490 struct machine *machine; 572 struct machine *machine;
491 struct thread *thread; 573 struct thread *thread;
@@ -526,7 +608,8 @@ out_problem:
526 return 0; 608 return 0;
527} 609}
528 610
529int event__process_task(event_t *self, struct perf_session *session) 611int event__process_task(event_t *self, struct sample_data *sample __used,
612 struct perf_session *session)
530{ 613{
531 struct thread *thread = perf_session__findnew(session, self->fork.tid); 614 struct thread *thread = perf_session__findnew(session, self->fork.tid);
532 struct thread *parent = perf_session__findnew(session, self->fork.ptid); 615 struct thread *parent = perf_session__findnew(session, self->fork.ptid);
@@ -548,18 +631,19 @@ int event__process_task(event_t *self, struct perf_session *session)
548 return 0; 631 return 0;
549} 632}
550 633
551int event__process(event_t *event, struct perf_session *session) 634int event__process(event_t *event, struct sample_data *sample,
635 struct perf_session *session)
552{ 636{
553 switch (event->header.type) { 637 switch (event->header.type) {
554 case PERF_RECORD_COMM: 638 case PERF_RECORD_COMM:
555 event__process_comm(event, session); 639 event__process_comm(event, sample, session);
556 break; 640 break;
557 case PERF_RECORD_MMAP: 641 case PERF_RECORD_MMAP:
558 event__process_mmap(event, session); 642 event__process_mmap(event, sample, session);
559 break; 643 break;
560 case PERF_RECORD_FORK: 644 case PERF_RECORD_FORK:
561 case PERF_RECORD_EXIT: 645 case PERF_RECORD_EXIT:
562 event__process_task(event, session); 646 event__process_task(event, sample, session);
563 break; 647 break;
564 default: 648 default:
565 break; 649 break;
@@ -674,32 +758,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
674 symbol_filter_t filter) 758 symbol_filter_t filter)
675{ 759{
676 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 760 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
677 struct thread *thread; 761 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 762
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) 763 if (thread == NULL)
704 return -1; 764 return -1;
705 765
@@ -766,9 +826,65 @@ out_filtered:
766 return 0; 826 return 0;
767} 827}
768 828
769int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) 829static int event__parse_id_sample(const event_t *event,
830 struct perf_session *session,
831 struct sample_data *sample)
770{ 832{
771 const u64 *array = event->sample.array; 833 const u64 *array;
834 u64 type;
835
836 sample->cpu = sample->pid = sample->tid = -1;
837 sample->stream_id = sample->id = sample->time = -1ULL;
838
839 if (!session->sample_id_all)
840 return 0;
841
842 array = event->sample.array;
843 array += ((event->header.size -
844 sizeof(event->header)) / sizeof(u64)) - 1;
845 type = session->sample_type;
846
847 if (type & PERF_SAMPLE_CPU) {
848 u32 *p = (u32 *)array;
849 sample->cpu = *p;
850 array--;
851 }
852
853 if (type & PERF_SAMPLE_STREAM_ID) {
854 sample->stream_id = *array;
855 array--;
856 }
857
858 if (type & PERF_SAMPLE_ID) {
859 sample->id = *array;
860 array--;
861 }
862
863 if (type & PERF_SAMPLE_TIME) {
864 sample->time = *array;
865 array--;
866 }
867
868 if (type & PERF_SAMPLE_TID) {
869 u32 *p = (u32 *)array;
870 sample->pid = p[0];
871 sample->tid = p[1];
872 }
873
874 return 0;
875}
876
877int event__parse_sample(const event_t *event, struct perf_session *session,
878 struct sample_data *data)
879{
880 const u64 *array;
881 u64 type;
882
883 if (event->header.type != PERF_RECORD_SAMPLE)
884 return event__parse_id_sample(event, session, data);
885
886 array = event->sample.array;
887 type = session->sample_type;
772 888
773 if (type & PERF_SAMPLE_IP) { 889 if (type & PERF_SAMPLE_IP) {
774 data->ip = event->ip.ip; 890 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 7cba0551a565..989fa2dee2fd 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);
@@ -433,8 +438,10 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
433 int idx = 0, err; 438 int idx = 0, err;
434 439
435 session = container_of(self, struct perf_session, header); 440 session = container_of(self, struct perf_session, header);
436 if (perf_session__read_build_ids(session, true)) 441
437 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);
438 445
439 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 446 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
440 if (!nr_sections) 447 if (!nr_sections)
@@ -456,7 +463,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
456 463
457 /* Write trace info */ 464 /* Write trace info */
458 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 465 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
459 read_tracing_data(fd, attrs, nr_counters); 466 read_tracing_data(fd, &evsel_list);
460 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 467 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
461 } 468 }
462 469
@@ -599,7 +606,7 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
599static int perf_header__getbuffer64(struct perf_header *self, 606static int perf_header__getbuffer64(struct perf_header *self,
600 int fd, void *buf, size_t size) 607 int fd, void *buf, size_t size)
601{ 608{
602 if (do_read(fd, buf, size) <= 0) 609 if (readn(fd, buf, size) <= 0)
603 return -1; 610 return -1;
604 611
605 if (self->needs_swap) 612 if (self->needs_swap)
@@ -655,7 +662,7 @@ int perf_file_header__read(struct perf_file_header *self,
655{ 662{
656 lseek(fd, 0, SEEK_SET); 663 lseek(fd, 0, SEEK_SET);
657 664
658 if (do_read(fd, self, sizeof(*self)) <= 0 || 665 if (readn(fd, self, sizeof(*self)) <= 0 ||
659 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 666 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
660 return -1; 667 return -1;
661 668
@@ -816,7 +823,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
816 struct perf_header *ph, int fd, 823 struct perf_header *ph, int fd,
817 bool repipe) 824 bool repipe)
818{ 825{
819 if (do_read(fd, self, sizeof(*self)) <= 0 || 826 if (readn(fd, self, sizeof(*self)) <= 0 ||
820 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 827 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
821 return -1; 828 return -1;
822 829
@@ -941,6 +948,24 @@ u64 perf_header__sample_type(struct perf_header *header)
941 return type; 948 return type;
942} 949}
943 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
944struct perf_event_attr * 969struct perf_event_attr *
945perf_header__find_attr(u64 id, struct perf_header *header) 970perf_header__find_attr(u64 id, struct perf_header *header)
946{ 971{
@@ -987,21 +1012,23 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
987 1012
988 ev = malloc(size); 1013 ev = malloc(size);
989 1014
1015 if (ev == NULL)
1016 return -ENOMEM;
1017
990 ev->attr.attr = *attr; 1018 ev->attr.attr = *attr;
991 memcpy(ev->attr.id, id, ids * sizeof(u64)); 1019 memcpy(ev->attr.id, id, ids * sizeof(u64));
992 1020
993 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 1021 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
994 ev->attr.header.size = size; 1022 ev->attr.header.size = size;
995 1023
996 err = process(ev, session); 1024 err = process(ev, NULL, session);
997 1025
998 free(ev); 1026 free(ev);
999 1027
1000 return err; 1028 return err;
1001} 1029}
1002 1030
1003int event__synthesize_attrs(struct perf_header *self, 1031int event__synthesize_attrs(struct perf_header *self, event__handler_t process,
1004 event__handler_t process,
1005 struct perf_session *session) 1032 struct perf_session *session)
1006{ 1033{
1007 struct perf_header_attr *attr; 1034 struct perf_header_attr *attr;
@@ -1071,7 +1098,7 @@ int event__synthesize_event_type(u64 event_id, char *name,
1071 ev.event_type.header.size = sizeof(ev.event_type) - 1098 ev.event_type.header.size = sizeof(ev.event_type) -
1072 (sizeof(ev.event_type.event_type.name) - size); 1099 (sizeof(ev.event_type.event_type.name) - size);
1073 1100
1074 err = process(&ev, session); 1101 err = process(&ev, NULL, session);
1075 1102
1076 return err; 1103 return err;
1077} 1104}
@@ -1106,8 +1133,7 @@ int event__process_event_type(event_t *self,
1106 return 0; 1133 return 0;
1107} 1134}
1108 1135
1109int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, 1136int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
1110 int nb_events,
1111 event__handler_t process, 1137 event__handler_t process,
1112 struct perf_session *session __unused) 1138 struct perf_session *session __unused)
1113{ 1139{
@@ -1118,7 +1144,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1118 memset(&ev, 0, sizeof(ev)); 1144 memset(&ev, 0, sizeof(ev));
1119 1145
1120 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 1146 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
1121 size = read_tracing_data_size(fd, pattrs, nb_events); 1147 size = read_tracing_data_size(fd, pattrs);
1122 if (size <= 0) 1148 if (size <= 0)
1123 return size; 1149 return size;
1124 aligned_size = ALIGN(size, sizeof(u64)); 1150 aligned_size = ALIGN(size, sizeof(u64));
@@ -1126,9 +1152,9 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1126 ev.tracing_data.header.size = sizeof(ev.tracing_data); 1152 ev.tracing_data.header.size = sizeof(ev.tracing_data);
1127 ev.tracing_data.size = aligned_size; 1153 ev.tracing_data.size = aligned_size;
1128 1154
1129 process(&ev, session); 1155 process(&ev, NULL, session);
1130 1156
1131 err = read_tracing_data(fd, pattrs, nb_events); 1157 err = read_tracing_data(fd, pattrs);
1132 write_padded(fd, NULL, 0, padding); 1158 write_padded(fd, NULL, 0, padding);
1133 1159
1134 return aligned_size; 1160 return aligned_size;
@@ -1186,7 +1212,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
1186 ev.build_id.header.size = sizeof(ev.build_id) + len; 1212 ev.build_id.header.size = sizeof(ev.build_id) + len;
1187 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);
1188 1214
1189 err = process(&ev, session); 1215 err = process(&ev, NULL, session);
1190 1216
1191 return err; 1217 return err;
1192} 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 76bcc35cf9b1..c749ba6136a0 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1092,6 +1092,12 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1092 FILE *file; 1092 FILE *file;
1093 int err = 0; 1093 int err = 0;
1094 u64 len; 1094 u64 len;
1095 char symfs_filename[PATH_MAX];
1096
1097 if (filename) {
1098 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1099 symbol_conf.symfs, filename);
1100 }
1095 1101
1096 if (filename == NULL) { 1102 if (filename == NULL) {
1097 if (dso->has_build_id) { 1103 if (dso->has_build_id) {
@@ -1100,9 +1106,9 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1100 return -ENOMEM; 1106 return -ENOMEM;
1101 } 1107 }
1102 goto fallback; 1108 goto fallback;
1103 } else if (readlink(filename, command, sizeof(command)) < 0 || 1109 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
1104 strstr(command, "[kernel.kallsyms]") || 1110 strstr(command, "[kernel.kallsyms]") ||
1105 access(filename, R_OK)) { 1111 access(symfs_filename, R_OK)) {
1106 free(filename); 1112 free(filename);
1107fallback: 1113fallback:
1108 /* 1114 /*
@@ -1111,6 +1117,8 @@ fallback:
1111 * DSO is the same as when 'perf record' ran. 1117 * DSO is the same as when 'perf record' ran.
1112 */ 1118 */
1113 filename = dso->long_name; 1119 filename = dso->long_name;
1120 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1121 symbol_conf.symfs, filename);
1114 free_filename = false; 1122 free_filename = false;
1115 } 1123 }
1116 1124
@@ -1137,7 +1145,7 @@ fallback:
1137 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand", 1145 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand",
1138 map__rip_2objdump(map, sym->start), 1146 map__rip_2objdump(map, sym->start),
1139 map__rip_2objdump(map, sym->end), 1147 map__rip_2objdump(map, sym->end),
1140 filename, filename); 1148 symfs_filename, filename);
1141 1149
1142 pr_debug("Executing: %s\n", command); 1150 pr_debug("Executing: %s\n", command);
1143 1151
@@ -1168,10 +1176,13 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
1168 size_t ret = 0; 1176 size_t ret = 0;
1169 1177
1170 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 1178 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
1171 if (!event__name[i]) 1179 const char *name = event__get_event_name(i);
1180
1181 if (!strcmp(name, "UNKNOWN"))
1172 continue; 1182 continue;
1173 ret += fprintf(fp, "%10s events: %10d\n", 1183
1174 event__name[i], self->stats.nr_events[i]); 1184 ret += fprintf(fp, "%16s events: %10d\n", name,
1185 self->stats.nr_events[i]);
1175 } 1186 }
1176 1187
1177 return ret; 1188 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..8be0b968ca0b 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -13,6 +13,11 @@ static inline void set_bit(int nr, unsigned long *addr)
13 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); 13 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
14} 14}
15 15
16static inline void clear_bit(int nr, unsigned long *addr)
17{
18 addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
19}
20
16static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) 21static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
17{ 22{
18 return ((1UL << (nr % BITS_PER_LONG)) & 23 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/parse-events.c b/tools/perf/util/parse-events.c
index 4af5bd59cfd1..5cb6f4bde905 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}
@@ -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,37 @@ 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
493static int store_event_type(const char *orgname)
494{
495 char filename[PATH_MAX], *c;
496 FILE *file;
497 int id, n;
498
499 sprintf(filename, "%s/", debugfs_path);
500 strncat(filename, orgname, strlen(orgname));
501 strcat(filename, "/id");
502
503 c = strchr(filename, ':');
504 if (c)
505 *c = '/';
506
507 file = fopen(filename, "r");
508 if (!file)
509 return 0;
510 n = fscanf(file, "%i", &id);
511 fclose(file);
512 if (n < 1) {
513 pr_err("cannot store event ID\n");
514 return -EINVAL;
515 }
516 return perf_header__push_event(id, orgname);
517}
493 518
494static enum event_result parse_tracepoint_event(const char **strp, 519static enum event_result parse_tracepoint_event(const char **strp,
495 struct perf_event_attr *attr) 520 struct perf_event_attr *attr)
496{ 521{
497 const char *evt_name; 522 const char *evt_name;
498 char *flags; 523 char *flags = NULL, *comma_loc;
499 char sys_name[MAX_EVENT_LENGTH]; 524 char sys_name[MAX_EVENT_LENGTH];
500 unsigned int sys_length, evt_length; 525 unsigned int sys_length, evt_length;
501 526
@@ -514,6 +539,11 @@ static enum event_result parse_tracepoint_event(const char **strp,
514 sys_name[sys_length] = '\0'; 539 sys_name[sys_length] = '\0';
515 evt_name = evt_name + 1; 540 evt_name = evt_name + 1;
516 541
542 comma_loc = strchr(evt_name, ',');
543 if (comma_loc) {
544 /* take the event name up to the comma */
545 evt_name = strndup(evt_name, comma_loc - evt_name);
546 }
517 flags = strchr(evt_name, ':'); 547 flags = strchr(evt_name, ':');
518 if (flags) { 548 if (flags) {
519 /* split it out: */ 549 /* split it out: */
@@ -524,14 +554,17 @@ static enum event_result parse_tracepoint_event(const char **strp,
524 evt_length = strlen(evt_name); 554 evt_length = strlen(evt_name);
525 if (evt_length >= MAX_EVENT_LENGTH) 555 if (evt_length >= MAX_EVENT_LENGTH)
526 return EVT_FAILED; 556 return EVT_FAILED;
527
528 if (strpbrk(evt_name, "*?")) { 557 if (strpbrk(evt_name, "*?")) {
529 *strp = evt_name + evt_length; 558 *strp += strlen(sys_name) + evt_length;
530 return parse_multiple_tracepoint_event(sys_name, evt_name, 559 return parse_multiple_tracepoint_event(sys_name, evt_name,
531 flags); 560 flags);
532 } else 561 } else {
562 if (store_event_type(evt_name) < 0)
563 return EVT_FAILED;
564
533 return parse_single_tracepoint_event(sys_name, evt_name, 565 return parse_single_tracepoint_event(sys_name, evt_name,
534 evt_length, attr, strp); 566 evt_length, attr, strp);
567 }
535} 568}
536 569
537static enum event_result 570static enum event_result
@@ -774,45 +807,12 @@ modifier:
774 return ret; 807 return ret;
775} 808}
776 809
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) 810int parse_events(const struct option *opt __used, const char *str, int unset __used)
804{ 811{
805 struct perf_event_attr attr; 812 struct perf_event_attr attr;
806 enum event_result ret; 813 enum event_result ret;
807 814
808 if (strchr(str, ':'))
809 if (store_event_type(str) < 0)
810 return -1;
811
812 for (;;) { 815 for (;;) {
813 if (nr_counters == MAX_COUNTERS)
814 return -1;
815
816 memset(&attr, 0, sizeof(attr)); 816 memset(&attr, 0, sizeof(attr));
817 ret = parse_event_symbols(&str, &attr); 817 ret = parse_event_symbols(&str, &attr);
818 if (ret == EVT_FAILED) 818 if (ret == EVT_FAILED)
@@ -822,8 +822,13 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
822 return -1; 822 return -1;
823 823
824 if (ret != EVT_HANDLED_ALL) { 824 if (ret != EVT_HANDLED_ALL) {
825 attrs[nr_counters] = attr; 825 struct perf_evsel *evsel;
826 nr_counters++; 826 evsel = perf_evsel__new(&attr,
827 nr_counters);
828 if (evsel == NULL)
829 return -1;
830 list_add_tail(&evsel->node, &evsel_list);
831 ++nr_counters;
827 } 832 }
828 833
829 if (*str == 0) 834 if (*str == 0)
@@ -840,21 +845,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, 845int parse_filter(const struct option *opt __used, const char *str,
841 int unset __used) 846 int unset __used)
842{ 847{
843 int i = nr_counters - 1; 848 struct perf_evsel *last = NULL;
844 int len = strlen(str); 849
850 if (!list_empty(&evsel_list))
851 last = list_entry(evsel_list.prev, struct perf_evsel, node);
845 852
846 if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) { 853 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
847 fprintf(stderr, 854 fprintf(stderr,
848 "-F option should follow a -e tracepoint option\n"); 855 "-F option should follow a -e tracepoint option\n");
849 return -1; 856 return -1;
850 } 857 }
851 858
852 filters[i] = malloc(len + 1); 859 last->filter = strdup(str);
853 if (!filters[i]) { 860 if (last->filter == NULL) {
854 fprintf(stderr, "not enough memory to hold filter string\n"); 861 fprintf(stderr, "not enough memory to hold filter string\n");
855 return -1; 862 return -1;
856 } 863 }
857 strcpy(filters[i], str);
858 864
859 return 0; 865 return 0;
860} 866}
@@ -906,6 +912,47 @@ static void print_tracepoint_events(void)
906} 912}
907 913
908/* 914/*
915 * Check whether event is in <debugfs_mount_point>/tracing/events
916 */
917
918int is_valid_tracepoint(const char *event_string)
919{
920 DIR *sys_dir, *evt_dir;
921 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
922 char evt_path[MAXPATHLEN];
923 char dir_path[MAXPATHLEN];
924
925 if (debugfs_valid_mountpoint(debugfs_path))
926 return 0;
927
928 sys_dir = opendir(debugfs_path);
929 if (!sys_dir)
930 return 0;
931
932 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
933
934 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
935 sys_dirent.d_name);
936 evt_dir = opendir(dir_path);
937 if (!evt_dir)
938 continue;
939
940 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
941 snprintf(evt_path, MAXPATHLEN, "%s:%s",
942 sys_dirent.d_name, evt_dirent.d_name);
943 if (!strcmp(evt_path, event_string)) {
944 closedir(evt_dir);
945 closedir(sys_dir);
946 return 1;
947 }
948 }
949 closedir(evt_dir);
950 }
951 closedir(sys_dir);
952 return 0;
953}
954
955/*
909 * Print the help text for the event symbols: 956 * Print the help text for the event symbols:
910 */ 957 */
911void print_events(void) 958void print_events(void)
@@ -963,3 +1010,33 @@ void print_events(void)
963 1010
964 exit(129); 1011 exit(129);
965} 1012}
1013
1014int perf_evsel_list__create_default(void)
1015{
1016 struct perf_evsel *evsel;
1017 struct perf_event_attr attr;
1018
1019 memset(&attr, 0, sizeof(attr));
1020 attr.type = PERF_TYPE_HARDWARE;
1021 attr.config = PERF_COUNT_HW_CPU_CYCLES;
1022
1023 evsel = perf_evsel__new(&attr, 0);
1024
1025 if (evsel == NULL)
1026 return -ENOMEM;
1027
1028 list_add(&evsel->node, &evsel_list);
1029 ++nr_counters;
1030 return 0;
1031}
1032
1033void perf_evsel_list__delete(void)
1034{
1035 struct perf_evsel *pos, *n;
1036
1037 list_for_each_entry_safe(pos, n, &evsel_list, node) {
1038 list_del_init(&pos->node);
1039 perf_evsel__delete(pos);
1040 }
1041 nr_counters = 0;
1042}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index fc4ab3fe877a..b82cafb83772 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 *evsel_list);
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 61191c6cbe7a..128aaab0aeda 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:
@@ -149,7 +149,8 @@ static int open_vmlinux(const char *module)
149{ 149{
150 const char *path = kernel_get_module_path(module); 150 const char *path = kernel_get_module_path(module);
151 if (!path) { 151 if (!path) {
152 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");
153 return -ENOENT; 154 return -ENOENT;
154 } 155 }
155 pr_debug("Try to open %s\n", path); 156 pr_debug("Try to open %s\n", path);
@@ -226,7 +227,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
226 pr_warning("Warning: No dwarf info found in the vmlinux - " 227 pr_warning("Warning: No dwarf info found in the vmlinux - "
227 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 228 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
228 if (!need_dwarf) { 229 if (!need_dwarf) {
229 pr_debug("Trying to use symbols.\nn"); 230 pr_debug("Trying to use symbols.\n");
230 return 0; 231 return 0;
231 } 232 }
232 } 233 }
@@ -295,42 +296,49 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
295#define LINEBUF_SIZE 256 296#define LINEBUF_SIZE 256
296#define NR_ADDITIONAL_LINES 2 297#define NR_ADDITIONAL_LINES 2
297 298
298static 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)
299{ 300{
300 char buf[LINEBUF_SIZE]; 301 char buf[LINEBUF_SIZE];
301 const char *color = PERF_COLOR_BLUE; 302 const char *color = show_num ? "" : PERF_COLOR_BLUE;
303 const char *prefix = NULL;
302 304
303 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 305 do {
304 goto error;
305 if (!skip) {
306 if (show_num)
307 fprintf(stdout, "%7d %s", l, buf);
308 else
309 color_fprintf(stdout, color, " %s", buf);
310 }
311
312 while (strlen(buf) == LINEBUF_SIZE - 1 &&
313 buf[LINEBUF_SIZE - 2] != '\n') {
314 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 306 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
315 goto error; 307 goto error;
316 if (!skip) { 308 if (skip)
317 if (show_num) 309 continue;
318 fprintf(stdout, "%s", buf); 310 if (!prefix) {
319 else 311 prefix = show_num ? "%7d " : " ";
320 color_fprintf(stdout, color, "%s", buf); 312 color_fprintf(stdout, color, prefix, l);
321 } 313 }
322 } 314 color_fprintf(stdout, color, "%s", buf);
323 315
324 return 0; 316 } while (strchr(buf, '\n') == NULL);
317
318 return 1;
325error: 319error:
326 if (feof(fp)) 320 if (ferror(fp)) {
327 pr_warning("Source file is shorter than expected.\n");
328 else
329 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}
330 326
331 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;
332} 335}
333 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
334/* 342/*
335 * Show line-range always requires debuginfo to find source file and 343 * Show line-range always requires debuginfo to find source file and
336 * line number. 344 * line number.
@@ -379,7 +387,7 @@ int show_line_range(struct line_range *lr, const char *module)
379 fprintf(stdout, "<%s:%d>\n", lr->function, 387 fprintf(stdout, "<%s:%d>\n", lr->function,
380 lr->start - lr->offset); 388 lr->start - lr->offset);
381 else 389 else
382 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 390 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
383 391
384 fp = fopen(lr->path, "r"); 392 fp = fopen(lr->path, "r");
385 if (fp == NULL) { 393 if (fp == NULL) {
@@ -388,26 +396,30 @@ int show_line_range(struct line_range *lr, const char *module)
388 return -errno; 396 return -errno;
389 } 397 }
390 /* Skip to starting line number */ 398 /* Skip to starting line number */
391 while (l < lr->start && ret >= 0) 399 while (l < lr->start) {
392 ret = show_one_line(fp, l++, true, false); 400 ret = skip_one_line(fp, l++);
393 if (ret < 0) 401 if (ret < 0)
394 goto end; 402 goto end;
403 }
395 404
396 list_for_each_entry(ln, &lr->line_list, list) { 405 list_for_each_entry(ln, &lr->line_list, list) {
397 while (ln->line > l && ret >= 0) 406 for (; ln->line > l; l++) {
398 ret = show_one_line(fp, (l++) - lr->offset, 407 ret = show_one_line(fp, l - lr->offset);
399 false, false); 408 if (ret < 0)
400 if (ret >= 0) 409 goto end;
401 ret = show_one_line(fp, (l++) - lr->offset, 410 }
402 false, true); 411 ret = show_one_line_with_num(fp, l++ - lr->offset);
403 if (ret < 0) 412 if (ret < 0)
404 goto end; 413 goto end;
405 } 414 }
406 415
407 if (lr->end == INT_MAX) 416 if (lr->end == INT_MAX)
408 lr->end = l + NR_ADDITIONAL_LINES; 417 lr->end = l + NR_ADDITIONAL_LINES;
409 while (l <= lr->end && !feof(fp) && ret >= 0) 418 while (l <= lr->end) {
410 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 }
411end: 423end:
412 fclose(fp); 424 fclose(fp);
413 return ret; 425 return ret;
@@ -466,7 +478,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
466 478
467 fd = open_vmlinux(module); 479 fd = open_vmlinux(module);
468 if (fd < 0) { 480 if (fd < 0) {
469 pr_warning("Failed to open debuginfo file.\n"); 481 pr_warning("Failed to open debug information file.\n");
470 return fd; 482 return fd;
471 } 483 }
472 484
@@ -526,56 +538,87 @@ int show_available_vars(struct perf_probe_event *pevs __unused,
526} 538}
527#endif 539#endif
528 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 */
529int parse_line_range_desc(const char *arg, struct line_range *lr) 561int parse_line_range_desc(const char *arg, struct line_range *lr)
530{ 562{
531 const char *ptr; 563 char *range, *name = strdup(arg);
532 char *tmp; 564 int err;
533 /* 565
534 * <Syntax> 566 if (!name)
535 * SRC:SLN[+NUM|-ELN] 567 return -ENOMEM;
536 * FUNC[:SLN[+NUM|-ELN]] 568
537 */ 569 lr->start = 0;
538 ptr = strchr(arg, ':'); 570 lr->end = INT_MAX;
539 if (ptr) { 571
540 lr->start = (int)strtoul(ptr + 1, &tmp, 0); 572 range = strchr(name, ':');
541 if (*tmp == '+') { 573 if (range) {
542 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 574 *range++ = '\0';
543 lr->end--; /* 575
544 * Adjust the number of lines here. 576 err = parse_line_num(&range, &lr->start, "start line");
545 * If the number of lines == 1, the 577 if (err)
546 * the end of line should be equal to 578 goto err;
547 * the start of line. 579
548 */ 580 if (*range == '+' || *range == '-') {
549 } else if (*tmp == '-') 581 const char c = *range++;
550 lr->end = (int)strtoul(tmp + 1, &tmp, 0); 582
551 else 583 err = parse_line_num(&range, &lr->end, "end line");
552 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
553 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;
554 if (lr->start > lr->end) { 602 if (lr->start > lr->end) {
555 semantic_error("Start line must be smaller" 603 semantic_error("Start line must be smaller"
556 " than end line.\n"); 604 " than end line.\n");
557 return -EINVAL; 605 goto err;
558 } 606 }
559 if (*tmp != '\0') { 607 if (*range != '\0') {
560 semantic_error("Tailing with invalid character '%d'.\n", 608 semantic_error("Tailing with invalid str '%s'.\n", range);
561 *tmp); 609 goto err;
562 return -EINVAL;
563 } 610 }
564 tmp = strndup(arg, (ptr - arg));
565 } else {
566 tmp = strdup(arg);
567 lr->end = INT_MAX;
568 } 611 }
569 612
570 if (tmp == NULL) 613 if (strchr(name, '.'))
571 return -ENOMEM; 614 lr->file = name;
572
573 if (strchr(tmp, '.'))
574 lr->file = tmp;
575 else 615 else
576 lr->function = tmp; 616 lr->function = name;
577 617
578 return 0; 618 return 0;
619err:
620 free(name);
621 return err;
579} 622}
580 623
581/* Check the name is good for event/group */ 624/* Check the name is good for event/group */
@@ -699,39 +742,40 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
699 742
700 /* Exclusion check */ 743 /* Exclusion check */
701 if (pp->lazy_line && pp->line) { 744 if (pp->lazy_line && pp->line) {
702 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");
703 return -EINVAL; 747 return -EINVAL;
704 } 748 }
705 749
706 if (pp->lazy_line && pp->offset) { 750 if (pp->lazy_line && pp->offset) {
707 semantic_error("Lazy pattern can't be used with offset."); 751 semantic_error("Lazy pattern can't be used with offset.\n");
708 return -EINVAL; 752 return -EINVAL;
709 } 753 }
710 754
711 if (pp->line && pp->offset) { 755 if (pp->line && pp->offset) {
712 semantic_error("Offset can't be used with line number."); 756 semantic_error("Offset can't be used with line number.\n");
713 return -EINVAL; 757 return -EINVAL;
714 } 758 }
715 759
716 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 760 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
717 semantic_error("File always requires line number or " 761 semantic_error("File always requires line number or "
718 "lazy pattern."); 762 "lazy pattern.\n");
719 return -EINVAL; 763 return -EINVAL;
720 } 764 }
721 765
722 if (pp->offset && !pp->function) { 766 if (pp->offset && !pp->function) {
723 semantic_error("Offset requires an entry function."); 767 semantic_error("Offset requires an entry function.\n");
724 return -EINVAL; 768 return -EINVAL;
725 } 769 }
726 770
727 if (pp->retprobe && !pp->function) { 771 if (pp->retprobe && !pp->function) {
728 semantic_error("Return probe requires an entry function."); 772 semantic_error("Return probe requires an entry function.\n");
729 return -EINVAL; 773 return -EINVAL;
730 } 774 }
731 775
732 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 776 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
733 semantic_error("Offset/Line/Lazy pattern can't be used with " 777 semantic_error("Offset/Line/Lazy pattern can't be used with "
734 "return probe."); 778 "return probe.\n");
735 return -EINVAL; 779 return -EINVAL;
736 } 780 }
737 781
@@ -1005,7 +1049,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1005 1049
1006 return tmp - buf; 1050 return tmp - buf;
1007error: 1051error:
1008 pr_debug("Failed to synthesize perf probe argument: %s", 1052 pr_debug("Failed to synthesize perf probe argument: %s\n",
1009 strerror(-ret)); 1053 strerror(-ret));
1010 return ret; 1054 return ret;
1011} 1055}
@@ -1033,13 +1077,13 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1033 goto error; 1077 goto error;
1034 } 1078 }
1035 if (pp->file) { 1079 if (pp->file) {
1036 len = strlen(pp->file) - 31; 1080 tmp = pp->file;
1037 if (len < 0) 1081 len = strlen(tmp);
1038 len = 0; 1082 if (len > 30) {
1039 tmp = strchr(pp->file + len, '/'); 1083 tmp = strchr(pp->file + len - 30, '/');
1040 if (!tmp) 1084 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1041 tmp = pp->file + len; 1085 }
1042 ret = e_snprintf(file, 32, "@%s", tmp + 1); 1086 ret = e_snprintf(file, 32, "@%s", tmp);
1043 if (ret <= 0) 1087 if (ret <= 0)
1044 goto error; 1088 goto error;
1045 } 1089 }
@@ -1055,7 +1099,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1055 1099
1056 return buf; 1100 return buf;
1057error: 1101error:
1058 pr_debug("Failed to synthesize perf probe point: %s", 1102 pr_debug("Failed to synthesize perf probe point: %s\n",
1059 strerror(-ret)); 1103 strerror(-ret));
1060 if (buf) 1104 if (buf)
1061 free(buf); 1105 free(buf);
@@ -1796,7 +1840,7 @@ static int del_trace_probe_event(int fd, const char *group,
1796 1840
1797 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1841 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1798 if (ret < 0) { 1842 if (ret < 0) {
1799 pr_err("Failed to copy event."); 1843 pr_err("Failed to copy event.\n");
1800 return ret; 1844 return ret;
1801 } 1845 }
1802 1846
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ddf4d4556321..ab83b6ac5d65 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -652,8 +652,8 @@ static_var:
652 regs = get_arch_regstr(regn); 652 regs = get_arch_regstr(regn);
653 if (!regs) { 653 if (!regs) {
654 /* This should be a bug in DWARF or this tool */ 654 /* This should be a bug in DWARF or this tool */
655 pr_warning("Mapping for DWARF register number %u " 655 pr_warning("Mapping for the register number %u "
656 "missing on this architecture.", regn); 656 "missing on this architecture.\n", regn);
657 return -ERANGE; 657 return -ERANGE;
658 } 658 }
659 659
@@ -699,13 +699,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
699 if (ret != DW_TAG_pointer_type && 699 if (ret != DW_TAG_pointer_type &&
700 ret != DW_TAG_array_type) { 700 ret != DW_TAG_array_type) {
701 pr_warning("Failed to cast into string: " 701 pr_warning("Failed to cast into string: "
702 "%s(%s) is not a pointer nor array.", 702 "%s(%s) is not a pointer nor array.\n",
703 dwarf_diename(vr_die), dwarf_diename(&type)); 703 dwarf_diename(vr_die), dwarf_diename(&type));
704 return -EINVAL; 704 return -EINVAL;
705 } 705 }
706 if (ret == DW_TAG_pointer_type) { 706 if (ret == DW_TAG_pointer_type) {
707 if (die_get_real_type(&type, &type) == NULL) { 707 if (die_get_real_type(&type, &type) == NULL) {
708 pr_warning("Failed to get a type information."); 708 pr_warning("Failed to get a type"
709 " information.\n");
709 return -ENOENT; 710 return -ENOENT;
710 } 711 }
711 while (*ref_ptr) 712 while (*ref_ptr)
@@ -720,7 +721,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
720 if (!die_compare_name(&type, "char") && 721 if (!die_compare_name(&type, "char") &&
721 !die_compare_name(&type, "unsigned char")) { 722 !die_compare_name(&type, "unsigned char")) {
722 pr_warning("Failed to cast into string: " 723 pr_warning("Failed to cast into string: "
723 "%s is not (unsigned) char *.", 724 "%s is not (unsigned) char *.\n",
724 dwarf_diename(vr_die)); 725 dwarf_diename(vr_die));
725 return -EINVAL; 726 return -EINVAL;
726 } 727 }
@@ -830,8 +831,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
830 return -EINVAL; 831 return -EINVAL;
831 } 832 }
832 if (field->name[0] == '[') { 833 if (field->name[0] == '[') {
833 pr_err("Semantic error: %s is not a pointor nor array.", 834 pr_err("Semantic error: %s is not a pointor"
834 varname); 835 " nor array.\n", varname);
835 return -EINVAL; 836 return -EINVAL;
836 } 837 }
837 if (field->ref) { 838 if (field->ref) {
@@ -978,7 +979,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
978 name = dwarf_diename(sp_die); 979 name = dwarf_diename(sp_die);
979 if (name) { 980 if (name) {
980 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 981 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
981 pr_warning("Failed to get entry pc of %s\n", 982 pr_warning("Failed to get entry address of %s\n",
982 dwarf_diename(sp_die)); 983 dwarf_diename(sp_die));
983 return -ENOENT; 984 return -ENOENT;
984 } 985 }
@@ -994,7 +995,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
994 if (retprobe) { 995 if (retprobe) {
995 if (eaddr != paddr) { 996 if (eaddr != paddr) {
996 pr_warning("Return probe must be on the head of" 997 pr_warning("Return probe must be on the head of"
997 " a real function\n"); 998 " a real function.\n");
998 return -EINVAL; 999 return -EINVAL;
999 } 1000 }
1000 tp->retprobe = true; 1001 tp->retprobe = true;
@@ -1033,7 +1034,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1033 Dwarf_Frame *frame; 1034 Dwarf_Frame *frame;
1034 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 1035 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
1035 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 1036 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
1036 pr_warning("Failed to get CFA on 0x%jx\n", 1037 pr_warning("Failed to get call frame on 0x%jx\n",
1037 (uintmax_t)pf->addr); 1038 (uintmax_t)pf->addr);
1038 return -ENOENT; 1039 return -ENOENT;
1039 } 1040 }
@@ -1060,7 +1061,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
1060 int ret = 0; 1061 int ret = 0;
1061 1062
1062 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1063 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1063 pr_warning("No source lines found in this CU.\n"); 1064 pr_warning("No source lines found.\n");
1064 return -ENOENT; 1065 return -ENOENT;
1065 } 1066 }
1066 1067
@@ -1162,7 +1163,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1162 } 1163 }
1163 1164
1164 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1165 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1165 pr_warning("No source lines found in this CU.\n"); 1166 pr_warning("No source lines found.\n");
1166 return -ENOENT; 1167 return -ENOENT;
1167 } 1168 }
1168 1169
@@ -1220,7 +1221,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1220 else { 1221 else {
1221 /* Get probe address */ 1222 /* Get probe address */
1222 if (dwarf_entrypc(in_die, &addr) != 0) { 1223 if (dwarf_entrypc(in_die, &addr) != 0) {
1223 pr_warning("Failed to get entry pc of %s.\n", 1224 pr_warning("Failed to get entry address of %s.\n",
1224 dwarf_diename(in_die)); 1225 dwarf_diename(in_die));
1225 param->retval = -ENOENT; 1226 param->retval = -ENOENT;
1226 return DWARF_CB_ABORT; 1227 return DWARF_CB_ABORT;
@@ -1261,8 +1262,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1261 param->retval = find_probe_point_lazy(sp_die, pf); 1262 param->retval = find_probe_point_lazy(sp_die, pf);
1262 else { 1263 else {
1263 if (dwarf_entrypc(sp_die, &pf->addr) != 0) { 1264 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1264 pr_warning("Failed to get entry pc of %s.\n", 1265 pr_warning("Failed to get entry address of "
1265 dwarf_diename(sp_die)); 1266 "%s.\n", dwarf_diename(sp_die));
1266 param->retval = -ENOENT; 1267 param->retval = -ENOENT;
1267 return DWARF_CB_ABORT; 1268 return DWARF_CB_ABORT;
1268 } 1269 }
@@ -1304,7 +1305,7 @@ static int find_probes(int fd, struct probe_finder *pf)
1304 1305
1305 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1306 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1306 if (!dbg) { 1307 if (!dbg) {
1307 pr_warning("No dwarf info found in the vmlinux - " 1308 pr_warning("No debug information found in the vmlinux - "
1308 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1309 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1309 return -EBADF; 1310 return -EBADF;
1310 } 1311 }
@@ -1549,7 +1550,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1549 /* Open the live linux kernel */ 1550 /* Open the live linux kernel */
1550 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); 1551 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
1551 if (!dbg) { 1552 if (!dbg) {
1552 pr_warning("No dwarf info found in the vmlinux - " 1553 pr_warning("No debug information found in the vmlinux - "
1553 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1554 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1554 ret = -EINVAL; 1555 ret = -EINVAL;
1555 goto end; 1556 goto end;
@@ -1559,7 +1560,8 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1559 addr += bias; 1560 addr += bias;
1560 /* Find cu die */ 1561 /* Find cu die */
1561 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { 1562 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) {
1562 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);
1563 ret = -EINVAL; 1565 ret = -EINVAL;
1564 goto end; 1566 goto end;
1565 } 1567 }
@@ -1684,7 +1686,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1684 1686
1685 line_list__init(&lf->lr->line_list); 1687 line_list__init(&lf->lr->line_list);
1686 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { 1688 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1687 pr_warning("No source lines found in this CU.\n"); 1689 pr_warning("No source lines found.\n");
1688 return -ENOENT; 1690 return -ENOENT;
1689 } 1691 }
1690 1692
@@ -1809,7 +1811,7 @@ int find_line_range(int fd, struct line_range *lr)
1809 1811
1810 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1812 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1811 if (!dbg) { 1813 if (!dbg) {
1812 pr_warning("No dwarf info found in the vmlinux - " 1814 pr_warning("No debug information found in the vmlinux - "
1813 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1815 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1814 return -EBADF; 1816 return -EBADF;
1815 } 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..313dac2d94ce 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,265 @@ 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:%Lu\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: %016Lx\n", i, sample->callchain->ips[i]);
568} 659}
569 660
570static int perf_session__process_sample(event_t *event, struct perf_session *s, 661static void perf_session__print_tstamp(struct perf_session *session,
571 struct perf_event_ops *ops) 662 event_t *event,
663 struct sample_data *sample)
572{ 664{
573 struct sample_data data; 665 if (event->header.type != PERF_RECORD_SAMPLE &&
666 !session->sample_id_all) {
667 fputs("-1 -1 ", stdout);
668 return;
669 }
574 670
575 if (!ops->ordered_samples) 671 if ((session->sample_type & PERF_SAMPLE_CPU))
576 return ops->sample(event, s); 672 printf("%u ", sample->cpu);
577 673
578 bzero(&data, sizeof(struct sample_data)); 674 if (session->sample_type & PERF_SAMPLE_TIME)
579 event__parse_sample(event, s->sample_type, &data); 675 printf("%Lu ", sample->time);
676}
580 677
581 queue_sample_event(event, &data, s); 678static void dump_event(struct perf_session *session, event_t *event,
679 u64 file_offset, struct sample_data *sample)
680{
681 if (!dump_trace)
682 return;
582 683
583 return 0; 684 printf("\n%#Lx [%#x]: event: %d\n", file_offset, event->header.size,
685 event->header.type);
686
687 trace_event(event);
688
689 if (sample)
690 perf_session__print_tstamp(session, event, sample);
691
692 printf("%#Lx [%#x]: PERF_RECORD_%s", file_offset, event->header.size,
693 event__get_event_name(event->header.type));
584} 694}
585 695
586static int perf_session__process_event(struct perf_session *self, 696static void dump_sample(struct perf_session *session, event_t *event,
587 event_t *event, 697 struct sample_data *sample)
588 struct perf_event_ops *ops,
589 u64 offset, u64 head)
590{ 698{
591 trace_event(event); 699 if (!dump_trace)
700 return;
592 701
593 if (event->header.type < PERF_RECORD_HEADER_MAX) { 702 printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
594 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 703 sample->pid, sample->tid, sample->ip, sample->period);
595 offset + head, event->header.size,
596 event__name[event->header.type]);
597 hists__inc_nr_events(&self->hists, event->header.type);
598 }
599 704
600 if (self->header.needs_swap && event__swap_ops[event->header.type]) 705 if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
601 event__swap_ops[event->header.type](event); 706 callchain__printf(sample);
707}
708
709static int perf_session_deliver_event(struct perf_session *session,
710 event_t *event,
711 struct sample_data *sample,
712 struct perf_event_ops *ops,
713 u64 file_offset)
714{
715 dump_event(session, event, file_offset, sample);
602 716
603 switch (event->header.type) { 717 switch (event->header.type) {
604 case PERF_RECORD_SAMPLE: 718 case PERF_RECORD_SAMPLE:
605 return perf_session__process_sample(event, self, ops); 719 dump_sample(session, event, sample);
720 return ops->sample(event, sample, session);
606 case PERF_RECORD_MMAP: 721 case PERF_RECORD_MMAP:
607 return ops->mmap(event, self); 722 return ops->mmap(event, sample, session);
608 case PERF_RECORD_COMM: 723 case PERF_RECORD_COMM:
609 return ops->comm(event, self); 724 return ops->comm(event, sample, session);
610 case PERF_RECORD_FORK: 725 case PERF_RECORD_FORK:
611 return ops->fork(event, self); 726 return ops->fork(event, sample, session);
612 case PERF_RECORD_EXIT: 727 case PERF_RECORD_EXIT:
613 return ops->exit(event, self); 728 return ops->exit(event, sample, session);
614 case PERF_RECORD_LOST: 729 case PERF_RECORD_LOST:
615 return ops->lost(event, self); 730 return ops->lost(event, sample, session);
616 case PERF_RECORD_READ: 731 case PERF_RECORD_READ:
617 return ops->read(event, self); 732 return ops->read(event, sample, session);
618 case PERF_RECORD_THROTTLE: 733 case PERF_RECORD_THROTTLE:
619 return ops->throttle(event, self); 734 return ops->throttle(event, sample, session);
620 case PERF_RECORD_UNTHROTTLE: 735 case PERF_RECORD_UNTHROTTLE:
621 return ops->unthrottle(event, self); 736 return ops->unthrottle(event, sample, session);
737 default:
738 ++session->hists.stats.nr_unknown_events;
739 return -1;
740 }
741}
742
743static int perf_session__preprocess_sample(struct perf_session *session,
744 event_t *event, struct sample_data *sample)
745{
746 if (event->header.type != PERF_RECORD_SAMPLE ||
747 !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
748 return 0;
749
750 if (!ip_callchain__valid(sample->callchain, event)) {
751 pr_debug("call-chain problem with event, skipping it.\n");
752 ++session->hists.stats.nr_invalid_chains;
753 session->hists.stats.total_invalid_chains += sample->period;
754 return -EINVAL;
755 }
756 return 0;
757}
758
759static int perf_session__process_user_event(struct perf_session *session, event_t *event,
760 struct perf_event_ops *ops, u64 file_offset)
761{
762 dump_event(session, event, file_offset, NULL);
763
764 /* These events are processed right away */
765 switch (event->header.type) {
622 case PERF_RECORD_HEADER_ATTR: 766 case PERF_RECORD_HEADER_ATTR:
623 return ops->attr(event, self); 767 return ops->attr(event, session);
624 case PERF_RECORD_HEADER_EVENT_TYPE: 768 case PERF_RECORD_HEADER_EVENT_TYPE:
625 return ops->event_type(event, self); 769 return ops->event_type(event, session);
626 case PERF_RECORD_HEADER_TRACING_DATA: 770 case PERF_RECORD_HEADER_TRACING_DATA:
627 /* setup for reading amidst mmap */ 771 /* setup for reading amidst mmap */
628 lseek(self->fd, offset + head, SEEK_SET); 772 lseek(session->fd, file_offset, SEEK_SET);
629 return ops->tracing_data(event, self); 773 return ops->tracing_data(event, session);
630 case PERF_RECORD_HEADER_BUILD_ID: 774 case PERF_RECORD_HEADER_BUILD_ID:
631 return ops->build_id(event, self); 775 return ops->build_id(event, session);
632 case PERF_RECORD_FINISHED_ROUND: 776 case PERF_RECORD_FINISHED_ROUND:
633 return ops->finished_round(event, self, ops); 777 return ops->finished_round(event, session, ops);
634 default: 778 default:
635 ++self->hists.stats.nr_unknown_events; 779 return -EINVAL;
636 return -1;
637 } 780 }
638} 781}
639 782
783static int perf_session__process_event(struct perf_session *session,
784 event_t *event,
785 struct perf_event_ops *ops,
786 u64 file_offset)
787{
788 struct sample_data sample;
789 int ret;
790
791 if (session->header.needs_swap && event__swap_ops[event->header.type])
792 event__swap_ops[event->header.type](event);
793
794 if (event->header.type >= PERF_RECORD_HEADER_MAX)
795 return -EINVAL;
796
797 hists__inc_nr_events(&session->hists, event->header.type);
798
799 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
800 return perf_session__process_user_event(session, event, ops, file_offset);
801
802 /*
803 * For all kernel events we get the sample data
804 */
805 event__parse_sample(event, session, &sample);
806
807 /* Preprocess sample records - precheck callchains */
808 if (perf_session__preprocess_sample(session, event, &sample))
809 return 0;
810
811 if (ops->ordered_samples) {
812 ret = perf_session_queue_event(session, event, &sample,
813 file_offset);
814 if (ret != -ETIME)
815 return ret;
816 }
817
818 return perf_session_deliver_event(session, event, &sample, ops,
819 file_offset);
820}
821
640void perf_event_header__bswap(struct perf_event_header *self) 822void perf_event_header__bswap(struct perf_event_header *self)
641{ 823{
642 self->type = bswap_32(self->type); 824 self->type = bswap_32(self->type);
@@ -656,21 +838,33 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
656 return thread; 838 return thread;
657} 839}
658 840
659int do_read(int fd, void *buf, size_t size) 841static void perf_session__warn_about_errors(const struct perf_session *session,
842 const struct perf_event_ops *ops)
660{ 843{
661 void *buf_start = buf; 844 if (ops->lost == event__process_lost &&
662 845 session->hists.stats.total_lost != 0) {
663 while (size) { 846 ui__warning("Processed %Lu events and LOST %Lu!\n\n"
664 int ret = read(fd, buf, size); 847 "Check IO/CPU overload!\n\n",
665 848 session->hists.stats.total_period,
666 if (ret <= 0) 849 session->hists.stats.total_lost);
667 return ret; 850 }
668 851
669 size -= ret; 852 if (session->hists.stats.nr_unknown_events != 0) {
670 buf += ret; 853 ui__warning("Found %u unknown events!\n\n"
854 "Is this an older tool processing a perf.data "
855 "file generated by a more recent tool?\n\n"
856 "If that is not the case, consider "
857 "reporting to linux-kernel@vger.kernel.org.\n\n",
858 session->hists.stats.nr_unknown_events);
671 } 859 }
672 860
673 return buf - buf_start; 861 if (session->hists.stats.nr_invalid_chains != 0) {
862 ui__warning("Found invalid callchains!\n\n"
863 "%u out of %u events were discarded for this reason.\n\n"
864 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
865 session->hists.stats.nr_invalid_chains,
866 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
867 }
674} 868}
675 869
676#define session_done() (*(volatile int *)(&session_done)) 870#define session_done() (*(volatile int *)(&session_done))
@@ -690,7 +884,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
690 884
691 head = 0; 885 head = 0;
692more: 886more:
693 err = do_read(self->fd, &event, sizeof(struct perf_event_header)); 887 err = readn(self->fd, &event, sizeof(struct perf_event_header));
694 if (err <= 0) { 888 if (err <= 0) {
695 if (err == 0) 889 if (err == 0)
696 goto done; 890 goto done;
@@ -710,8 +904,7 @@ more:
710 p += sizeof(struct perf_event_header); 904 p += sizeof(struct perf_event_header);
711 905
712 if (size - sizeof(struct perf_event_header)) { 906 if (size - sizeof(struct perf_event_header)) {
713 err = do_read(self->fd, p, 907 err = readn(self->fd, p, size - sizeof(struct perf_event_header));
714 size - sizeof(struct perf_event_header));
715 if (err <= 0) { 908 if (err <= 0) {
716 if (err == 0) { 909 if (err == 0) {
717 pr_err("unexpected end of event stream\n"); 910 pr_err("unexpected end of event stream\n");
@@ -724,8 +917,7 @@ more:
724 } 917 }
725 918
726 if (size == 0 || 919 if (size == 0 ||
727 (skip = perf_session__process_event(self, &event, ops, 920 (skip = perf_session__process_event(self, &event, ops, head)) < 0) {
728 0, head)) < 0) {
729 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n", 921 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
730 head, event.header.size, event.header.type); 922 head, event.header.size, event.header.type);
731 /* 923 /*
@@ -740,9 +932,6 @@ more:
740 932
741 head += size; 933 head += size;
742 934
743 dump_printf("\n%#Lx [%#x]: event: %d\n",
744 head, event.header.size, event.header.type);
745
746 if (skip > 0) 935 if (skip > 0)
747 head += skip; 936 head += skip;
748 937
@@ -751,82 +940,91 @@ more:
751done: 940done:
752 err = 0; 941 err = 0;
753out_err: 942out_err:
943 perf_session__warn_about_errors(self, ops);
944 perf_session_free_sample_buffers(self);
754 return err; 945 return err;
755} 946}
756 947
757int __perf_session__process_events(struct perf_session *self, 948int __perf_session__process_events(struct perf_session *session,
758 u64 data_offset, u64 data_size, 949 u64 data_offset, u64 data_size,
759 u64 file_size, struct perf_event_ops *ops) 950 u64 file_size, struct perf_event_ops *ops)
760{ 951{
761 int err, mmap_prot, mmap_flags; 952 u64 head, page_offset, file_offset, file_pos, progress_next;
762 u64 head, shift; 953 int err, mmap_prot, mmap_flags, map_idx = 0;
763 u64 offset = 0; 954 struct ui_progress *progress;
764 size_t page_size; 955 size_t page_size, mmap_size;
956 char *buf, *mmaps[8];
765 event_t *event; 957 event_t *event;
766 uint32_t size; 958 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 959
773 perf_event_ops__fill_defaults(ops); 960 perf_event_ops__fill_defaults(ops);
774 961
775 page_size = sysconf(_SC_PAGESIZE); 962 page_size = sysconf(_SC_PAGESIZE);
776 963
777 head = data_offset; 964 page_offset = page_size * (data_offset / page_size);
778 shift = page_size * (head / page_size); 965 file_offset = page_offset;
779 offset += shift; 966 head = data_offset - page_offset;
780 head -= shift; 967
968 if (data_offset + data_size < file_size)
969 file_size = data_offset + data_size;
970
971 progress_next = file_size / 16;
972 progress = ui_progress__new("Processing events...", file_size);
973 if (progress == NULL)
974 return -1;
975
976 mmap_size = session->mmap_window;
977 if (mmap_size > file_size)
978 mmap_size = file_size;
979
980 memset(mmaps, 0, sizeof(mmaps));
781 981
782 mmap_prot = PROT_READ; 982 mmap_prot = PROT_READ;
783 mmap_flags = MAP_SHARED; 983 mmap_flags = MAP_SHARED;
784 984
785 if (self->header.needs_swap) { 985 if (session->header.needs_swap) {
786 mmap_prot |= PROT_WRITE; 986 mmap_prot |= PROT_WRITE;
787 mmap_flags = MAP_PRIVATE; 987 mmap_flags = MAP_PRIVATE;
788 } 988 }
789remap: 989remap:
790 buf = mmap(NULL, page_size * self->mmap_window, mmap_prot, 990 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd,
791 mmap_flags, self->fd, offset); 991 file_offset);
792 if (buf == MAP_FAILED) { 992 if (buf == MAP_FAILED) {
793 pr_err("failed to mmap file\n"); 993 pr_err("failed to mmap file\n");
794 err = -errno; 994 err = -errno;
795 goto out_err; 995 goto out_err;
796 } 996 }
997 mmaps[map_idx] = buf;
998 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
999 file_pos = file_offset + head;
797 1000
798more: 1001more:
799 event = (event_t *)(buf + head); 1002 event = (event_t *)(buf + head);
800 ui_progress__update(progress, offset);
801 1003
802 if (self->header.needs_swap) 1004 if (session->header.needs_swap)
803 perf_event_header__bswap(&event->header); 1005 perf_event_header__bswap(&event->header);
804 size = event->header.size; 1006 size = event->header.size;
805 if (size == 0) 1007 if (size == 0)
806 size = 8; 1008 size = 8;
807 1009
808 if (head + event->header.size >= page_size * self->mmap_window) { 1010 if (head + event->header.size > mmap_size) {
809 int munmap_ret; 1011 if (mmaps[map_idx]) {
810 1012 munmap(mmaps[map_idx], mmap_size);
811 shift = page_size * (head / page_size); 1013 mmaps[map_idx] = NULL;
812 1014 }
813 munmap_ret = munmap(buf, page_size * self->mmap_window);
814 assert(munmap_ret == 0);
815 1015
816 offset += shift; 1016 page_offset = page_size * (head / page_size);
817 head -= shift; 1017 file_offset += page_offset;
1018 head -= page_offset;
818 goto remap; 1019 goto remap;
819 } 1020 }
820 1021
821 size = event->header.size; 1022 size = event->header.size;
822 1023
823 dump_printf("\n%#Lx [%#x]: event: %d\n",
824 offset + head, event->header.size, event->header.type);
825
826 if (size == 0 || 1024 if (size == 0 ||
827 perf_session__process_event(self, event, ops, offset, head) < 0) { 1025 perf_session__process_event(session, event, ops, file_pos) < 0) {
828 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n", 1026 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
829 offset + head, event->header.size, 1027 file_offset + head, event->header.size,
830 event->header.type); 1028 event->header.type);
831 /* 1029 /*
832 * assume we lost track of the stream, check alignment, and 1030 * assume we lost track of the stream, check alignment, and
@@ -839,19 +1037,24 @@ more:
839 } 1037 }
840 1038
841 head += size; 1039 head += size;
1040 file_pos += size;
842 1041
843 if (offset + head >= data_offset + data_size) 1042 if (file_pos >= progress_next) {
844 goto done; 1043 progress_next += file_size / 16;
1044 ui_progress__update(progress, file_pos);
1045 }
845 1046
846 if (offset + head < file_size) 1047 if (file_pos < file_size)
847 goto more; 1048 goto more;
848done: 1049
849 err = 0; 1050 err = 0;
850 /* do the final flush for ordered samples */ 1051 /* do the final flush for ordered samples */
851 self->ordered_samples.next_flush = ULLONG_MAX; 1052 session->ordered_samples.next_flush = ULLONG_MAX;
852 flush_sample_queue(self, ops); 1053 flush_sample_queue(session, ops);
853out_err: 1054out_err:
854 ui_progress__delete(progress); 1055 ui_progress__delete(progress);
1056 perf_session__warn_about_errors(session, ops);
1057 perf_session_free_sample_buffers(session);
855 return err; 1058 return err;
856} 1059}
857 1060
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/symbol.c b/tools/perf/util/symbol.c
index 439ab947daf4..15ccfba8cdf8 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -22,6 +22,10 @@
22#include <limits.h> 22#include <limits.h>
23#include <sys/utsname.h> 23#include <sys/utsname.h>
24 24
25#ifndef KSYM_NAME_LEN
26#define KSYM_NAME_LEN 128
27#endif
28
25#ifndef NT_GNU_BUILD_ID 29#ifndef NT_GNU_BUILD_ID
26#define NT_GNU_BUILD_ID 3 30#define NT_GNU_BUILD_ID 3
27#endif 31#endif
@@ -41,6 +45,7 @@ struct symbol_conf symbol_conf = {
41 .exclude_other = true, 45 .exclude_other = true,
42 .use_modules = true, 46 .use_modules = true,
43 .try_vmlinux_path = true, 47 .try_vmlinux_path = true,
48 .symfs = "",
44}; 49};
45 50
46int dso__name_len(const struct dso *self) 51int dso__name_len(const struct dso *self)
@@ -92,7 +97,7 @@ static void symbols__fixup_end(struct rb_root *self)
92 prev = curr; 97 prev = curr;
93 curr = rb_entry(nd, struct symbol, rb_node); 98 curr = rb_entry(nd, struct symbol, rb_node);
94 99
95 if (prev->end == prev->start) 100 if (prev->end == prev->start && prev->end != curr->start)
96 prev->end = curr->start - 1; 101 prev->end = curr->start - 1;
97 } 102 }
98 103
@@ -121,7 +126,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 126 * We still haven't the actual symbols, so guess the
122 * last map final address. 127 * last map final address.
123 */ 128 */
124 curr->end = ~0UL; 129 curr->end = ~0ULL;
125} 130}
126 131
127static void map_groups__fixup_end(struct map_groups *self) 132static void map_groups__fixup_end(struct map_groups *self)
@@ -425,16 +430,25 @@ size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
425 430
426int kallsyms__parse(const char *filename, void *arg, 431int kallsyms__parse(const char *filename, void *arg,
427 int (*process_symbol)(void *arg, const char *name, 432 int (*process_symbol)(void *arg, const char *name,
428 char type, u64 start)) 433 char type, u64 start, u64 end))
429{ 434{
430 char *line = NULL; 435 char *line = NULL;
431 size_t n; 436 size_t n;
432 int err = 0; 437 int err = -1;
438 u64 prev_start = 0;
439 char prev_symbol_type = 0;
440 char *prev_symbol_name;
433 FILE *file = fopen(filename, "r"); 441 FILE *file = fopen(filename, "r");
434 442
435 if (file == NULL) 443 if (file == NULL)
436 goto out_failure; 444 goto out_failure;
437 445
446 prev_symbol_name = malloc(KSYM_NAME_LEN);
447 if (prev_symbol_name == NULL)
448 goto out_close;
449
450 err = 0;
451
438 while (!feof(file)) { 452 while (!feof(file)) {
439 u64 start; 453 u64 start;
440 int line_len, len; 454 int line_len, len;
@@ -454,14 +468,33 @@ int kallsyms__parse(const char *filename, void *arg,
454 continue; 468 continue;
455 469
456 symbol_type = toupper(line[len]); 470 symbol_type = toupper(line[len]);
457 symbol_name = line + len + 2; 471 len += 2;
472 symbol_name = line + len;
473 len = line_len - len;
458 474
459 err = process_symbol(arg, symbol_name, symbol_type, start); 475 if (len >= KSYM_NAME_LEN) {
460 if (err) 476 err = -1;
461 break; 477 break;
478 }
479
480 if (prev_symbol_type) {
481 u64 end = start;
482 if (end != prev_start)
483 --end;
484 err = process_symbol(arg, prev_symbol_name,
485 prev_symbol_type, prev_start, end);
486 if (err)
487 break;
488 }
489
490 memcpy(prev_symbol_name, symbol_name, len + 1);
491 prev_symbol_type = symbol_type;
492 prev_start = start;
462 } 493 }
463 494
495 free(prev_symbol_name);
464 free(line); 496 free(line);
497out_close:
465 fclose(file); 498 fclose(file);
466 return err; 499 return err;
467 500
@@ -483,7 +516,7 @@ static u8 kallsyms2elf_type(char type)
483} 516}
484 517
485static int map__process_kallsym_symbol(void *arg, const char *name, 518static int map__process_kallsym_symbol(void *arg, const char *name,
486 char type, u64 start) 519 char type, u64 start, u64 end)
487{ 520{
488 struct symbol *sym; 521 struct symbol *sym;
489 struct process_kallsyms_args *a = arg; 522 struct process_kallsyms_args *a = arg;
@@ -492,11 +525,8 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
492 if (!symbol_type__is_a(type, a->map->type)) 525 if (!symbol_type__is_a(type, a->map->type))
493 return 0; 526 return 0;
494 527
495 /* 528 sym = symbol__new(start, end - start + 1,
496 * Will fix up the end later, when we have all symbols sorted. 529 kallsyms2elf_type(type), name);
497 */
498 sym = symbol__new(start, 0, kallsyms2elf_type(type), name);
499
500 if (sym == NULL) 530 if (sym == NULL)
501 return -ENOMEM; 531 return -ENOMEM;
502 /* 532 /*
@@ -649,7 +679,6 @@ int dso__load_kallsyms(struct dso *self, const char *filename,
649 if (dso__load_all_kallsyms(self, filename, map) < 0) 679 if (dso__load_all_kallsyms(self, filename, map) < 0)
650 return -1; 680 return -1;
651 681
652 symbols__fixup_end(&self->symbols[map->type]);
653 if (self->kernel == DSO_TYPE_GUEST_KERNEL) 682 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
654 self->origin = DSO__ORIG_GUEST_KERNEL; 683 self->origin = DSO__ORIG_GUEST_KERNEL;
655 else 684 else
@@ -839,8 +868,11 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map,
839 char sympltname[1024]; 868 char sympltname[1024];
840 Elf *elf; 869 Elf *elf;
841 int nr = 0, symidx, fd, err = 0; 870 int nr = 0, symidx, fd, err = 0;
871 char name[PATH_MAX];
842 872
843 fd = open(self->long_name, O_RDONLY); 873 snprintf(name, sizeof(name), "%s%s",
874 symbol_conf.symfs, self->long_name);
875 fd = open(name, O_RDONLY);
844 if (fd < 0) 876 if (fd < 0)
845 goto out; 877 goto out;
846 878
@@ -1452,16 +1484,19 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1452 self->origin++) { 1484 self->origin++) {
1453 switch (self->origin) { 1485 switch (self->origin) {
1454 case DSO__ORIG_BUILD_ID_CACHE: 1486 case DSO__ORIG_BUILD_ID_CACHE:
1455 if (dso__build_id_filename(self, name, size) == NULL) 1487 /* skip the locally configured cache if a symfs is given */
1488 if (symbol_conf.symfs[0] ||
1489 (dso__build_id_filename(self, name, size) == NULL)) {
1456 continue; 1490 continue;
1491 }
1457 break; 1492 break;
1458 case DSO__ORIG_FEDORA: 1493 case DSO__ORIG_FEDORA:
1459 snprintf(name, size, "/usr/lib/debug%s.debug", 1494 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1460 self->long_name); 1495 symbol_conf.symfs, self->long_name);
1461 break; 1496 break;
1462 case DSO__ORIG_UBUNTU: 1497 case DSO__ORIG_UBUNTU:
1463 snprintf(name, size, "/usr/lib/debug%s", 1498 snprintf(name, size, "%s/usr/lib/debug%s",
1464 self->long_name); 1499 symbol_conf.symfs, self->long_name);
1465 break; 1500 break;
1466 case DSO__ORIG_BUILDID: { 1501 case DSO__ORIG_BUILDID: {
1467 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1502 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -1473,19 +1508,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1473 sizeof(self->build_id), 1508 sizeof(self->build_id),
1474 build_id_hex); 1509 build_id_hex);
1475 snprintf(name, size, 1510 snprintf(name, size,
1476 "/usr/lib/debug/.build-id/%.2s/%s.debug", 1511 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1477 build_id_hex, build_id_hex + 2); 1512 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1478 } 1513 }
1479 break; 1514 break;
1480 case DSO__ORIG_DSO: 1515 case DSO__ORIG_DSO:
1481 snprintf(name, size, "%s", self->long_name); 1516 snprintf(name, size, "%s%s",
1517 symbol_conf.symfs, self->long_name);
1482 break; 1518 break;
1483 case DSO__ORIG_GUEST_KMODULE: 1519 case DSO__ORIG_GUEST_KMODULE:
1484 if (map->groups && map->groups->machine) 1520 if (map->groups && map->groups->machine)
1485 root_dir = map->groups->machine->root_dir; 1521 root_dir = map->groups->machine->root_dir;
1486 else 1522 else
1487 root_dir = ""; 1523 root_dir = "";
1488 snprintf(name, size, "%s%s", root_dir, self->long_name); 1524 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1525 root_dir, self->long_name);
1526 break;
1527
1528 case DSO__ORIG_KMODULE:
1529 snprintf(name, size, "%s%s", symbol_conf.symfs,
1530 self->long_name);
1489 break; 1531 break;
1490 1532
1491 default: 1533 default:
@@ -1784,17 +1826,20 @@ int dso__load_vmlinux(struct dso *self, struct map *map,
1784 const char *vmlinux, symbol_filter_t filter) 1826 const char *vmlinux, symbol_filter_t filter)
1785{ 1827{
1786 int err = -1, fd; 1828 int err = -1, fd;
1829 char symfs_vmlinux[PATH_MAX];
1787 1830
1788 fd = open(vmlinux, O_RDONLY); 1831 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s",
1832 symbol_conf.symfs, vmlinux);
1833 fd = open(symfs_vmlinux, O_RDONLY);
1789 if (fd < 0) 1834 if (fd < 0)
1790 return -1; 1835 return -1;
1791 1836
1792 dso__set_loaded(self, map->type); 1837 dso__set_loaded(self, map->type);
1793 err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0); 1838 err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
1794 close(fd); 1839 close(fd);
1795 1840
1796 if (err > 0) 1841 if (err > 0)
1797 pr_debug("Using %s for symbols\n", vmlinux); 1842 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1798 1843
1799 return err; 1844 return err;
1800} 1845}
@@ -1836,8 +1881,8 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1836 const char *kallsyms_filename = NULL; 1881 const char *kallsyms_filename = NULL;
1837 char *kallsyms_allocated_filename = NULL; 1882 char *kallsyms_allocated_filename = NULL;
1838 /* 1883 /*
1839 * Step 1: if the user specified a vmlinux filename, use it and only 1884 * Step 1: if the user specified a kallsyms or vmlinux filename, use
1840 * it, reporting errors to the user if it cannot be used. 1885 * it and only it, reporting errors to the user if it cannot be used.
1841 * 1886 *
1842 * For instance, try to analyse an ARM perf.data file _without_ a 1887 * For instance, try to analyse an ARM perf.data file _without_ a
1843 * build-id, or if the user specifies the wrong path to the right 1888 * build-id, or if the user specifies the wrong path to the right
@@ -1850,6 +1895,11 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1850 * validation in dso__load_vmlinux and will bail out if they don't 1895 * validation in dso__load_vmlinux and will bail out if they don't
1851 * match. 1896 * match.
1852 */ 1897 */
1898 if (symbol_conf.kallsyms_name != NULL) {
1899 kallsyms_filename = symbol_conf.kallsyms_name;
1900 goto do_kallsyms;
1901 }
1902
1853 if (symbol_conf.vmlinux_name != NULL) { 1903 if (symbol_conf.vmlinux_name != NULL) {
1854 err = dso__load_vmlinux(self, map, 1904 err = dso__load_vmlinux(self, map,
1855 symbol_conf.vmlinux_name, filter); 1905 symbol_conf.vmlinux_name, filter);
@@ -1867,6 +1917,10 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1867 goto out_fixup; 1917 goto out_fixup;
1868 } 1918 }
1869 1919
1920 /* do not try local files if a symfs was given */
1921 if (symbol_conf.symfs[0] != 0)
1922 return -1;
1923
1870 /* 1924 /*
1871 * Say the kernel DSO was created when processing the build-id header table, 1925 * Say the kernel DSO was created when processing the build-id header table,
1872 * we have a build-id, so check if it is the same as the running kernel, 1926 * we have a build-id, so check if it is the same as the running kernel,
@@ -2136,7 +2190,7 @@ struct process_args {
2136}; 2190};
2137 2191
2138static int symbol__in_kernel(void *arg, const char *name, 2192static int symbol__in_kernel(void *arg, const char *name,
2139 char type __used, u64 start) 2193 char type __used, u64 start, u64 end __used)
2140{ 2194{
2141 struct process_args *args = arg; 2195 struct process_args *args = arg;
2142 2196
@@ -2257,9 +2311,6 @@ static int vmlinux_path__init(void)
2257 struct utsname uts; 2311 struct utsname uts;
2258 char bf[PATH_MAX]; 2312 char bf[PATH_MAX];
2259 2313
2260 if (uname(&uts) < 0)
2261 return -1;
2262
2263 vmlinux_path = malloc(sizeof(char *) * 5); 2314 vmlinux_path = malloc(sizeof(char *) * 5);
2264 if (vmlinux_path == NULL) 2315 if (vmlinux_path == NULL)
2265 return -1; 2316 return -1;
@@ -2272,6 +2323,14 @@ static int vmlinux_path__init(void)
2272 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2323 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2273 goto out_fail; 2324 goto out_fail;
2274 ++vmlinux_path__nr_entries; 2325 ++vmlinux_path__nr_entries;
2326
2327 /* only try running kernel version if no symfs was given */
2328 if (symbol_conf.symfs[0] != 0)
2329 return 0;
2330
2331 if (uname(&uts) < 0)
2332 return -1;
2333
2275 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 2334 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
2276 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 2335 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
2277 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2336 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
@@ -2331,6 +2390,8 @@ static int setup_list(struct strlist **list, const char *list_str,
2331 2390
2332int symbol__init(void) 2391int symbol__init(void)
2333{ 2392{
2393 const char *symfs;
2394
2334 if (symbol_conf.initialized) 2395 if (symbol_conf.initialized)
2335 return 0; 2396 return 0;
2336 2397
@@ -2359,6 +2420,18 @@ int symbol__init(void)
2359 symbol_conf.sym_list_str, "symbol") < 0) 2420 symbol_conf.sym_list_str, "symbol") < 0)
2360 goto out_free_comm_list; 2421 goto out_free_comm_list;
2361 2422
2423 /*
2424 * A path to symbols of "/" is identical to ""
2425 * reset here for simplicity.
2426 */
2427 symfs = realpath(symbol_conf.symfs, NULL);
2428 if (symfs == NULL)
2429 symfs = symbol_conf.symfs;
2430 if (strcmp(symfs, "/") == 0)
2431 symbol_conf.symfs = "";
2432 if (symfs != symbol_conf.symfs)
2433 free((void *)symfs);
2434
2362 symbol_conf.initialized = true; 2435 symbol_conf.initialized = true;
2363 return 0; 2436 return 0;
2364 2437
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6c6eafdb932d..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;
@@ -215,7 +217,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
215int build_id__sprintf(const u8 *self, int len, char *bf); 217int build_id__sprintf(const u8 *self, int len, char *bf);
216int kallsyms__parse(const char *filename, void *arg, 218int kallsyms__parse(const char *filename, void *arg,
217 int (*process_symbol)(void *arg, const char *name, 219 int (*process_symbol)(void *arg, const char *name,
218 char type, u64 start)); 220 char type, u64 start, u64 end));
219 221
220void machine__destroy_kernel_maps(struct machine *self); 222void machine__destroy_kernel_maps(struct machine *self);
221int __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/ui/util.c b/tools/perf/util/ui/util.c
index 056c69521a38..7b5a8926624e 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -104,10 +104,24 @@ out_destroy_form:
104 return rc; 104 return rc;
105} 105}
106 106
107static const char yes[] = "Yes", no[] = "No"; 107static const char yes[] = "Yes", no[] = "No",
108 warning_str[] = "Warning!", ok[] = "Ok";
108 109
109bool ui__dialog_yesno(const char *msg) 110bool ui__dialog_yesno(const char *msg)
110{ 111{
111 /* newtWinChoice should really be accepting const char pointers... */ 112 /* newtWinChoice should really be accepting const char pointers... */
112 return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1; 113 return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1;
113} 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);
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/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/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}