aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-03-31 02:33:43 -0400
committerIngo Molnar <mingo@kernel.org>2016-03-31 02:33:43 -0400
commit643cb15ba07260faadd9fcfabac4f5d9d0ddc053 (patch)
treee57bb3a38ed43eb91daac81c0818ba614e6d6bac
parentc932cf07ddc02f79e093596924e41cf6d7fda509 (diff)
parentd1706b39f0af6901ab2a5e2ebb210b53c1a5bdc7 (diff)
Merge tag 'perf-core-for-mingo-20160330' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes: User visible changes: - Add support for skipping itrace instructions, useful to fast forward processor trace (Intel PT, BTS) to right after initialization code at the start of a workload (Andi Kleen) - Add support for backtraces in perl 'perf script's (Dima Kogan) - Add -U/-K (--all-user/--all-kernel) options to 'perf mem' (Jiri Olsa) - Make -f/--force option documentation consistent across tools (Jiri Olsa) Infrastructure changes: - Add 'perf test' to check for event times (Jiri Olsa) - 'perf config' cleanups (Taeung Song) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/Documentation/intel-pt.txt7
-rw-r--r--tools/perf/Documentation/itrace.txt8
-rw-r--r--tools/perf/Documentation/perf-annotate.txt2
-rw-r--r--tools/perf/Documentation/perf-diff.txt2
-rw-r--r--tools/perf/Documentation/perf-mem.txt8
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt4
-rw-r--r--tools/perf/builtin-mem.c11
-rw-r--r--tools/perf/perf.c3
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/event-times.c236
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/util/auxtrace.c7
-rw-r--r--tools/perf/util/auxtrace.h2
-rw-r--r--tools/perf/util/config.c57
-rw-r--r--tools/perf/util/hist.c5
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/intel-bts.c5
-rw-r--r--tools/perf/util/intel-pt.c22
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c114
21 files changed, 448 insertions, 55 deletions
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index be764f9ec769..c6c8318e38a2 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -672,6 +672,7 @@ The letters are:
672 d create a debug log 672 d create a debug log
673 g synthesize a call chain (use with i or x) 673 g synthesize a call chain (use with i or x)
674 l synthesize last branch entries (use with i or x) 674 l synthesize last branch entries (use with i or x)
675 s skip initial number of events
675 676
676"Instructions" events look like they were recorded by "perf record -e 677"Instructions" events look like they were recorded by "perf record -e
677instructions". 678instructions".
@@ -730,6 +731,12 @@ from one sample to the next.
730 731
731To disable trace decoding entirely, use the option --no-itrace. 732To disable trace decoding entirely, use the option --no-itrace.
732 733
734It is also possible to skip events generated (instructions, branches, transactions)
735at the beginning. This is useful to ignore initialization code.
736
737 --itrace=i0nss1000000
738
739skips the first million instructions.
733 740
734dump option 741dump option
735----------- 742-----------
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index 65453f4c7006..e2a4c5e0dbe5 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -7,6 +7,7 @@
7 d create a debug log 7 d create a debug log
8 g synthesize a call chain (use with i or x) 8 g synthesize a call chain (use with i or x)
9 l synthesize last branch entries (use with i or x) 9 l synthesize last branch entries (use with i or x)
10 s skip initial number of events
10 11
11 The default is all events i.e. the same as --itrace=ibxe 12 The default is all events i.e. the same as --itrace=ibxe
12 13
@@ -24,3 +25,10 @@
24 25
25 Also the number of last branch entries (default 64, max. 1024) for 26 Also the number of last branch entries (default 64, max. 1024) for
26 instructions or transactions events can be specified. 27 instructions or transactions events can be specified.
28
29 It is also possible to skip events generated (instructions, branches, transactions)
30 at the beginning. This is useful to ignore initialization code.
31
32 --itrace=i0nss1000000
33
34 skips the first million instructions.
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index e9cd39a92dc2..778f54d4d0bd 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -33,7 +33,7 @@ OPTIONS
33 33
34-f:: 34-f::
35--force:: 35--force::
36 Don't complain, do it. 36 Don't do ownership validation.
37 37
38-v:: 38-v::
39--verbose:: 39--verbose::
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index d1deb573877f..3e9490b9c533 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -75,7 +75,7 @@ OPTIONS
75 75
76-f:: 76-f::
77--force:: 77--force::
78 Don't complain, do it. 78 Don't do ownership validation.
79 79
80--symfs=<directory>:: 80--symfs=<directory>::
81 Look for files with symbols relative to this directory. 81 Look for files with symbols relative to this directory.
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 43310d8661fe..1d6092c460dd 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -48,6 +48,14 @@ OPTIONS
48 option can be passed in record mode. It will be interpreted the same way as perf 48 option can be passed in record mode. It will be interpreted the same way as perf
49 record. 49 record.
50 50
51-K::
52--all-kernel::
53 Configure all used events to run in kernel space.
54
55-U::
56--all-user::
57 Configure all used events to run in user space.
58
51SEE ALSO 59SEE ALSO
52-------- 60--------
53linkperf:perf-record[1], linkperf:perf-report[1] 61linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 12113992ac9d..496d42cdf02b 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -285,7 +285,7 @@ OPTIONS
285 285
286-f:: 286-f::
287--force:: 287--force::
288 Don't complain, do it. 288 Don't do ownership validation.
289 289
290--symfs=<directory>:: 290--symfs=<directory>::
291 Look for files with symbols relative to this directory. 291 Look for files with symbols relative to this directory.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 382ddfb45d1d..22ef3933342a 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -262,6 +262,10 @@ include::itrace.txt[]
262--ns:: 262--ns::
263 Use 9 decimal places when displaying time (i.e. show the nanoseconds) 263 Use 9 decimal places when displaying time (i.e. show the nanoseconds)
264 264
265-f::
266--force::
267 Don't do ownership validation.
268
265SEE ALSO 269SEE ALSO
266-------- 270--------
267linkperf:perf-record[1], linkperf:perf-script-perl[1], 271linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 85db3be4b3cb..1dc140c5481d 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -62,19 +62,22 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
62 int rec_argc, i = 0, j; 62 int rec_argc, i = 0, j;
63 const char **rec_argv; 63 const char **rec_argv;
64 int ret; 64 int ret;
65 bool all_user = false, all_kernel = false;
65 struct option options[] = { 66 struct option options[] = {
66 OPT_CALLBACK('e', "event", &mem, "event", 67 OPT_CALLBACK('e', "event", &mem, "event",
67 "event selector. use 'perf mem record -e list' to list available events", 68 "event selector. use 'perf mem record -e list' to list available events",
68 parse_record_events), 69 parse_record_events),
69 OPT_INCR('v', "verbose", &verbose, 70 OPT_INCR('v', "verbose", &verbose,
70 "be more verbose (show counter open errors, etc)"), 71 "be more verbose (show counter open errors, etc)"),
72 OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"),
73 OPT_BOOLEAN('K', "--all-kernel", &all_kernel, "collect only kernel level data"),
71 OPT_END() 74 OPT_END()
72 }; 75 };
73 76
74 argc = parse_options(argc, argv, options, record_mem_usage, 77 argc = parse_options(argc, argv, options, record_mem_usage,
75 PARSE_OPT_STOP_AT_NON_OPTION); 78 PARSE_OPT_STOP_AT_NON_OPTION);
76 79
77 rec_argc = argc + 7; /* max number of arguments */ 80 rec_argc = argc + 9; /* max number of arguments */
78 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 81 rec_argv = calloc(rec_argc + 1, sizeof(char *));
79 if (!rec_argv) 82 if (!rec_argv)
80 return -1; 83 return -1;
@@ -103,6 +106,12 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
103 rec_argv[i++] = perf_mem_events__name(j); 106 rec_argv[i++] = perf_mem_events__name(j);
104 }; 107 };
105 108
109 if (all_user)
110 rec_argv[i++] = "--all-user";
111
112 if (all_kernel)
113 rec_argv[i++] = "--all-kernel";
114
106 for (j = 0; j < argc; j++, i++) 115 for (j = 0; j < argc; j++, i++)
107 rec_argv[i] = argv[j]; 116 rec_argv[i] = argv[j];
108 117
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index aaee0a782747..7b2df2b46525 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -549,6 +549,7 @@ int main(int argc, const char **argv)
549 srandom(time(NULL)); 549 srandom(time(NULL));
550 550
551 perf_config(perf_default_config, NULL); 551 perf_config(perf_default_config, NULL);
552 set_buildid_dir(NULL);
552 553
553 /* get debugfs/tracefs mount point from /proc/mounts */ 554 /* get debugfs/tracefs mount point from /proc/mounts */
554 tracing_path_mount(); 555 tracing_path_mount();
@@ -572,7 +573,6 @@ int main(int argc, const char **argv)
572 } 573 }
573 if (!prefixcmp(cmd, "trace")) { 574 if (!prefixcmp(cmd, "trace")) {
574#ifdef HAVE_LIBAUDIT_SUPPORT 575#ifdef HAVE_LIBAUDIT_SUPPORT
575 set_buildid_dir(NULL);
576 setup_path(); 576 setup_path();
577 argv[0] = "trace"; 577 argv[0] = "trace";
578 return cmd_trace(argc, argv, NULL); 578 return cmd_trace(argc, argv, NULL);
@@ -587,7 +587,6 @@ int main(int argc, const char **argv)
587 argc--; 587 argc--;
588 handle_options(&argv, &argc, NULL); 588 handle_options(&argv, &argc, NULL);
589 commit_pager_choice(); 589 commit_pager_choice();
590 set_buildid_dir(NULL);
591 590
592 if (argc > 0) { 591 if (argc > 0) {
593 if (!prefixcmp(argv[0], "--")) 592 if (!prefixcmp(argv[0], "--"))
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 1ba628ed049a..449fe97a555f 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -37,6 +37,7 @@ perf-y += topology.o
37perf-y += cpumap.o 37perf-y += cpumap.o
38perf-y += stat.o 38perf-y += stat.o
39perf-y += event_update.o 39perf-y += event_update.o
40perf-y += event-times.o
40 41
41$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 42$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
42 $(call rule_mkdir) 43 $(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index f2b1dcac45d3..93c467015e71 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -204,6 +204,10 @@ static struct test generic_tests[] = {
204 .func = test__event_update, 204 .func = test__event_update,
205 }, 205 },
206 { 206 {
207 .desc = "Test events times",
208 .func = test__event_times,
209 },
210 {
207 .func = NULL, 211 .func = NULL,
208 }, 212 },
209}; 213};
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
new file mode 100644
index 000000000000..95fb744f6628
--- /dev/null
+++ b/tools/perf/tests/event-times.c
@@ -0,0 +1,236 @@
1#include <linux/compiler.h>
2#include <string.h>
3#include "tests.h"
4#include "evlist.h"
5#include "evsel.h"
6#include "util.h"
7#include "debug.h"
8#include "thread_map.h"
9#include "target.h"
10
11static int attach__enable_on_exec(struct perf_evlist *evlist)
12{
13 struct perf_evsel *evsel = perf_evlist__last(evlist);
14 struct target target = {
15 .uid = UINT_MAX,
16 };
17 const char *argv[] = { "true", NULL, };
18 char sbuf[STRERR_BUFSIZE];
19 int err;
20
21 pr_debug("attaching to spawned child, enable on exec\n");
22
23 err = perf_evlist__create_maps(evlist, &target);
24 if (err < 0) {
25 pr_debug("Not enough memory to create thread/cpu maps\n");
26 return err;
27 }
28
29 err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL);
30 if (err < 0) {
31 pr_debug("Couldn't run the workload!\n");
32 return err;
33 }
34
35 evsel->attr.enable_on_exec = 1;
36
37 err = perf_evlist__open(evlist);
38 if (err < 0) {
39 pr_debug("perf_evlist__open: %s\n",
40 strerror_r(errno, sbuf, sizeof(sbuf)));
41 return err;
42 }
43
44 return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
45}
46
47static int detach__enable_on_exec(struct perf_evlist *evlist)
48{
49 waitpid(evlist->workload.pid, NULL, 0);
50 return 0;
51}
52
53static int attach__current_disabled(struct perf_evlist *evlist)
54{
55 struct perf_evsel *evsel = perf_evlist__last(evlist);
56 struct thread_map *threads;
57 int err;
58
59 pr_debug("attaching to current thread as disabled\n");
60
61 threads = thread_map__new(-1, getpid(), UINT_MAX);
62 if (threads == NULL) {
63 pr_debug("thread_map__new\n");
64 return -1;
65 }
66
67 evsel->attr.disabled = 1;
68
69 err = perf_evsel__open_per_thread(evsel, threads);
70 if (err) {
71 pr_debug("Failed to open event cpu-clock:u\n");
72 return err;
73 }
74
75 thread_map__put(threads);
76 return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
77}
78
79static int attach__current_enabled(struct perf_evlist *evlist)
80{
81 struct perf_evsel *evsel = perf_evlist__last(evlist);
82 struct thread_map *threads;
83 int err;
84
85 pr_debug("attaching to current thread as enabled\n");
86
87 threads = thread_map__new(-1, getpid(), UINT_MAX);
88 if (threads == NULL) {
89 pr_debug("failed to call thread_map__new\n");
90 return -1;
91 }
92
93 err = perf_evsel__open_per_thread(evsel, threads);
94
95 thread_map__put(threads);
96 return err == 0 ? TEST_OK : TEST_FAIL;
97}
98
99static int detach__disable(struct perf_evlist *evlist)
100{
101 struct perf_evsel *evsel = perf_evlist__last(evlist);
102
103 return perf_evsel__enable(evsel);
104}
105
106static int attach__cpu_disabled(struct perf_evlist *evlist)
107{
108 struct perf_evsel *evsel = perf_evlist__last(evlist);
109 struct cpu_map *cpus;
110 int err;
111
112 pr_debug("attaching to CPU 0 as enabled\n");
113
114 cpus = cpu_map__new("0");
115 if (cpus == NULL) {
116 pr_debug("failed to call cpu_map__new\n");
117 return -1;
118 }
119
120 evsel->attr.disabled = 1;
121
122 err = perf_evsel__open_per_cpu(evsel, cpus);
123 if (err) {
124 if (err == -EACCES)
125 return TEST_SKIP;
126
127 pr_debug("Failed to open event cpu-clock:u\n");
128 return err;
129 }
130
131 cpu_map__put(cpus);
132 return perf_evsel__enable(evsel);
133}
134
135static int attach__cpu_enabled(struct perf_evlist *evlist)
136{
137 struct perf_evsel *evsel = perf_evlist__last(evlist);
138 struct cpu_map *cpus;
139 int err;
140
141 pr_debug("attaching to CPU 0 as enabled\n");
142
143 cpus = cpu_map__new("0");
144 if (cpus == NULL) {
145 pr_debug("failed to call cpu_map__new\n");
146 return -1;
147 }
148
149 err = perf_evsel__open_per_cpu(evsel, cpus);
150 if (err == -EACCES)
151 return TEST_SKIP;
152
153 cpu_map__put(cpus);
154 return err ? TEST_FAIL : TEST_OK;
155}
156
157static int test_times(int (attach)(struct perf_evlist *),
158 int (detach)(struct perf_evlist *))
159{
160 struct perf_counts_values count;
161 struct perf_evlist *evlist = NULL;
162 struct perf_evsel *evsel;
163 int err = -1, i;
164
165 evlist = perf_evlist__new();
166 if (!evlist) {
167 pr_debug("failed to create event list\n");
168 goto out_err;
169 }
170
171 err = parse_events(evlist, "cpu-clock:u", NULL);
172 if (err) {
173 pr_debug("failed to parse event cpu-clock:u\n");
174 goto out_err;
175 }
176
177 evsel = perf_evlist__last(evlist);
178 evsel->attr.read_format |=
179 PERF_FORMAT_TOTAL_TIME_ENABLED |
180 PERF_FORMAT_TOTAL_TIME_RUNNING;
181
182 err = attach(evlist);
183 if (err == TEST_SKIP) {
184 pr_debug(" SKIP : not enough rights\n");
185 return err;
186 }
187
188 TEST_ASSERT_VAL("failed to attach", !err);
189
190 for (i = 0; i < 100000000; i++) { }
191
192 TEST_ASSERT_VAL("failed to detach", !detach(evlist));
193
194 perf_evsel__read(evsel, 0, 0, &count);
195
196 err = !(count.ena == count.run);
197
198 pr_debug(" %s: ena %" PRIu64", run %" PRIu64"\n",
199 !err ? "OK " : "FAILED",
200 count.ena, count.run);
201
202out_err:
203 if (evlist)
204 perf_evlist__delete(evlist);
205 return !err ? TEST_OK : TEST_FAIL;
206}
207
208/*
209 * This test creates software event 'cpu-clock'
210 * attaches it in several ways (explained below)
211 * and checks that enabled and running times
212 * match.
213 */
214int test__event_times(int subtest __maybe_unused)
215{
216 int err, ret = 0;
217
218#define _T(attach, detach) \
219 err = test_times(attach, detach); \
220 if (err && (ret == TEST_OK || ret == TEST_SKIP)) \
221 ret = err;
222
223 /* attach on newly spawned process after exec */
224 _T(attach__enable_on_exec, detach__enable_on_exec)
225 /* attach on current process as enabled */
226 _T(attach__current_enabled, detach__disable)
227 /* attach on current process as disabled */
228 _T(attach__current_disabled, detach__disable)
229 /* attach on cpu as disabled */
230 _T(attach__cpu_disabled, detach__disable)
231 /* attach on cpu as enabled */
232 _T(attach__cpu_enabled, detach__disable)
233
234#undef _T
235 return ret;
236}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 82b2b5e6ba7c..0fc946989cf0 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -85,6 +85,7 @@ int test__synthesize_stat_config(int subtest);
85int test__synthesize_stat(int subtest); 85int test__synthesize_stat(int subtest);
86int test__synthesize_stat_round(int subtest); 86int test__synthesize_stat_round(int subtest);
87int test__event_update(int subtest); 87int test__event_update(int subtest);
88int test__event_times(int subtest);
88 89
89#if defined(__arm__) || defined(__aarch64__) 90#if defined(__arm__) || defined(__aarch64__)
90#ifdef HAVE_DWARF_UNWIND_SUPPORT 91#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index ec164fe70718..c9169011e55e 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -940,6 +940,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
940 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 940 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
941 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; 941 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
942 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ; 942 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
943 synth_opts->initial_skip = 0;
943} 944}
944 945
945/* 946/*
@@ -1064,6 +1065,12 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
1064 synth_opts->last_branch_sz = val; 1065 synth_opts->last_branch_sz = val;
1065 } 1066 }
1066 break; 1067 break;
1068 case 's':
1069 synth_opts->initial_skip = strtoul(p, &endptr, 10);
1070 if (p == endptr)
1071 goto out_err;
1072 p = endptr;
1073 break;
1067 case ' ': 1074 case ' ':
1068 case ',': 1075 case ',':
1069 break; 1076 break;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 57ff31ecb8e4..767989e0e312 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -68,6 +68,7 @@ enum itrace_period_type {
68 * @last_branch_sz: branch context size 68 * @last_branch_sz: branch context size
69 * @period: 'instructions' events period 69 * @period: 'instructions' events period
70 * @period_type: 'instructions' events period type 70 * @period_type: 'instructions' events period type
71 * @initial_skip: skip N events at the beginning.
71 */ 72 */
72struct itrace_synth_opts { 73struct itrace_synth_opts {
73 bool set; 74 bool set;
@@ -86,6 +87,7 @@ struct itrace_synth_opts {
86 unsigned int last_branch_sz; 87 unsigned int last_branch_sz;
87 unsigned long long period; 88 unsigned long long period;
88 enum itrace_period_type period_type; 89 enum itrace_period_type period_type;
90 unsigned long initial_skip;
89}; 91};
90 92
91/** 93/**
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 4e727635476e..5c20d783423b 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -377,6 +377,21 @@ const char *perf_config_dirname(const char *name, const char *value)
377 return value; 377 return value;
378} 378}
379 379
380static int perf_buildid_config(const char *var, const char *value)
381{
382 /* same dir for all commands */
383 if (!strcmp(var, "buildid.dir")) {
384 const char *dirname = perf_config_dirname(var, value);
385
386 if (!dirname)
387 return -1;
388 strncpy(buildid_dir, dirname, MAXPATHLEN-1);
389 buildid_dir[MAXPATHLEN-1] = '\0';
390 }
391
392 return 0;
393}
394
380static int perf_default_core_config(const char *var __maybe_unused, 395static int perf_default_core_config(const char *var __maybe_unused,
381 const char *value __maybe_unused) 396 const char *value __maybe_unused)
382{ 397{
@@ -412,6 +427,9 @@ int perf_default_config(const char *var, const char *value,
412 if (!prefixcmp(var, "llvm.")) 427 if (!prefixcmp(var, "llvm."))
413 return perf_llvm_config(var, value); 428 return perf_llvm_config(var, value);
414 429
430 if (!prefixcmp(var, "buildid."))
431 return perf_buildid_config(var, value);
432
415 /* Add other config variables here. */ 433 /* Add other config variables here. */
416 return 0; 434 return 0;
417} 435}
@@ -515,49 +533,18 @@ int config_error_nonbool(const char *var)
515 return error("Missing value for '%s'", var); 533 return error("Missing value for '%s'", var);
516} 534}
517 535
518struct buildid_dir_config {
519 char *dir;
520};
521
522static int buildid_dir_command_config(const char *var, const char *value,
523 void *data)
524{
525 struct buildid_dir_config *c = data;
526 const char *v;
527
528 /* same dir for all commands */
529 if (!strcmp(var, "buildid.dir")) {
530 v = perf_config_dirname(var, value);
531 if (!v)
532 return -1;
533 strncpy(c->dir, v, MAXPATHLEN-1);
534 c->dir[MAXPATHLEN-1] = '\0';
535 }
536 return 0;
537}
538
539static void check_buildid_dir_config(void)
540{
541 struct buildid_dir_config c;
542 c.dir = buildid_dir;
543 perf_config(buildid_dir_command_config, &c);
544}
545
546void set_buildid_dir(const char *dir) 536void set_buildid_dir(const char *dir)
547{ 537{
548 if (dir) 538 if (dir)
549 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); 539 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir);
550 540
551 /* try config file */
552 if (buildid_dir[0] == '\0')
553 check_buildid_dir_config();
554
555 /* default to $HOME/.debug */ 541 /* default to $HOME/.debug */
556 if (buildid_dir[0] == '\0') { 542 if (buildid_dir[0] == '\0') {
557 char *v = getenv("HOME"); 543 char *home = getenv("HOME");
558 if (v) { 544
545 if (home) {
559 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", 546 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s",
560 v, DEBUG_CACHE_DIR); 547 home, DEBUG_CACHE_DIR);
561 } else { 548 } else {
562 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); 549 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1);
563 } 550 }
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 31c4641fe5ff..3d34c57dfbe2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1295,8 +1295,9 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
1295 return ret; 1295 return ret;
1296} 1296}
1297 1297
1298int hists__collapse_insert_entry(struct hists *hists, struct rb_root *root, 1298static int hists__collapse_insert_entry(struct hists *hists,
1299 struct hist_entry *he) 1299 struct rb_root *root,
1300 struct hist_entry *he)
1300{ 1301{
1301 struct rb_node **p = &root->rb_node; 1302 struct rb_node **p = &root->rb_node;
1302 struct rb_node *parent = NULL; 1303 struct rb_node *parent = NULL;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index bec0cd660fbd..588596561cb3 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -199,8 +199,6 @@ int hists__init(void);
199int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); 199int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list);
200 200
201struct rb_root *hists__get_rotate_entries_in(struct hists *hists); 201struct rb_root *hists__get_rotate_entries_in(struct hists *hists);
202int hists__collapse_insert_entry(struct hists *hists,
203 struct rb_root *root, struct hist_entry *he);
204 202
205struct perf_hpp { 203struct perf_hpp {
206 char *buf; 204 char *buf;
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index abf1366e2a24..9df996085563 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -66,6 +66,7 @@ struct intel_bts {
66 u64 branches_id; 66 u64 branches_id;
67 size_t branches_event_size; 67 size_t branches_event_size;
68 bool synth_needs_swap; 68 bool synth_needs_swap;
69 unsigned long num_events;
69}; 70};
70 71
71struct intel_bts_queue { 72struct intel_bts_queue {
@@ -275,6 +276,10 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
275 union perf_event event; 276 union perf_event event;
276 struct perf_sample sample = { .ip = 0, }; 277 struct perf_sample sample = { .ip = 0, };
277 278
279 if (bts->synth_opts.initial_skip &&
280 bts->num_events++ <= bts->synth_opts.initial_skip)
281 return 0;
282
278 event.sample.header.type = PERF_RECORD_SAMPLE; 283 event.sample.header.type = PERF_RECORD_SAMPLE;
279 event.sample.header.misc = PERF_RECORD_MISC_USER; 284 event.sample.header.misc = PERF_RECORD_MISC_USER;
280 event.sample.header.size = sizeof(struct perf_event_header); 285 event.sample.header.size = sizeof(struct perf_event_header);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 407f11b97c8d..ddec87f6e616 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -100,6 +100,8 @@ struct intel_pt {
100 u64 cyc_bit; 100 u64 cyc_bit;
101 u64 noretcomp_bit; 101 u64 noretcomp_bit;
102 unsigned max_non_turbo_ratio; 102 unsigned max_non_turbo_ratio;
103
104 unsigned long num_events;
103}; 105};
104 106
105enum switch_state { 107enum switch_state {
@@ -972,6 +974,10 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
972 if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) 974 if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
973 return 0; 975 return 0;
974 976
977 if (pt->synth_opts.initial_skip &&
978 pt->num_events++ < pt->synth_opts.initial_skip)
979 return 0;
980
975 event->sample.header.type = PERF_RECORD_SAMPLE; 981 event->sample.header.type = PERF_RECORD_SAMPLE;
976 event->sample.header.misc = PERF_RECORD_MISC_USER; 982 event->sample.header.misc = PERF_RECORD_MISC_USER;
977 event->sample.header.size = sizeof(struct perf_event_header); 983 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1029,6 +1035,10 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
1029 union perf_event *event = ptq->event_buf; 1035 union perf_event *event = ptq->event_buf;
1030 struct perf_sample sample = { .ip = 0, }; 1036 struct perf_sample sample = { .ip = 0, };
1031 1037
1038 if (pt->synth_opts.initial_skip &&
1039 pt->num_events++ < pt->synth_opts.initial_skip)
1040 return 0;
1041
1032 event->sample.header.type = PERF_RECORD_SAMPLE; 1042 event->sample.header.type = PERF_RECORD_SAMPLE;
1033 event->sample.header.misc = PERF_RECORD_MISC_USER; 1043 event->sample.header.misc = PERF_RECORD_MISC_USER;
1034 event->sample.header.size = sizeof(struct perf_event_header); 1044 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1087,6 +1097,10 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1087 union perf_event *event = ptq->event_buf; 1097 union perf_event *event = ptq->event_buf;
1088 struct perf_sample sample = { .ip = 0, }; 1098 struct perf_sample sample = { .ip = 0, };
1089 1099
1100 if (pt->synth_opts.initial_skip &&
1101 pt->num_events++ < pt->synth_opts.initial_skip)
1102 return 0;
1103
1090 event->sample.header.type = PERF_RECORD_SAMPLE; 1104 event->sample.header.type = PERF_RECORD_SAMPLE;
1091 event->sample.header.misc = PERF_RECORD_MISC_USER; 1105 event->sample.header.misc = PERF_RECORD_MISC_USER;
1092 event->sample.header.size = sizeof(struct perf_event_header); 1106 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1199,14 +1213,18 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1199 ptq->have_sample = false; 1213 ptq->have_sample = false;
1200 1214
1201 if (pt->sample_instructions && 1215 if (pt->sample_instructions &&
1202 (state->type & INTEL_PT_INSTRUCTION)) { 1216 (state->type & INTEL_PT_INSTRUCTION) &&
1217 (!pt->synth_opts.initial_skip ||
1218 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1203 err = intel_pt_synth_instruction_sample(ptq); 1219 err = intel_pt_synth_instruction_sample(ptq);
1204 if (err) 1220 if (err)
1205 return err; 1221 return err;
1206 } 1222 }
1207 1223
1208 if (pt->sample_transactions && 1224 if (pt->sample_transactions &&
1209 (state->type & INTEL_PT_TRANSACTION)) { 1225 (state->type & INTEL_PT_TRANSACTION) &&
1226 (!pt->synth_opts.initial_skip ||
1227 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1210 err = intel_pt_synth_transaction_sample(ptq); 1228 err = intel_pt_synth_transaction_sample(ptq);
1211 if (err) 1229 if (err)
1212 return err; 1230 return err;
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b3aabc0d4eb0..1d160855cda9 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -31,6 +31,8 @@
31#include <perl.h> 31#include <perl.h>
32 32
33#include "../../perf.h" 33#include "../../perf.h"
34#include "../callchain.h"
35#include "../machine.h"
34#include "../thread.h" 36#include "../thread.h"
35#include "../event.h" 37#include "../event.h"
36#include "../trace-event.h" 38#include "../trace-event.h"
@@ -248,10 +250,78 @@ static void define_event_symbols(struct event_format *event,
248 define_event_symbols(event, ev_name, args->next); 250 define_event_symbols(event, ev_name, args->next);
249} 251}
250 252
253static SV *perl_process_callchain(struct perf_sample *sample,
254 struct perf_evsel *evsel,
255 struct addr_location *al)
256{
257 AV *list;
258
259 list = newAV();
260 if (!list)
261 goto exit;
262
263 if (!symbol_conf.use_callchain || !sample->callchain)
264 goto exit;
265
266 if (thread__resolve_callchain(al->thread, evsel,
267 sample, NULL, NULL,
268 PERF_MAX_STACK_DEPTH) != 0) {
269 pr_err("Failed to resolve callchain. Skipping\n");
270 goto exit;
271 }
272 callchain_cursor_commit(&callchain_cursor);
273
274
275 while (1) {
276 HV *elem;
277 struct callchain_cursor_node *node;
278 node = callchain_cursor_current(&callchain_cursor);
279 if (!node)
280 break;
281
282 elem = newHV();
283 if (!elem)
284 goto exit;
285
286 hv_stores(elem, "ip", newSVuv(node->ip));
287
288 if (node->sym) {
289 HV *sym = newHV();
290 if (!sym)
291 goto exit;
292 hv_stores(sym, "start", newSVuv(node->sym->start));
293 hv_stores(sym, "end", newSVuv(node->sym->end));
294 hv_stores(sym, "binding", newSVuv(node->sym->binding));
295 hv_stores(sym, "name", newSVpvn(node->sym->name,
296 node->sym->namelen));
297 hv_stores(elem, "sym", newRV_noinc((SV*)sym));
298 }
299
300 if (node->map) {
301 struct map *map = node->map;
302 const char *dsoname = "[unknown]";
303 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
304 if (symbol_conf.show_kernel_path && map->dso->long_name)
305 dsoname = map->dso->long_name;
306 else if (map->dso->name)
307 dsoname = map->dso->name;
308 }
309 hv_stores(elem, "dso", newSVpv(dsoname,0));
310 }
311
312 callchain_cursor_advance(&callchain_cursor);
313 av_push(list, newRV_noinc((SV*)elem));
314 }
315
316exit:
317 return newRV_noinc((SV*)list);
318}
319
251static void perl_process_tracepoint(struct perf_sample *sample, 320static void perl_process_tracepoint(struct perf_sample *sample,
252 struct perf_evsel *evsel, 321 struct perf_evsel *evsel,
253 struct thread *thread) 322 struct addr_location *al)
254{ 323{
324 struct thread *thread = al->thread;
255 struct event_format *event = evsel->tp_format; 325 struct event_format *event = evsel->tp_format;
256 struct format_field *field; 326 struct format_field *field;
257 static char handler[256]; 327 static char handler[256];
@@ -295,6 +365,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
295 XPUSHs(sv_2mortal(newSVuv(ns))); 365 XPUSHs(sv_2mortal(newSVuv(ns)));
296 XPUSHs(sv_2mortal(newSViv(pid))); 366 XPUSHs(sv_2mortal(newSViv(pid)));
297 XPUSHs(sv_2mortal(newSVpv(comm, 0))); 367 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
368 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
298 369
299 /* common fields other than pid can be accessed via xsub fns */ 370 /* common fields other than pid can be accessed via xsub fns */
300 371
@@ -329,6 +400,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
329 XPUSHs(sv_2mortal(newSVuv(nsecs))); 400 XPUSHs(sv_2mortal(newSVuv(nsecs)));
330 XPUSHs(sv_2mortal(newSViv(pid))); 401 XPUSHs(sv_2mortal(newSViv(pid)));
331 XPUSHs(sv_2mortal(newSVpv(comm, 0))); 402 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
403 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
332 call_pv("main::trace_unhandled", G_SCALAR); 404 call_pv("main::trace_unhandled", G_SCALAR);
333 } 405 }
334 SPAGAIN; 406 SPAGAIN;
@@ -366,7 +438,7 @@ static void perl_process_event(union perf_event *event,
366 struct perf_evsel *evsel, 438 struct perf_evsel *evsel,
367 struct addr_location *al) 439 struct addr_location *al)
368{ 440{
369 perl_process_tracepoint(sample, evsel, al->thread); 441 perl_process_tracepoint(sample, evsel, al);
370 perl_process_event_generic(event, sample, evsel); 442 perl_process_event_generic(event, sample, evsel);
371} 443}
372 444
@@ -490,7 +562,27 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
490 fprintf(ofp, "use Perf::Trace::Util;\n\n"); 562 fprintf(ofp, "use Perf::Trace::Util;\n\n");
491 563
492 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n"); 564 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
493 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n"); 565 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n");
566
567
568 fprintf(ofp, "\n\
569sub print_backtrace\n\
570{\n\
571 my $callchain = shift;\n\
572 for my $node (@$callchain)\n\
573 {\n\
574 if(exists $node->{sym})\n\
575 {\n\
576 printf( \"\\t[\\%%x] \\%%s\\n\", $node->{ip}, $node->{sym}{name});\n\
577 }\n\
578 else\n\
579 {\n\
580 printf( \"\\t[\\%%x]\\n\", $node{ip});\n\
581 }\n\
582 }\n\
583}\n\n\
584");
585
494 586
495 while ((event = trace_find_next_event(pevent, event))) { 587 while ((event = trace_find_next_event(pevent, event))) {
496 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name); 588 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
@@ -502,7 +594,8 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
502 fprintf(ofp, "$common_secs, "); 594 fprintf(ofp, "$common_secs, ");
503 fprintf(ofp, "$common_nsecs,\n"); 595 fprintf(ofp, "$common_nsecs,\n");
504 fprintf(ofp, "\t $common_pid, "); 596 fprintf(ofp, "\t $common_pid, ");
505 fprintf(ofp, "$common_comm,\n\t "); 597 fprintf(ofp, "$common_comm, ");
598 fprintf(ofp, "$common_callchain,\n\t ");
506 599
507 not_first = 0; 600 not_first = 0;
508 count = 0; 601 count = 0;
@@ -519,7 +612,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
519 612
520 fprintf(ofp, "\tprint_header($event_name, $common_cpu, " 613 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
521 "$common_secs, $common_nsecs,\n\t " 614 "$common_secs, $common_nsecs,\n\t "
522 "$common_pid, $common_comm);\n\n"); 615 "$common_pid, $common_comm, $common_callchain);\n\n");
523 616
524 fprintf(ofp, "\tprintf(\""); 617 fprintf(ofp, "\tprintf(\"");
525 618
@@ -581,17 +674,22 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
581 fprintf(ofp, "$%s", f->name); 674 fprintf(ofp, "$%s", f->name);
582 } 675 }
583 676
584 fprintf(ofp, ");\n"); 677 fprintf(ofp, ");\n\n");
678
679 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
680
585 fprintf(ofp, "}\n\n"); 681 fprintf(ofp, "}\n\n");
586 } 682 }
587 683
588 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, " 684 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
589 "$common_cpu, $common_secs, $common_nsecs,\n\t " 685 "$common_cpu, $common_secs, $common_nsecs,\n\t "
590 "$common_pid, $common_comm) = @_;\n\n"); 686 "$common_pid, $common_comm, $common_callchain) = @_;\n\n");
591 687
592 fprintf(ofp, "\tprint_header($event_name, $common_cpu, " 688 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
593 "$common_secs, $common_nsecs,\n\t $common_pid, " 689 "$common_secs, $common_nsecs,\n\t $common_pid, "
594 "$common_comm);\n}\n\n"); 690 "$common_comm, $common_callchain);\n");
691 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
692 fprintf(ofp, "}\n\n");
595 693
596 fprintf(ofp, "sub print_header\n{\n" 694 fprintf(ofp, "sub print_header\n{\n"
597 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" 695 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"