aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-09-29 03:43:46 -0400
committerIngo Molnar <mingo@kernel.org>2015-09-29 03:43:46 -0400
commit9c17dbc6eb73bdd8a6aaea1baefd37ff78d86148 (patch)
tree5b303f98bc8898f26d2445138904f2fb14403a2d
parent18ab2cd3ee9d52dc64c5ae984146a261a328c4e8 (diff)
parente637d17757a10732fa5d573c18f20b3cd4d31245 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: - Accept a zero --itrace period, meaning "as often as possible". In the case of Intel PT that is the same as a period of 1 and a unit of 'instructions' (i.e. --itrace=i1i). (Adrian Hunter) - Harmonize itrace's synthesized callchains with the existing --max-stack tool option. (Adrian Hunter) - Allow time to be displayed in nanoseconds in 'perf script'. (Adrian Hunter) - Fix potential infinite loop when handling Intel PT timestamps. (Adrian Hunter) - Slighly improve Intel PT debug logging. (Adrian Hunter) - Warn when AUX data has been lost, just like when processing PERF_RECORD_LOST. (Adrian Hunter) - Further document export-to-postgresql.py script. (Adrian Hunter) - Add option to synthesize branch stack from auxtrace data. (Adrian Hunter) - Use equivalent logic to avoid using dso->kernel. (Arnaldo Carvalho de Melo) - Show proper error messages when parsing bad terms for hw/sw events. (He Kuang) - Tracepoint event parsing improvements. (He Kuang) - Store tracing mountpoint for better error message. (Jiri Olsa) - Add fixdep to tools/build, bringing it closer to the kernel counterpart, from where it is being lifted. (Jiri Olsa) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/build/Build1
-rw-r--r--tools/build/Build.include17
-rw-r--r--tools/build/Documentation/Build.txt52
-rw-r--r--tools/build/Makefile43
-rw-r--r--tools/build/Makefile.build7
-rw-r--r--tools/build/Makefile.include6
-rw-r--r--tools/build/fixdep.c168
-rw-r--r--tools/build/tests/ex/Build1
-rw-r--r--tools/build/tests/ex/Makefile13
-rw-r--r--tools/build/tests/ex/ex.c2
-rw-r--r--tools/build/tests/ex/inc.c8
-rwxr-xr-xtools/build/tests/run.sh27
-rw-r--r--tools/lib/api/Makefile6
-rw-r--r--tools/lib/api/fs/tracing_path.c13
-rw-r--r--tools/lib/bpf/Makefile6
-rw-r--r--tools/lib/lockdep/Makefile6
-rw-r--r--tools/perf/Documentation/intel-pt.txt44
-rw-r--r--tools/perf/Documentation/itrace.txt4
-rw-r--r--tools/perf/Documentation/perf-inject.txt3
-rw-r--r--tools/perf/Documentation/perf-script.txt3
-rw-r--r--tools/perf/Makefile.perf32
-rw-r--r--tools/perf/builtin-inject.c127
-rw-r--r--tools/perf/builtin-report.c31
-rw-r--r--tools/perf/builtin-script.c18
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py221
-rw-r--r--tools/perf/ui/browsers/hists.c24
-rw-r--r--tools/perf/util/auxtrace.c24
-rw-r--r--tools/perf/util/auxtrace.h4
-rw-r--r--tools/perf/util/event.c2
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evlist.c22
-rw-r--r--tools/perf/util/evlist.h3
-rw-r--r--tools/perf/util/hist.c6
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c4
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.c21
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.h38
-rw-r--r--tools/perf/util/intel-pt.c135
-rw-r--r--tools/perf/util/parse-events.c151
-rw-r--r--tools/perf/util/parse-events.h4
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/parse-events.y51
-rw-r--r--tools/perf/util/pmu.c37
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c2
-rw-r--r--tools/perf/util/session.c12
-rw-r--r--tools/perf/util/trace-event.h2
47 files changed, 1240 insertions, 167 deletions
diff --git a/tools/build/Build b/tools/build/Build
new file mode 100644
index 000000000000..63a6c34c0c88
--- /dev/null
+++ b/tools/build/Build
@@ -0,0 +1 @@
fixdep-y := fixdep.o
diff --git a/tools/build/Build.include b/tools/build/Build.include
index 4c8daaccb82a..4d000bc959b4 100644
--- a/tools/build/Build.include
+++ b/tools/build/Build.include
@@ -55,14 +55,25 @@ make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1)))))
55any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) 55any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
56 56
57### 57###
58# Copy dependency data into .cmd file
59# - gcc -M dependency info
60# - command line to create object 'cmd_object :='
61dep-cmd = $(if $(wildcard $(fixdep)), \
62 $(fixdep) $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp; \
63 rm -f $(depfile); \
64 mv -f $(dot-target).tmp $(dot-target).cmd, \
65 printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \
66 printf '\# using basic dep data\n\n' >> $(dot-target).cmd; \
67 cat $(depfile) >> $(dot-target).cmd; \
68 printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
69
70###
58# if_changed_dep - execute command if any prerequisite is newer than 71# if_changed_dep - execute command if any prerequisite is newer than
59# target, or command line has changed and update 72# target, or command line has changed and update
60# dependencies in the cmd file 73# dependencies in the cmd file
61if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \ 74if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \
62 @set -e; \ 75 @set -e; \
63 $(echo-cmd) $(cmd_$(1)); \ 76 $(echo-cmd) $(cmd_$(1)) && $(dep-cmd))
64 cat $(depfile) > $(dot-target).cmd; \
65 printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
66 77
67# if_changed - execute command if any prerequisite is newer than 78# if_changed - execute command if any prerequisite is newer than
68# target, or command line has changed 79# target, or command line has changed
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
index aa5e092c4352..a47bffbae159 100644
--- a/tools/build/Documentation/Build.txt
+++ b/tools/build/Documentation/Build.txt
@@ -11,8 +11,9 @@ Unlike the kernel we don't have a single build object 'obj-y' list that where
11we setup source objects, but we support more. This allows one 'Build' file to 11we setup source objects, but we support more. This allows one 'Build' file to
12carry a sources list for multiple build objects. 12carry a sources list for multiple build objects.
13 13
14a) Build framework makefiles 14
15---------------------------- 15Build framework makefiles
16-------------------------
16 17
17The build framework consists of 2 Makefiles: 18The build framework consists of 2 Makefiles:
18 19
@@ -23,7 +24,7 @@ While the 'Build.include' file contains just some generic definitions, the
23'Makefile.build' file is the makefile used from the outside. It's 24'Makefile.build' file is the makefile used from the outside. It's
24interface/usage is following: 25interface/usage is following:
25 26
26 $ make -f tools/build/Makefile srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT) 27 $ make -f tools/build/Makefile.build srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT)
27 28
28where: 29where:
29 30
@@ -38,8 +39,9 @@ called $(OBJECT)-in.o:
38 39
39which includes all compiled sources described in 'Build' makefiles. 40which includes all compiled sources described in 'Build' makefiles.
40 41
41a) Build makefiles 42
42------------------ 43Build makefiles
44---------------
43 45
44The user supplies 'Build' makefiles that contains a objects list, and connects 46The user supplies 'Build' makefiles that contains a objects list, and connects
45the build to nested directories. 47the build to nested directories.
@@ -95,8 +97,31 @@ It's only a matter of 2 single commands to create the final binaries:
95 97
96You can check the 'ex' example in 'tools/build/tests/ex' for more details. 98You can check the 'ex' example in 'tools/build/tests/ex' for more details.
97 99
98b) Rules 100
99-------- 101Makefile.include
102----------------
103
104The tools/build/Makefile.include makefile could be included
105via user makefiles to get usefull definitions.
106
107It defines following interface:
108
109 - build macro definition:
110 build := -f $(srctree)/tools/build/Makefile.build dir=. obj
111
112 to make it easier to invoke build like:
113 make $(build)=ex
114
115
116Fixdep
117------
118It is necessary to build the fixdep helper before invoking the build.
119The Makefile.include file adds the fixdep target, that could be
120invoked by the user.
121
122
123Rules
124-----
100 125
101The build framework provides standard compilation rules to handle .S and .c 126The build framework provides standard compilation rules to handle .S and .c
102compilation. 127compilation.
@@ -104,8 +129,9 @@ compilation.
104It's possible to include special rule if needed (like we do for flex or bison 129It's possible to include special rule if needed (like we do for flex or bison
105code generation). 130code generation).
106 131
107c) CFLAGS 132
108--------- 133CFLAGS
134------
109 135
110It's possible to alter the standard object C flags in the following way: 136It's possible to alter the standard object C flags in the following way:
111 137
@@ -115,8 +141,8 @@ It's possible to alter the standard object C flags in the following way:
115This C flags changes has the scope of the Build makefile they are defined in. 141This C flags changes has the scope of the Build makefile they are defined in.
116 142
117 143
118d) Dependencies 144Dependencies
119--------------- 145------------
120 146
121For each built object file 'a.o' the '.a.cmd' is created and holds: 147For each built object file 'a.o' the '.a.cmd' is created and holds:
122 148
@@ -130,8 +156,8 @@ All existing '.cmd' files are included in the Build process to follow properly
130the dependencies and trigger a rebuild when necessary. 156the dependencies and trigger a rebuild when necessary.
131 157
132 158
133e) Single rules 159Single rules
134--------------- 160------------
135 161
136It's possible to build single object file by choice, like: 162It's possible to build single object file by choice, like:
137 163
diff --git a/tools/build/Makefile b/tools/build/Makefile
new file mode 100644
index 000000000000..a93036272d43
--- /dev/null
+++ b/tools/build/Makefile
@@ -0,0 +1,43 @@
1ifeq ($(srctree),)
2srctree := $(patsubst %/,%,$(dir $(shell pwd)))
3srctree := $(patsubst %/,%,$(dir $(srctree)))
4endif
5
6include $(srctree)/tools//scripts/Makefile.include
7
8define allow-override
9 $(if $(or $(findstring environment,$(origin $(1))),\
10 $(findstring command line,$(origin $(1)))),,\
11 $(eval $(1) = $(2)))
12endef
13
14$(call allow-override,CC,$(CROSS_COMPILE)gcc)
15$(call allow-override,LD,$(CROSS_COMPILE)ld)
16
17ifeq ($(V),1)
18 Q =
19else
20 Q = @
21endif
22
23export Q srctree CC LD
24
25MAKEFLAGS := --no-print-directory
26build := -f $(srctree)/tools/build/Makefile.build dir=. obj
27
28all: fixdep
29
30clean:
31 $(call QUIET_CLEAN, fixdep)
32 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
33 $(Q)rm -f fixdep
34
35$(OUTPUT)fixdep-in.o: FORCE
36 $(Q)$(MAKE) $(build)=fixdep
37
38$(OUTPUT)fixdep: $(OUTPUT)fixdep-in.o
39 $(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $<
40
41FORCE:
42
43.PHONY: FORCE
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index 0c5f485521d6..4a96473b180f 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -21,6 +21,13 @@ endif
21 21
22build-dir := $(srctree)/tools/build 22build-dir := $(srctree)/tools/build
23 23
24# Define $(fixdep) for dep-cmd function
25ifeq ($(OUTPUT),)
26 fixdep := $(build-dir)/fixdep
27else
28 fixdep := $(OUTPUT)/fixdep
29endif
30
24# Generic definitions 31# Generic definitions
25include $(build-dir)/Build.include 32include $(build-dir)/Build.include
26 33
diff --git a/tools/build/Makefile.include b/tools/build/Makefile.include
new file mode 100644
index 000000000000..6572bb023543
--- /dev/null
+++ b/tools/build/Makefile.include
@@ -0,0 +1,6 @@
1build := -f $(srctree)/tools/build/Makefile.build dir=. obj
2
3fixdep:
4 $(Q)$(MAKE) -C $(srctree)/tools/build fixdep
5
6.PHONY: fixdep
diff --git a/tools/build/fixdep.c b/tools/build/fixdep.c
new file mode 100644
index 000000000000..1521d36cef0d
--- /dev/null
+++ b/tools/build/fixdep.c
@@ -0,0 +1,168 @@
1/*
2 * "Optimize" a list of dependencies as spit out by gcc -MD
3 * for the build framework.
4 *
5 * Original author:
6 * Copyright 2002 by Kai Germaschewski <kai.germaschewski@gmx.de>
7 *
8 * This code has been borrowed from kbuild's fixdep (scripts/basic/fixdep.c),
9 * Please check it for detailed explanation. This fixdep borow only the
10 * base transformation of dependecies without the CONFIG mangle.
11 */
12
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <sys/mman.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <string.h>
19#include <stdlib.h>
20#include <stdio.h>
21#include <limits.h>
22
23char *target;
24char *depfile;
25char *cmdline;
26
27static void usage(void)
28{
29 fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
30 exit(1);
31}
32
33/*
34 * Print out the commandline prefixed with cmd_<target filename> :=
35 */
36static void print_cmdline(void)
37{
38 printf("cmd_%s := %s\n\n", target, cmdline);
39}
40
41/*
42 * Important: The below generated source_foo.o and deps_foo.o variable
43 * assignments are parsed not only by make, but also by the rather simple
44 * parser in scripts/mod/sumversion.c.
45 */
46static void parse_dep_file(void *map, size_t len)
47{
48 char *m = map;
49 char *end = m + len;
50 char *p;
51 char s[PATH_MAX];
52 int is_target;
53 int saw_any_target = 0;
54 int is_first_dep = 0;
55
56 while (m < end) {
57 /* Skip any "white space" */
58 while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
59 m++;
60 /* Find next "white space" */
61 p = m;
62 while (p < end && *p != ' ' && *p != '\\' && *p != '\n')
63 p++;
64 /* Is the token we found a target name? */
65 is_target = (*(p-1) == ':');
66 /* Don't write any target names into the dependency file */
67 if (is_target) {
68 /* The /next/ file is the first dependency */
69 is_first_dep = 1;
70 } else {
71 /* Save this token/filename */
72 memcpy(s, m, p-m);
73 s[p - m] = 0;
74
75 /*
76 * Do not list the source file as dependency,
77 * so that kbuild is not confused if a .c file
78 * is rewritten into .S or vice versa. Storing
79 * it in source_* is needed for modpost to
80 * compute srcversions.
81 */
82 if (is_first_dep) {
83 /*
84 * If processing the concatenation of
85 * multiple dependency files, only
86 * process the first target name, which
87 * will be the original source name,
88 * and ignore any other target names,
89 * which will be intermediate temporary
90 * files.
91 */
92 if (!saw_any_target) {
93 saw_any_target = 1;
94 printf("source_%s := %s\n\n",
95 target, s);
96 printf("deps_%s := \\\n",
97 target);
98 }
99 is_first_dep = 0;
100 } else
101 printf(" %s \\\n", s);
102 }
103 /*
104 * Start searching for next token immediately after the first
105 * "whitespace" character that follows this token.
106 */
107 m = p + 1;
108 }
109
110 if (!saw_any_target) {
111 fprintf(stderr, "fixdep: parse error; no targets found\n");
112 exit(1);
113 }
114
115 printf("\n%s: $(deps_%s)\n\n", target, target);
116 printf("$(deps_%s):\n", target);
117}
118
119static void print_deps(void)
120{
121 struct stat st;
122 int fd;
123 void *map;
124
125 fd = open(depfile, O_RDONLY);
126 if (fd < 0) {
127 fprintf(stderr, "fixdep: error opening depfile: ");
128 perror(depfile);
129 exit(2);
130 }
131 if (fstat(fd, &st) < 0) {
132 fprintf(stderr, "fixdep: error fstat'ing depfile: ");
133 perror(depfile);
134 exit(2);
135 }
136 if (st.st_size == 0) {
137 fprintf(stderr, "fixdep: %s is empty\n", depfile);
138 close(fd);
139 return;
140 }
141 map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
142 if ((long) map == -1) {
143 perror("fixdep: mmap");
144 close(fd);
145 return;
146 }
147
148 parse_dep_file(map, st.st_size);
149
150 munmap(map, st.st_size);
151
152 close(fd);
153}
154
155int main(int argc, char **argv)
156{
157 if (argc != 4)
158 usage();
159
160 depfile = argv[1];
161 target = argv[2];
162 cmdline = argv[3];
163
164 print_cmdline();
165 print_deps();
166
167 return 0;
168}
diff --git a/tools/build/tests/ex/Build b/tools/build/tests/ex/Build
index 429c7d452101..4d502f9b1a50 100644
--- a/tools/build/tests/ex/Build
+++ b/tools/build/tests/ex/Build
@@ -4,6 +4,7 @@ ex-y += b.o
4ex-y += b.o 4ex-y += b.o
5ex-y += empty/ 5ex-y += empty/
6ex-y += empty2/ 6ex-y += empty2/
7ex-y += inc.o
7 8
8libex-y += c.o 9libex-y += c.o
9libex-y += d.o 10libex-y += d.o
diff --git a/tools/build/tests/ex/Makefile b/tools/build/tests/ex/Makefile
index 52d2476073a3..c50d5782ad5a 100644
--- a/tools/build/tests/ex/Makefile
+++ b/tools/build/tests/ex/Makefile
@@ -1,19 +1,22 @@
1export srctree := ../../../.. 1export srctree := $(abspath ../../../..)
2export CC := gcc 2export CC := gcc
3export LD := ld 3export LD := ld
4export AR := ar 4export AR := ar
5 5
6build := -f $(srctree)/tools/build/Makefile.build dir=. obj 6ex:
7
8include $(srctree)/tools/build/Makefile.include
9
7ex: ex-in.o libex-in.o 10ex: ex-in.o libex-in.o
8 gcc -o $@ $^ 11 gcc -o $@ $^
9 12
10ex.%: FORCE 13ex.%: fixdep FORCE
11 make -f $(srctree)/tools/build/Makefile.build dir=. $@ 14 make -f $(srctree)/tools/build/Makefile.build dir=. $@
12 15
13ex-in.o: FORCE 16ex-in.o: fixdep FORCE
14 make $(build)=ex 17 make $(build)=ex
15 18
16libex-in.o: FORCE 19libex-in.o: fixdep FORCE
17 make $(build)=libex 20 make $(build)=libex
18 21
19clean: 22clean:
diff --git a/tools/build/tests/ex/ex.c b/tools/build/tests/ex/ex.c
index dc42eb2e1a67..57de6074d252 100644
--- a/tools/build/tests/ex/ex.c
+++ b/tools/build/tests/ex/ex.c
@@ -5,6 +5,7 @@ int c(void);
5int d(void); 5int d(void);
6int e(void); 6int e(void);
7int f(void); 7int f(void);
8int inc(void);
8 9
9int main(void) 10int main(void)
10{ 11{
@@ -14,6 +15,7 @@ int main(void)
14 d(); 15 d();
15 e(); 16 e();
16 f(); 17 f();
18 inc();
17 19
18 return 0; 20 return 0;
19} 21}
diff --git a/tools/build/tests/ex/inc.c b/tools/build/tests/ex/inc.c
new file mode 100644
index 000000000000..c20f1e9033a3
--- /dev/null
+++ b/tools/build/tests/ex/inc.c
@@ -0,0 +1,8 @@
1#ifdef INCLUDE
2#include "krava.h"
3#endif
4
5int inc(void)
6{
7 return 0;
8}
diff --git a/tools/build/tests/run.sh b/tools/build/tests/run.sh
index 5494f8ea7567..44d2a0fade67 100755
--- a/tools/build/tests/run.sh
+++ b/tools/build/tests/run.sh
@@ -34,9 +34,36 @@ function test_ex_suffix {
34 make -C ex V=1 clean > /dev/null 2>&1 34 make -C ex V=1 clean > /dev/null 2>&1
35 rm -f ex.out 35 rm -f ex.out
36} 36}
37
38function test_ex_include {
39 make -C ex V=1 clean > ex.out 2>&1
40
41 # build with krava.h include
42 touch ex/krava.h
43 make -C ex V=1 CFLAGS=-DINCLUDE >> ex.out 2>&1
44
45 if [ ! -x ./ex/ex ]; then
46 echo FAILED
47 exit -1
48 fi
49
50 # build without the include
51 rm -f ex/krava.h ex/ex
52 make -C ex V=1 >> ex.out 2>&1
53
54 if [ ! -x ./ex/ex ]; then
55 echo FAILED
56 exit -1
57 fi
58
59 make -C ex V=1 clean > /dev/null 2>&1
60 rm -f ex.out
61}
62
37echo -n Testing.. 63echo -n Testing..
38 64
39test_ex 65test_ex
40test_ex_suffix 66test_ex_suffix
67test_ex_include
41 68
42echo OK 69echo OK
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index fe1b02c2c95b..d85904dc9b38 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -21,12 +21,14 @@ CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
21 21
22RM = rm -f 22RM = rm -f
23 23
24build := -f $(srctree)/tools/build/Makefile.build dir=. obj
25API_IN := $(OUTPUT)libapi-in.o 24API_IN := $(OUTPUT)libapi-in.o
26 25
26all:
27
27export srctree OUTPUT CC LD CFLAGS V 28export srctree OUTPUT CC LD CFLAGS V
29include $(srctree)/tools/build/Makefile.include
28 30
29all: $(LIBFILE) 31all: fixdep $(LIBFILE)
30 32
31$(API_IN): FORCE 33$(API_IN): FORCE
32 @$(MAKE) $(build)=libapi 34 @$(MAKE) $(build)=libapi
diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 38aca2dd1946..0406a7d5c891 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -12,12 +12,14 @@
12#include "tracing_path.h" 12#include "tracing_path.h"
13 13
14 14
15char tracing_mnt[PATH_MAX + 1] = "/sys/kernel/debug";
15char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing"; 16char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing";
16char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events"; 17char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
17 18
18 19
19static void __tracing_path_set(const char *tracing, const char *mountpoint) 20static void __tracing_path_set(const char *tracing, const char *mountpoint)
20{ 21{
22 snprintf(tracing_mnt, sizeof(tracing_mnt), "%s", mountpoint);
21 snprintf(tracing_path, sizeof(tracing_path), "%s/%s", 23 snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
22 mountpoint, tracing); 24 mountpoint, tracing);
23 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s", 25 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
@@ -109,19 +111,10 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
109 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'"); 111 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
110 break; 112 break;
111 case EACCES: { 113 case EACCES: {
112 const char *mountpoint = debugfs__mountpoint();
113
114 if (!access(mountpoint, R_OK) && strncmp(filename, "tracing/", 8) == 0) {
115 const char *tracefs_mntpoint = tracefs__mountpoint();
116
117 if (tracefs_mntpoint)
118 mountpoint = tracefs__mountpoint();
119 }
120
121 snprintf(buf, size, 114 snprintf(buf, size,
122 "Error:\tNo permissions to read %s/%s\n" 115 "Error:\tNo permissions to read %s/%s\n"
123 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n", 116 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
124 tracing_events_path, filename, mountpoint); 117 tracing_events_path, filename, tracing_mnt);
125 } 118 }
126 break; 119 break;
127 default: 120 default:
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index e630f9fc4fb6..fc9af57b666e 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -123,8 +123,10 @@ endif
123# the same command line setup. 123# the same command line setup.
124MAKEOVERRIDES= 124MAKEOVERRIDES=
125 125
126all:
127
126export srctree OUTPUT CC LD CFLAGS V 128export srctree OUTPUT CC LD CFLAGS V
127build := -f $(srctree)/tools/build/Makefile.build dir=. obj 129include $(srctree)/tools/build/Makefile.include
128 130
129BPF_IN := $(OUTPUT)libbpf-in.o 131BPF_IN := $(OUTPUT)libbpf-in.o
130LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE)) 132LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
@@ -133,7 +135,7 @@ CMD_TARGETS = $(LIB_FILE)
133 135
134TARGETS = $(CMD_TARGETS) 136TARGETS = $(CMD_TARGETS)
135 137
136all: $(VERSION_FILES) all_cmd 138all: fixdep $(VERSION_FILES) all_cmd
137 139
138all_cmd: $(CMD_TARGETS) 140all_cmd: $(CMD_TARGETS)
139 141
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 18ffccf00426..7e319afac78a 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -93,8 +93,10 @@ else
93 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; 93 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
94endif 94endif
95 95
96all:
97
96export srctree OUTPUT CC LD CFLAGS V 98export srctree OUTPUT CC LD CFLAGS V
97build := -f $(srctree)/tools/build/Makefile.build dir=. obj 99include $(srctree)/tools/build/Makefile.include
98 100
99do_compile_shared_library = \ 101do_compile_shared_library = \
100 ($(print_shared_lib_compile) \ 102 ($(print_shared_lib_compile) \
@@ -109,7 +111,7 @@ CMD_TARGETS = $(LIB_FILE)
109TARGETS = $(CMD_TARGETS) 111TARGETS = $(CMD_TARGETS)
110 112
111 113
112all: all_cmd 114all: fixdep all_cmd
113 115
114all_cmd: $(CMD_TARGETS) 116all_cmd: $(CMD_TARGETS)
115 117
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index c94c9de3173e..be764f9ec769 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -671,6 +671,7 @@ The letters are:
671 e synthesize tracing error events 671 e synthesize tracing error events
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 675
675"Instructions" events look like they were recorded by "perf record -e 676"Instructions" events look like they were recorded by "perf record -e
676instructions". 677instructions".
@@ -707,12 +708,26 @@ on the sample is *not* adjusted and reflects the last known value of TSC.
707 708
708For Intel PT, the default period is 100us. 709For Intel PT, the default period is 100us.
709 710
711Setting it to a zero period means "as often as possible".
712
713In the case of Intel PT that is the same as a period of 1 and a unit of
714'instructions' (i.e. --itrace=i1i).
715
710Also the call chain size (default 16, max. 1024) for instructions or 716Also the call chain size (default 16, max. 1024) for instructions or
711transactions events can be specified. e.g. 717transactions events can be specified. e.g.
712 718
713 --itrace=ig32 719 --itrace=ig32
714 --itrace=xg32 720 --itrace=xg32
715 721
722Also the number of last branch entries (default 64, max. 1024) for instructions or
723transactions events can be specified. e.g.
724
725 --itrace=il10
726 --itrace=xl10
727
728Note that last branch entries are cleared for each sample, so there is no overlap
729from one sample to the next.
730
716To disable trace decoding entirely, use the option --no-itrace. 731To disable trace decoding entirely, use the option --no-itrace.
717 732
718 733
@@ -749,3 +764,32 @@ perf inject also accepts the --itrace option in which case tracing data is
749removed and replaced with the synthesized events. e.g. 764removed and replaced with the synthesized events. e.g.
750 765
751 perf inject --itrace -i perf.data -o perf.data.new 766 perf inject --itrace -i perf.data -o perf.data.new
767
768Below is an example of using Intel PT with autofdo. It requires autofdo
769(https://github.com/google/autofdo) and gcc version 5. The bubble
770sort example is from the AutoFDO tutorial (https://gcc.gnu.org/wiki/AutoFDO/Tutorial)
771amended to take the number of elements as a parameter.
772
773 $ gcc-5 -O3 sort.c -o sort_optimized
774 $ ./sort_optimized 30000
775 Bubble sorting array of 30000 elements
776 2254 ms
777
778 $ cat ~/.perfconfig
779 [intel-pt]
780 mispred-all
781
782 $ perf record -e intel_pt//u ./sort 3000
783 Bubble sorting array of 3000 elements
784 58 ms
785 [ perf record: Woken up 2 times to write data ]
786 [ perf record: Captured and wrote 3.939 MB perf.data ]
787 $ perf inject -i perf.data -o inj --itrace=i100usle --strip
788 $ ./create_gcov --binary=./sort --profile=inj --gcov=sort.gcov -gcov_version=1
789 $ gcc-5 -O3 -fauto-profile=sort.gcov sort.c -o sort_autofdo
790 $ ./sort_autofdo 30000
791 Bubble sorting array of 30000 elements
792 2155 ms
793
794Note there is currently no advantage to using Intel PT instead of LBR, but
795that may change in the future if greater use is made of the data.
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index 2ff946677e3b..65453f4c7006 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -6,6 +6,7 @@
6 e synthesize error events 6 e synthesize error events
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 10
10 The default is all events i.e. the same as --itrace=ibxe 11 The default is all events i.e. the same as --itrace=ibxe
11 12
@@ -20,3 +21,6 @@
20 21
21 Also the call chain size (default 16, max. 1024) for instructions or 22 Also the call chain size (default 16, max. 1024) for instructions or
22 transactions events can be specified. 23 transactions events can be specified.
24
25 Also the number of last branch entries (default 64, max. 1024) for
26 instructions or transactions events can be specified.
diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
index 0c721c3e37e1..0b1cedeef895 100644
--- a/tools/perf/Documentation/perf-inject.txt
+++ b/tools/perf/Documentation/perf-inject.txt
@@ -50,6 +50,9 @@ OPTIONS
50 50
51include::itrace.txt[] 51include::itrace.txt[]
52 52
53--strip::
54 Use with --itrace to strip out non-synthesized events.
55
53SEE ALSO 56SEE ALSO
54-------- 57--------
55linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] 58linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index dc3ec783b7bd..b3b42f9285df 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -249,6 +249,9 @@ include::itrace.txt[]
249--full-source-path:: 249--full-source-path::
250 Show the full path for source files for srcline output. 250 Show the full path for source files for srcline output.
251 251
252--ns::
253 Use 9 decimal places when displaying time (i.e. show the nanoseconds)
254
252SEE ALSO 255SEE ALSO
253-------- 256--------
254linkperf:perf-record[1], linkperf:perf-script-perl[1], 257linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 6c5c699002cb..56517d304772 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -297,16 +297,16 @@ strip: $(PROGRAMS) $(OUTPUT)perf
297PERF_IN := $(OUTPUT)perf-in.o 297PERF_IN := $(OUTPUT)perf-in.o
298 298
299export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK 299export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
300build := -f $(srctree)/tools/build/Makefile.build dir=. obj 300include $(srctree)/tools/build/Makefile.include
301 301
302$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE 302$(PERF_IN): prepare FORCE
303 $(Q)$(MAKE) $(build)=perf 303 $(Q)$(MAKE) $(build)=perf
304 304
305$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) 305$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
306 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \ 306 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
307 $(PERF_IN) $(LIBS) -o $@ 307 $(PERF_IN) $(LIBS) -o $@
308 308
309$(GTK_IN): FORCE 309$(GTK_IN): fixdep FORCE
310 $(Q)$(MAKE) $(build)=gtk 310 $(Q)$(MAKE) $(build)=gtk
311 311
312$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS) 312$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS)
@@ -349,27 +349,27 @@ endif
349__build-dir = $(subst $(OUTPUT),,$(dir $@)) 349__build-dir = $(subst $(OUTPUT),,$(dir $@))
350build-dir = $(if $(__build-dir),$(__build-dir),.) 350build-dir = $(if $(__build-dir),$(__build-dir),.)
351 351
352single_dep: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h 352prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep
353 353
354$(OUTPUT)%.o: %.c single_dep FORCE 354$(OUTPUT)%.o: %.c prepare FORCE
355 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 355 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
356 356
357$(OUTPUT)%.i: %.c single_dep FORCE 357$(OUTPUT)%.i: %.c prepare FORCE
358 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 358 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
359 359
360$(OUTPUT)%.s: %.c single_dep FORCE 360$(OUTPUT)%.s: %.c prepare FORCE
361 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 361 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
362 362
363$(OUTPUT)%-bison.o: %.c single_dep FORCE 363$(OUTPUT)%-bison.o: %.c prepare FORCE
364 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 364 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
365 365
366$(OUTPUT)%-flex.o: %.c single_dep FORCE 366$(OUTPUT)%-flex.o: %.c prepare FORCE
367 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 367 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
368 368
369$(OUTPUT)%.o: %.S single_dep FORCE 369$(OUTPUT)%.o: %.S prepare FORCE
370 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 370 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
371 371
372$(OUTPUT)%.i: %.S single_dep FORCE 372$(OUTPUT)%.i: %.S prepare FORCE
373 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 373 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
374 374
375$(OUTPUT)perf-%: %.o $(PERFLIBS) 375$(OUTPUT)perf-%: %.o $(PERFLIBS)
@@ -389,7 +389,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
389 389
390LIBPERF_IN := $(OUTPUT)libperf-in.o 390LIBPERF_IN := $(OUTPUT)libperf-in.o
391 391
392$(LIBPERF_IN): FORCE 392$(LIBPERF_IN): fixdep FORCE
393 $(Q)$(MAKE) $(build)=libperf 393 $(Q)$(MAKE) $(build)=libperf
394 394
395$(LIB_FILE): $(LIBPERF_IN) 395$(LIB_FILE): $(LIBPERF_IN)
@@ -397,10 +397,10 @@ $(LIB_FILE): $(LIBPERF_IN)
397 397
398LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 398LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
399 399
400$(LIBTRACEEVENT): FORCE 400$(LIBTRACEEVENT): fixdep FORCE
401 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a 401 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a
402 402
403libtraceevent_plugins: FORCE 403libtraceevent_plugins: fixdep FORCE
404 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins 404 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins
405 405
406$(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins 406$(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins
@@ -413,7 +413,7 @@ $(LIBTRACEEVENT)-clean:
413install-traceevent-plugins: $(LIBTRACEEVENT) 413install-traceevent-plugins: $(LIBTRACEEVENT)
414 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins 414 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins
415 415
416$(LIBAPI): FORCE 416$(LIBAPI): fixdep FORCE
417 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a 417 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a
418 418
419$(LIBAPI)-clean: 419$(LIBAPI)-clean:
@@ -591,6 +591,6 @@ FORCE:
591 591
592.PHONY: all install clean config-clean strip install-gtk 592.PHONY: all install clean config-clean strip install-gtk
593.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 593.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
594.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep 594.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare
595.PHONY: libtraceevent_plugins 595.PHONY: libtraceevent_plugins
596 596
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index f62c49b35be0..0a945d2e8ca5 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -28,9 +28,11 @@ struct perf_inject {
28 bool build_ids; 28 bool build_ids;
29 bool sched_stat; 29 bool sched_stat;
30 bool have_auxtrace; 30 bool have_auxtrace;
31 bool strip;
31 const char *input_name; 32 const char *input_name;
32 struct perf_data_file output; 33 struct perf_data_file output;
33 u64 bytes_written; 34 u64 bytes_written;
35 u64 aux_id;
34 struct list_head samples; 36 struct list_head samples;
35 struct itrace_synth_opts itrace_synth_opts; 37 struct itrace_synth_opts itrace_synth_opts;
36}; 38};
@@ -176,6 +178,27 @@ static int perf_event__repipe(struct perf_tool *tool,
176 return perf_event__repipe_synth(tool, event); 178 return perf_event__repipe_synth(tool, event);
177} 179}
178 180
181static int perf_event__drop(struct perf_tool *tool __maybe_unused,
182 union perf_event *event __maybe_unused,
183 struct perf_sample *sample __maybe_unused,
184 struct machine *machine __maybe_unused)
185{
186 return 0;
187}
188
189static int perf_event__drop_aux(struct perf_tool *tool,
190 union perf_event *event __maybe_unused,
191 struct perf_sample *sample,
192 struct machine *machine __maybe_unused)
193{
194 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
195
196 if (!inject->aux_id)
197 inject->aux_id = sample->id;
198
199 return 0;
200}
201
179typedef int (*inject_handler)(struct perf_tool *tool, 202typedef int (*inject_handler)(struct perf_tool *tool,
180 union perf_event *event, 203 union perf_event *event,
181 struct perf_sample *sample, 204 struct perf_sample *sample,
@@ -466,6 +489,78 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
466 return 0; 489 return 0;
467} 490}
468 491
492static int drop_sample(struct perf_tool *tool __maybe_unused,
493 union perf_event *event __maybe_unused,
494 struct perf_sample *sample __maybe_unused,
495 struct perf_evsel *evsel __maybe_unused,
496 struct machine *machine __maybe_unused)
497{
498 return 0;
499}
500
501static void strip_init(struct perf_inject *inject)
502{
503 struct perf_evlist *evlist = inject->session->evlist;
504 struct perf_evsel *evsel;
505
506 inject->tool.context_switch = perf_event__drop;
507
508 evlist__for_each(evlist, evsel)
509 evsel->handler = drop_sample;
510}
511
512static bool has_tracking(struct perf_evsel *evsel)
513{
514 return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm ||
515 evsel->attr.task;
516}
517
518#define COMPAT_MASK (PERF_SAMPLE_ID | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | \
519 PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER)
520
521/*
522 * In order that the perf.data file is parsable, tracking events like MMAP need
523 * their selected event to exist, except if there is only 1 selected event left
524 * and it has a compatible sample type.
525 */
526static bool ok_to_remove(struct perf_evlist *evlist,
527 struct perf_evsel *evsel_to_remove)
528{
529 struct perf_evsel *evsel;
530 int cnt = 0;
531 bool ok = false;
532
533 if (!has_tracking(evsel_to_remove))
534 return true;
535
536 evlist__for_each(evlist, evsel) {
537 if (evsel->handler != drop_sample) {
538 cnt += 1;
539 if ((evsel->attr.sample_type & COMPAT_MASK) ==
540 (evsel_to_remove->attr.sample_type & COMPAT_MASK))
541 ok = true;
542 }
543 }
544
545 return ok && cnt == 1;
546}
547
548static void strip_fini(struct perf_inject *inject)
549{
550 struct perf_evlist *evlist = inject->session->evlist;
551 struct perf_evsel *evsel, *tmp;
552
553 /* Remove non-synthesized evsels if possible */
554 evlist__for_each_safe(evlist, tmp, evsel) {
555 if (evsel->handler == drop_sample &&
556 ok_to_remove(evlist, evsel)) {
557 pr_debug("Deleting %s\n", perf_evsel__name(evsel));
558 perf_evlist__remove(evlist, evsel);
559 perf_evsel__delete(evsel);
560 }
561 }
562}
563
469static int __cmd_inject(struct perf_inject *inject) 564static int __cmd_inject(struct perf_inject *inject)
470{ 565{
471 int ret = -EINVAL; 566 int ret = -EINVAL;
@@ -512,10 +607,14 @@ static int __cmd_inject(struct perf_inject *inject)
512 inject->tool.id_index = perf_event__repipe_id_index; 607 inject->tool.id_index = perf_event__repipe_id_index;
513 inject->tool.auxtrace_info = perf_event__process_auxtrace_info; 608 inject->tool.auxtrace_info = perf_event__process_auxtrace_info;
514 inject->tool.auxtrace = perf_event__process_auxtrace; 609 inject->tool.auxtrace = perf_event__process_auxtrace;
610 inject->tool.aux = perf_event__drop_aux;
611 inject->tool.itrace_start = perf_event__drop_aux,
515 inject->tool.ordered_events = true; 612 inject->tool.ordered_events = true;
516 inject->tool.ordering_requires_timestamps = true; 613 inject->tool.ordering_requires_timestamps = true;
517 /* Allow space in the header for new attributes */ 614 /* Allow space in the header for new attributes */
518 output_data_offset = 4096; 615 output_data_offset = 4096;
616 if (inject->strip)
617 strip_init(inject);
519 } 618 }
520 619
521 if (!inject->itrace_synth_opts.set) 620 if (!inject->itrace_synth_opts.set)
@@ -535,11 +634,28 @@ static int __cmd_inject(struct perf_inject *inject)
535 } 634 }
536 /* 635 /*
537 * The AUX areas have been removed and replaced with 636 * The AUX areas have been removed and replaced with
538 * synthesized hardware events, so clear the feature flag. 637 * synthesized hardware events, so clear the feature flag and
638 * remove the evsel.
539 */ 639 */
540 if (inject->itrace_synth_opts.set) 640 if (inject->itrace_synth_opts.set) {
641 struct perf_evsel *evsel;
642
541 perf_header__clear_feat(&session->header, 643 perf_header__clear_feat(&session->header,
542 HEADER_AUXTRACE); 644 HEADER_AUXTRACE);
645 if (inject->itrace_synth_opts.last_branch)
646 perf_header__set_feat(&session->header,
647 HEADER_BRANCH_STACK);
648 evsel = perf_evlist__id2evsel_strict(session->evlist,
649 inject->aux_id);
650 if (evsel) {
651 pr_debug("Deleting %s\n",
652 perf_evsel__name(evsel));
653 perf_evlist__remove(session->evlist, evsel);
654 perf_evsel__delete(evsel);
655 }
656 if (inject->strip)
657 strip_fini(inject);
658 }
543 session->header.data_offset = output_data_offset; 659 session->header.data_offset = output_data_offset;
544 session->header.data_size = inject->bytes_written; 660 session->header.data_size = inject->bytes_written;
545 perf_session__write_header(session, session->evlist, fd, true); 661 perf_session__write_header(session, session->evlist, fd, true);
@@ -604,6 +720,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
604 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, 720 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
605 NULL, "opts", "Instruction Tracing options", 721 NULL, "opts", "Instruction Tracing options",
606 itrace_parse_synth_opts), 722 itrace_parse_synth_opts),
723 OPT_BOOLEAN(0, "strip", &inject.strip,
724 "strip non-synthesized events (use with --itrace)"),
607 OPT_END() 725 OPT_END()
608 }; 726 };
609 const char * const inject_usage[] = { 727 const char * const inject_usage[] = {
@@ -619,6 +737,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
619 if (argc) 737 if (argc)
620 usage_with_options(inject_usage, options); 738 usage_with_options(inject_usage, options);
621 739
740 if (inject.strip && !inject.itrace_synth_opts.set) {
741 pr_err("--strip option requires --itrace option\n");
742 return -1;
743 }
744
622 if (perf_data_file__open(&inject.output)) { 745 if (perf_data_file__open(&inject.output)) {
623 perror("failed to create output file"); 746 perror("failed to create output file");
624 return -1; 747 return -1;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e4e3f1432622..37c9f5125887 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -163,14 +163,21 @@ static int process_sample_event(struct perf_tool *tool,
163 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) 163 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
164 goto out_put; 164 goto out_put;
165 165
166 if (sort__mode == SORT_MODE__BRANCH) 166 if (sort__mode == SORT_MODE__BRANCH) {
167 /*
168 * A non-synthesized event might not have a branch stack if
169 * branch stacks have been synthesized (using itrace options).
170 */
171 if (!sample->branch_stack)
172 goto out_put;
167 iter.ops = &hist_iter_branch; 173 iter.ops = &hist_iter_branch;
168 else if (rep->mem_mode) 174 } else if (rep->mem_mode) {
169 iter.ops = &hist_iter_mem; 175 iter.ops = &hist_iter_mem;
170 else if (symbol_conf.cumulate_callchain) 176 } else if (symbol_conf.cumulate_callchain) {
171 iter.ops = &hist_iter_cumulative; 177 iter.ops = &hist_iter_cumulative;
172 else 178 } else {
173 iter.ops = &hist_iter_normal; 179 iter.ops = &hist_iter_normal;
180 }
174 181
175 if (al.map != NULL) 182 if (al.map != NULL)
176 al.map->dso->hit = 1; 183 al.map->dso->hit = 1;
@@ -214,6 +221,15 @@ static int report__setup_sample_type(struct report *rep)
214 u64 sample_type = perf_evlist__combined_sample_type(session->evlist); 221 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
215 bool is_pipe = perf_data_file__is_pipe(session->file); 222 bool is_pipe = perf_data_file__is_pipe(session->file);
216 223
224 if (session->itrace_synth_opts->callchain ||
225 (!is_pipe &&
226 perf_header__has_feat(&session->header, HEADER_AUXTRACE) &&
227 !session->itrace_synth_opts->set))
228 sample_type |= PERF_SAMPLE_CALLCHAIN;
229
230 if (session->itrace_synth_opts->last_branch)
231 sample_type |= PERF_SAMPLE_BRANCH_STACK;
232
217 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 233 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
218 if (sort__has_parent) { 234 if (sort__has_parent) {
219 ui__error("Selected --sort parent, but no " 235 ui__error("Selected --sort parent, but no "
@@ -793,6 +809,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
793 if (report.inverted_callchain) 809 if (report.inverted_callchain)
794 callchain_param.order = ORDER_CALLER; 810 callchain_param.order = ORDER_CALLER;
795 811
812 if (itrace_synth_opts.callchain &&
813 (int)itrace_synth_opts.callchain_sz > report.max_stack)
814 report.max_stack = itrace_synth_opts.callchain_sz;
815
796 if (!input_name || !strlen(input_name)) { 816 if (!input_name || !strlen(input_name)) {
797 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 817 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
798 input_name = "-"; 818 input_name = "-";
@@ -820,6 +840,9 @@ repeat:
820 has_br_stack = perf_header__has_feat(&session->header, 840 has_br_stack = perf_header__has_feat(&session->header,
821 HEADER_BRANCH_STACK); 841 HEADER_BRANCH_STACK);
822 842
843 if (itrace_synth_opts.last_branch)
844 has_br_stack = true;
845
823 /* 846 /*
824 * Branch mode is a tristate: 847 * Branch mode is a tristate:
825 * -1 means default, so decide based on the file having branch data. 848 * -1 means default, so decide based on the file having branch data.
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 284a76e04628..8ce1c6bbfa45 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -29,9 +29,12 @@ static bool no_callchain;
29static bool latency_format; 29static bool latency_format;
30static bool system_wide; 30static bool system_wide;
31static bool print_flags; 31static bool print_flags;
32static bool nanosecs;
32static const char *cpu_list; 33static const char *cpu_list;
33static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 34static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
34 35
36unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
37
35enum perf_output_field { 38enum perf_output_field {
36 PERF_OUTPUT_COMM = 1U << 0, 39 PERF_OUTPUT_COMM = 1U << 0,
37 PERF_OUTPUT_TID = 1U << 1, 40 PERF_OUTPUT_TID = 1U << 1,
@@ -415,7 +418,10 @@ static void print_sample_start(struct perf_sample *sample,
415 secs = nsecs / NSECS_PER_SEC; 418 secs = nsecs / NSECS_PER_SEC;
416 nsecs -= secs * NSECS_PER_SEC; 419 nsecs -= secs * NSECS_PER_SEC;
417 usecs = nsecs / NSECS_PER_USEC; 420 usecs = nsecs / NSECS_PER_USEC;
418 printf("%5lu.%06lu: ", secs, usecs); 421 if (nanosecs)
422 printf("%5lu.%09llu: ", secs, nsecs);
423 else
424 printf("%5lu.%06lu: ", secs, usecs);
419 } 425 }
420} 426}
421 427
@@ -471,7 +477,7 @@ static void print_sample_bts(union perf_event *event,
471 } 477 }
472 } 478 }
473 perf_evsel__print_ip(evsel, sample, al, print_opts, 479 perf_evsel__print_ip(evsel, sample, al, print_opts,
474 PERF_MAX_STACK_DEPTH); 480 scripting_max_stack);
475 } 481 }
476 482
477 /* print branch_to information */ 483 /* print branch_to information */
@@ -548,7 +554,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
548 554
549 perf_evsel__print_ip(evsel, sample, al, 555 perf_evsel__print_ip(evsel, sample, al,
550 output[attr->type].print_ip_opts, 556 output[attr->type].print_ip_opts,
551 PERF_MAX_STACK_DEPTH); 557 scripting_max_stack);
552 } 558 }
553 559
554 if (PRINT_FIELD(IREGS)) 560 if (PRINT_FIELD(IREGS))
@@ -1695,6 +1701,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1695 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events, 1701 OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
1696 "Show context switch events (if recorded)"), 1702 "Show context switch events (if recorded)"),
1697 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), 1703 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
1704 OPT_BOOLEAN(0, "ns", &nanosecs,
1705 "Use 9 decimal places when displaying time"),
1698 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 1706 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
1699 "Instruction Tracing options", 1707 "Instruction Tracing options",
1700 itrace_parse_synth_opts), 1708 itrace_parse_synth_opts),
@@ -1740,6 +1748,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1740 } 1748 }
1741 } 1749 }
1742 1750
1751 if (itrace_synth_opts.callchain &&
1752 itrace_synth_opts.callchain_sz > scripting_max_stack)
1753 scripting_max_stack = itrace_synth_opts.callchain_sz;
1754
1743 /* make sure PERF_EXEC_PATH is set for scripts */ 1755 /* make sure PERF_EXEC_PATH is set for scripts */
1744 perf_set_argv_exec_path(perf_exec_path()); 1756 perf_set_argv_exec_path(perf_exec_path());
1745 1757
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index bdaf44f24d5d..38d4d6cac823 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -655,7 +655,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
655{ 655{
656 const char *name = sym->name; 656 const char *name = sym->name;
657 657
658 if (!map->dso->kernel) 658 if (!__map__is_kernel(map))
659 return 0; 659 return 0;
660 /* 660 /*
661 * ppc64 uses function descriptors and appends a '.' to the 661 * ppc64 uses function descriptors and appends a '.' to the
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 84a32037a80f..1b02cdc0cab6 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -61,6 +61,142 @@ import datetime
61# 61#
62# An example of using the database is provided by the script 62# An example of using the database is provided by the script
63# call-graph-from-postgresql.py. Refer to that script for details. 63# call-graph-from-postgresql.py. Refer to that script for details.
64#
65# Tables:
66#
67# The tables largely correspond to perf tools' data structures. They are largely self-explanatory.
68#
69# samples
70#
71# 'samples' is the main table. It represents what instruction was executing at a point in time
72# when something (a selected event) happened. The memory address is the instruction pointer or 'ip'.
73#
74# calls
75#
76# 'calls' represents function calls and is related to 'samples' by 'call_id' and 'return_id'.
77# 'calls' is only created when the 'calls' option to this script is specified.
78#
79# call_paths
80#
81# 'call_paths' represents all the call stacks. Each 'call' has an associated record in 'call_paths'.
82# 'calls_paths' is only created when the 'calls' option to this script is specified.
83#
84# branch_types
85#
86# 'branch_types' provides descriptions for each type of branch.
87#
88# comm_threads
89#
90# 'comm_threads' shows how 'comms' relates to 'threads'.
91#
92# comms
93#
94# 'comms' contains a record for each 'comm' - the name given to the executable that is running.
95#
96# dsos
97#
98# 'dsos' contains a record for each executable file or library.
99#
100# machines
101#
102# 'machines' can be used to distinguish virtual machines if virtualization is supported.
103#
104# selected_events
105#
106# 'selected_events' contains a record for each kind of event that has been sampled.
107#
108# symbols
109#
110# 'symbols' contains a record for each symbol. Only symbols that have samples are present.
111#
112# threads
113#
114# 'threads' contains a record for each thread.
115#
116# Views:
117#
118# Most of the tables have views for more friendly display. The views are:
119#
120# calls_view
121# call_paths_view
122# comm_threads_view
123# dsos_view
124# machines_view
125# samples_view
126# symbols_view
127# threads_view
128#
129# More examples of browsing the database with psql:
130# Note that some of the examples are not the most optimal SQL query.
131# Note that call information is only available if the script's 'calls' option has been used.
132#
133# Top 10 function calls (not aggregated by symbol):
134#
135# SELECT * FROM calls_view ORDER BY elapsed_time DESC LIMIT 10;
136#
137# Top 10 function calls (aggregated by symbol):
138#
139# SELECT symbol_id,(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,
140# SUM(elapsed_time) AS tot_elapsed_time,SUM(branch_count) AS tot_branch_count
141# FROM calls_view GROUP BY symbol_id ORDER BY tot_elapsed_time DESC LIMIT 10;
142#
143# Note that the branch count gives a rough estimation of cpu usage, so functions
144# that took a long time but have a relatively low branch count must have spent time
145# waiting.
146#
147# Find symbols by pattern matching on part of the name (e.g. names containing 'alloc'):
148#
149# SELECT * FROM symbols_view WHERE name LIKE '%alloc%';
150#
151# Top 10 function calls for a specific symbol (e.g. whose symbol_id is 187):
152#
153# SELECT * FROM calls_view WHERE symbol_id = 187 ORDER BY elapsed_time DESC LIMIT 10;
154#
155# Show function calls made by function in the same context (i.e. same call path) (e.g. one with call_path_id 254):
156#
157# SELECT * FROM calls_view WHERE parent_call_path_id = 254;
158#
159# Show branches made during a function call (e.g. where call_id is 29357 and return_id is 29370 and tid is 29670)
160#
161# SELECT * FROM samples_view WHERE id >= 29357 AND id <= 29370 AND tid = 29670 AND event LIKE 'branches%';
162#
163# Show transactions:
164#
165# SELECT * FROM samples_view WHERE event = 'transactions';
166#
167# Note transaction start has 'in_tx' true whereas, transaction end has 'in_tx' false.
168# Transaction aborts have branch_type_name 'transaction abort'
169#
170# Show transaction aborts:
171#
172# SELECT * FROM samples_view WHERE event = 'transactions' AND branch_type_name = 'transaction abort';
173#
174# To print a call stack requires walking the call_paths table. For example this python script:
175# #!/usr/bin/python2
176#
177# import sys
178# from PySide.QtSql import *
179#
180# if __name__ == '__main__':
181# if (len(sys.argv) < 3):
182# print >> sys.stderr, "Usage is: printcallstack.py <database name> <call_path_id>"
183# raise Exception("Too few arguments")
184# dbname = sys.argv[1]
185# call_path_id = sys.argv[2]
186# db = QSqlDatabase.addDatabase('QPSQL')
187# db.setDatabaseName(dbname)
188# if not db.open():
189# raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
190# query = QSqlQuery(db)
191# print " id ip symbol_id symbol dso_id dso_short_name"
192# while call_path_id != 0 and call_path_id != 1:
193# ret = query.exec_('SELECT * FROM call_paths_view WHERE id = ' + str(call_path_id))
194# if not ret:
195# raise Exception("Query failed: " + query.lastError().text())
196# if not query.next():
197# raise Exception("Query failed")
198# print "{0:>6} {1:>10} {2:>9} {3:<30} {4:>6} {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5))
199# call_path_id = query.value(6)
64 200
65from PySide.QtSql import * 201from PySide.QtSql import *
66 202
@@ -244,6 +380,91 @@ if perf_db_export_calls:
244 'parent_call_path_id bigint,' 380 'parent_call_path_id bigint,'
245 'flags integer)') 381 'flags integer)')
246 382
383do_query(query, 'CREATE VIEW machines_view AS '
384 'SELECT '
385 'id,'
386 'pid,'
387 'root_dir,'
388 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
389 ' FROM machines')
390
391do_query(query, 'CREATE VIEW dsos_view AS '
392 'SELECT '
393 'id,'
394 'machine_id,'
395 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
396 'short_name,'
397 'long_name,'
398 'build_id'
399 ' FROM dsos')
400
401do_query(query, 'CREATE VIEW symbols_view AS '
402 'SELECT '
403 'id,'
404 'name,'
405 '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
406 'dso_id,'
407 'sym_start,'
408 'sym_end,'
409 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
410 ' FROM symbols')
411
412do_query(query, 'CREATE VIEW threads_view AS '
413 'SELECT '
414 'id,'
415 'machine_id,'
416 '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
417 'process_id,'
418 'pid,'
419 'tid'
420 ' FROM threads')
421
422do_query(query, 'CREATE VIEW comm_threads_view AS '
423 'SELECT '
424 'comm_id,'
425 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
426 'thread_id,'
427 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
428 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
429 ' FROM comm_threads')
430
431if perf_db_export_calls:
432 do_query(query, 'CREATE VIEW call_paths_view AS '
433 'SELECT '
434 'c.id,'
435 'to_hex(c.ip) AS ip,'
436 'c.symbol_id,'
437 '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
438 '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
439 '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
440 'c.parent_id,'
441 'to_hex(p.ip) AS parent_ip,'
442 'p.symbol_id AS parent_symbol_id,'
443 '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
444 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
445 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
446 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
447 do_query(query, 'CREATE VIEW calls_view AS '
448 'SELECT '
449 'calls.id,'
450 'thread_id,'
451 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
452 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
453 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
454 'call_path_id,'
455 'to_hex(ip) AS ip,'
456 'symbol_id,'
457 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
458 'call_time,'
459 'return_time,'
460 'return_time - call_time AS elapsed_time,'
461 'branch_count,'
462 'call_id,'
463 'return_id,'
464 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,'
465 'parent_call_path_id'
466 ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
467
247do_query(query, 'CREATE VIEW samples_view AS ' 468do_query(query, 'CREATE VIEW samples_view AS '
248 'SELECT ' 469 'SELECT '
249 'id,' 470 'id,'
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index e1f28f4cdc8e..a4e9b370c037 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1527,7 +1527,7 @@ add_thread_opt(struct hist_browser *browser, struct popup_action *act,
1527static int 1527static int
1528do_zoom_dso(struct hist_browser *browser, struct popup_action *act) 1528do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
1529{ 1529{
1530 struct dso *dso = act->dso; 1530 struct map *map = act->ms.map;
1531 1531
1532 if (browser->hists->dso_filter) { 1532 if (browser->hists->dso_filter) {
1533 pstack__remove(browser->pstack, &browser->hists->dso_filter); 1533 pstack__remove(browser->pstack, &browser->hists->dso_filter);
@@ -1535,11 +1535,11 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
1535 browser->hists->dso_filter = NULL; 1535 browser->hists->dso_filter = NULL;
1536 ui_helpline__pop(); 1536 ui_helpline__pop();
1537 } else { 1537 } else {
1538 if (dso == NULL) 1538 if (map == NULL)
1539 return 0; 1539 return 0;
1540 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", 1540 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
1541 dso->kernel ? "the Kernel" : dso->short_name); 1541 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name);
1542 browser->hists->dso_filter = dso; 1542 browser->hists->dso_filter = map->dso;
1543 perf_hpp__set_elide(HISTC_DSO, true); 1543 perf_hpp__set_elide(HISTC_DSO, true);
1544 pstack__push(browser->pstack, &browser->hists->dso_filter); 1544 pstack__push(browser->pstack, &browser->hists->dso_filter);
1545 } 1545 }
@@ -1551,17 +1551,18 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
1551 1551
1552static int 1552static int
1553add_dso_opt(struct hist_browser *browser, struct popup_action *act, 1553add_dso_opt(struct hist_browser *browser, struct popup_action *act,
1554 char **optstr, struct dso *dso) 1554 char **optstr, struct map *map)
1555{ 1555{
1556 if (dso == NULL) 1556 if (map == NULL)
1557 return 0; 1557 return 0;
1558 1558
1559 if (asprintf(optstr, "Zoom %s %s DSO", 1559 if (asprintf(optstr, "Zoom %s %s DSO",
1560 browser->hists->dso_filter ? "out of" : "into", 1560 browser->hists->dso_filter ? "out of" : "into",
1561 dso->kernel ? "the Kernel" : dso->short_name) < 0) 1561 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name) < 0)
1562 return 0; 1562 return 0;
1563 1563
1564 act->dso = dso; 1564 act->ms.map = map;
1565 act->dso = map->dso;
1565 act->fn = do_zoom_dso; 1566 act->fn = do_zoom_dso;
1566 return 1; 1567 return 1;
1567} 1568}
@@ -1814,6 +1815,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1814 while (1) { 1815 while (1) {
1815 struct thread *thread = NULL; 1816 struct thread *thread = NULL;
1816 struct dso *dso = NULL; 1817 struct dso *dso = NULL;
1818 struct map *map = NULL;
1817 int choice = 0; 1819 int choice = 0;
1818 int socked_id = -1; 1820 int socked_id = -1;
1819 1821
@@ -1823,7 +1825,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1823 1825
1824 if (browser->he_selection != NULL) { 1826 if (browser->he_selection != NULL) {
1825 thread = hist_browser__selected_thread(browser); 1827 thread = hist_browser__selected_thread(browser);
1826 dso = browser->selection->map ? browser->selection->map->dso : NULL; 1828 map = browser->selection->map;
1829 if (map)
1830 dso = map->dso;
1827 socked_id = browser->he_selection->socket; 1831 socked_id = browser->he_selection->socket;
1828 } 1832 }
1829 switch (key) { 1833 switch (key) {
@@ -2014,7 +2018,7 @@ skip_annotation:
2014 nr_options += add_thread_opt(browser, &actions[nr_options], 2018 nr_options += add_thread_opt(browser, &actions[nr_options],
2015 &options[nr_options], thread); 2019 &options[nr_options], thread);
2016 nr_options += add_dso_opt(browser, &actions[nr_options], 2020 nr_options += add_dso_opt(browser, &actions[nr_options],
2017 &options[nr_options], dso); 2021 &options[nr_options], map);
2018 nr_options += add_map_opt(browser, &actions[nr_options], 2022 nr_options += add_map_opt(browser, &actions[nr_options],
2019 &options[nr_options], 2023 &options[nr_options],
2020 browser->selection ? 2024 browser->selection ?
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index a980e7c50ee0..7f10430af39c 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -926,6 +926,8 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool,
926#define PERF_ITRACE_DEFAULT_PERIOD 100000 926#define PERF_ITRACE_DEFAULT_PERIOD 100000
927#define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16 927#define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16
928#define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024 928#define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024
929#define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64
930#define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024
929 931
930void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) 932void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
931{ 933{
@@ -936,6 +938,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
936 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; 938 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
937 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 939 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
938 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; 940 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
941 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
939} 942}
940 943
941/* 944/*
@@ -950,6 +953,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
950 const char *p; 953 const char *p;
951 char *endptr; 954 char *endptr;
952 bool period_type_set = false; 955 bool period_type_set = false;
956 bool period_set = false;
953 957
954 synth_opts->set = true; 958 synth_opts->set = true;
955 959
@@ -971,6 +975,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
971 p += 1; 975 p += 1;
972 if (isdigit(*p)) { 976 if (isdigit(*p)) {
973 synth_opts->period = strtoull(p, &endptr, 10); 977 synth_opts->period = strtoull(p, &endptr, 10);
978 period_set = true;
974 p = endptr; 979 p = endptr;
975 while (*p == ' ' || *p == ',') 980 while (*p == ' ' || *p == ',')
976 p += 1; 981 p += 1;
@@ -1041,6 +1046,23 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
1041 synth_opts->callchain_sz = val; 1046 synth_opts->callchain_sz = val;
1042 } 1047 }
1043 break; 1048 break;
1049 case 'l':
1050 synth_opts->last_branch = true;
1051 synth_opts->last_branch_sz =
1052 PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
1053 while (*p == ' ' || *p == ',')
1054 p += 1;
1055 if (isdigit(*p)) {
1056 unsigned int val;
1057
1058 val = strtoul(p, &endptr, 10);
1059 p = endptr;
1060 if (!val ||
1061 val > PERF_ITRACE_MAX_LAST_BRANCH_SZ)
1062 goto out_err;
1063 synth_opts->last_branch_sz = val;
1064 }
1065 break;
1044 case ' ': 1066 case ' ':
1045 case ',': 1067 case ',':
1046 break; 1068 break;
@@ -1053,7 +1075,7 @@ out:
1053 if (!period_type_set) 1075 if (!period_type_set)
1054 synth_opts->period_type = 1076 synth_opts->period_type =
1055 PERF_ITRACE_DEFAULT_PERIOD_TYPE; 1077 PERF_ITRACE_DEFAULT_PERIOD_TYPE;
1056 if (!synth_opts->period) 1078 if (!period_set)
1057 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 1079 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
1058 } 1080 }
1059 1081
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index bf72b77a588a..b86f90db1352 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -63,7 +63,9 @@ enum itrace_period_type {
63 * @calls: limit branch samples to calls (can be combined with @returns) 63 * @calls: limit branch samples to calls (can be combined with @returns)
64 * @returns: limit branch samples to returns (can be combined with @calls) 64 * @returns: limit branch samples to returns (can be combined with @calls)
65 * @callchain: add callchain to 'instructions' events 65 * @callchain: add callchain to 'instructions' events
66 * @last_branch: add branch context to 'instruction' events
66 * @callchain_sz: maximum callchain size 67 * @callchain_sz: maximum callchain size
68 * @last_branch_sz: branch context size
67 * @period: 'instructions' events period 69 * @period: 'instructions' events period
68 * @period_type: 'instructions' events period type 70 * @period_type: 'instructions' events period type
69 */ 71 */
@@ -79,7 +81,9 @@ struct itrace_synth_opts {
79 bool calls; 81 bool calls;
80 bool returns; 82 bool returns;
81 bool callchain; 83 bool callchain;
84 bool last_branch;
82 unsigned int callchain_sz; 85 unsigned int callchain_sz;
86 unsigned int last_branch_sz;
83 unsigned long long period; 87 unsigned long long period;
84 enum itrace_period_type period_type; 88 enum itrace_period_type period_type;
85}; 89};
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6214ad47d554..b1bb348ec3b6 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -378,7 +378,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
378 for (pos = maps__first(maps); pos; pos = map__next(pos)) { 378 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
379 size_t size; 379 size_t size;
380 380
381 if (pos->dso->kernel) 381 if (__map__is_kernel(pos))
382 continue; 382 continue;
383 383
384 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 384 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index be5cbc7be889..a0dbcbd4f6d8 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -257,6 +257,7 @@ struct events_stats {
257 u64 total_non_filtered_period; 257 u64 total_non_filtered_period;
258 u64 total_lost; 258 u64 total_lost;
259 u64 total_lost_samples; 259 u64 total_lost_samples;
260 u64 total_aux_lost;
260 u64 total_invalid_chains; 261 u64 total_invalid_chains;
261 u32 nr_events[PERF_RECORD_HEADER_MAX]; 262 u32 nr_events[PERF_RECORD_HEADER_MAX];
262 u32 nr_non_filtered_samples; 263 u32 nr_non_filtered_samples;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a8643735dcea..89546228b8ed 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -165,6 +165,13 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
165 __perf_evlist__propagate_maps(evlist, entry); 165 __perf_evlist__propagate_maps(evlist, entry);
166} 166}
167 167
168void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel)
169{
170 evsel->evlist = NULL;
171 list_del_init(&evsel->node);
172 evlist->nr_entries -= 1;
173}
174
168void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 175void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
169 struct list_head *list) 176 struct list_head *list)
170{ 177{
@@ -617,6 +624,21 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
617 return NULL; 624 return NULL;
618} 625}
619 626
627struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
628 u64 id)
629{
630 struct perf_sample_id *sid;
631
632 if (!id)
633 return NULL;
634
635 sid = perf_evlist__id2sid(evlist, id);
636 if (sid)
637 return sid->evsel;
638
639 return NULL;
640}
641
620static int perf_evlist__event2id(struct perf_evlist *evlist, 642static int perf_evlist__event2id(struct perf_evlist *evlist,
621 union perf_event *event, u64 *id) 643 union perf_event *event, u64 *id)
622{ 644{
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 115d8b53c601..66bc9d4c0869 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -73,6 +73,7 @@ void perf_evlist__exit(struct perf_evlist *evlist);
73void perf_evlist__delete(struct perf_evlist *evlist); 73void perf_evlist__delete(struct perf_evlist *evlist);
74 74
75void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 75void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
76void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel);
76int perf_evlist__add_default(struct perf_evlist *evlist); 77int perf_evlist__add_default(struct perf_evlist *evlist);
77int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 78int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
78 struct perf_event_attr *attrs, size_t nr_attrs); 79 struct perf_event_attr *attrs, size_t nr_attrs);
@@ -104,6 +105,8 @@ int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mas
104int perf_evlist__poll(struct perf_evlist *evlist, int timeout); 105int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
105 106
106struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 107struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
108struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
109 u64 id);
107 110
108struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); 111struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
109 112
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b3567a25f0c4..0cad9e07c5b4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -695,7 +695,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter,
695} 695}
696 696
697static int 697static int
698iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused, 698iter_prepare_cumulative_entry(struct hist_entry_iter *iter,
699 struct addr_location *al __maybe_unused) 699 struct addr_location *al __maybe_unused)
700{ 700{
701 struct hist_entry **he_cache; 701 struct hist_entry **he_cache;
@@ -707,7 +707,7 @@ iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused,
707 * cumulated only one time to prevent entries more than 100% 707 * cumulated only one time to prevent entries more than 100%
708 * overhead. 708 * overhead.
709 */ 709 */
710 he_cache = malloc(sizeof(*he_cache) * (PERF_MAX_STACK_DEPTH + 1)); 710 he_cache = malloc(sizeof(*he_cache) * (iter->max_stack + 1));
711 if (he_cache == NULL) 711 if (he_cache == NULL)
712 return -ENOMEM; 712 return -ENOMEM;
713 713
@@ -868,6 +868,8 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
868 if (err) 868 if (err)
869 return err; 869 return err;
870 870
871 iter->max_stack = max_stack_depth;
872
871 err = iter->ops->prepare_entry(iter, al); 873 err = iter->ops->prepare_entry(iter, al);
872 if (err) 874 if (err)
873 goto out; 875 goto out;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 4d6aa1dbdaee..8c20a8f6b214 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -90,6 +90,7 @@ struct hist_entry_iter {
90 int curr; 90 int curr;
91 91
92 bool hide_unresolved; 92 bool hide_unresolved;
93 int max_stack;
93 94
94 struct perf_evsel *evsel; 95 struct perf_evsel *evsel;
95 struct perf_sample *sample; 96 struct perf_sample *sample;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 22ba50224319..9409d014b46c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -650,7 +650,7 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
650 if (data->from_mtc && timestamp < data->timestamp && 650 if (data->from_mtc && timestamp < data->timestamp &&
651 data->timestamp - timestamp < decoder->tsc_slip) 651 data->timestamp - timestamp < decoder->tsc_slip)
652 return 1; 652 return 1;
653 while (timestamp < data->timestamp) 653 if (timestamp < data->timestamp)
654 timestamp += (1ULL << 56); 654 timestamp += (1ULL << 56);
655 if (pkt_info->last_packet_type != INTEL_PT_CYC) { 655 if (pkt_info->last_packet_type != INTEL_PT_CYC) {
656 if (data->from_mtc) 656 if (data->from_mtc)
@@ -1191,7 +1191,7 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder)
1191 timestamp); 1191 timestamp);
1192 timestamp = decoder->timestamp; 1192 timestamp = decoder->timestamp;
1193 } 1193 }
1194 while (timestamp < decoder->timestamp) { 1194 if (timestamp < decoder->timestamp) {
1195 intel_pt_log_to("Wraparound timestamp", timestamp); 1195 intel_pt_log_to("Wraparound timestamp", timestamp);
1196 timestamp += (1ULL << 56); 1196 timestamp += (1ULL << 56);
1197 decoder->tsc_timestamp = timestamp; 1197 decoder->tsc_timestamp = timestamp;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index d09c7d9f9050..319bef33a64b 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -29,18 +29,18 @@
29 29
30static FILE *f; 30static FILE *f;
31static char log_name[MAX_LOG_NAME]; 31static char log_name[MAX_LOG_NAME];
32static bool enable_logging; 32bool intel_pt_enable_logging;
33 33
34void intel_pt_log_enable(void) 34void intel_pt_log_enable(void)
35{ 35{
36 enable_logging = true; 36 intel_pt_enable_logging = true;
37} 37}
38 38
39void intel_pt_log_disable(void) 39void intel_pt_log_disable(void)
40{ 40{
41 if (f) 41 if (f)
42 fflush(f); 42 fflush(f);
43 enable_logging = false; 43 intel_pt_enable_logging = false;
44} 44}
45 45
46void intel_pt_log_set_name(const char *name) 46void intel_pt_log_set_name(const char *name)
@@ -80,7 +80,7 @@ static void intel_pt_print_no_data(uint64_t pos, int indent)
80 80
81static int intel_pt_log_open(void) 81static int intel_pt_log_open(void)
82{ 82{
83 if (!enable_logging) 83 if (!intel_pt_enable_logging)
84 return -1; 84 return -1;
85 85
86 if (f) 86 if (f)
@@ -91,15 +91,15 @@ static int intel_pt_log_open(void)
91 91
92 f = fopen(log_name, "w+"); 92 f = fopen(log_name, "w+");
93 if (!f) { 93 if (!f) {
94 enable_logging = false; 94 intel_pt_enable_logging = false;
95 return -1; 95 return -1;
96 } 96 }
97 97
98 return 0; 98 return 0;
99} 99}
100 100
101void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, 101void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
102 uint64_t pos, const unsigned char *buf) 102 uint64_t pos, const unsigned char *buf)
103{ 103{
104 char desc[INTEL_PT_PKT_DESC_MAX]; 104 char desc[INTEL_PT_PKT_DESC_MAX];
105 105
@@ -111,7 +111,7 @@ void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
111 fprintf(f, "%s\n", desc); 111 fprintf(f, "%s\n", desc);
112} 112}
113 113
114void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip) 114void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
115{ 115{
116 char desc[INTEL_PT_INSN_DESC_MAX]; 116 char desc[INTEL_PT_INSN_DESC_MAX];
117 size_t len = intel_pt_insn->length; 117 size_t len = intel_pt_insn->length;
@@ -128,7 +128,8 @@ void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
128 fprintf(f, "Bad instruction!\n"); 128 fprintf(f, "Bad instruction!\n");
129} 129}
130 130
131void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip) 131void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
132 uint64_t ip)
132{ 133{
133 char desc[INTEL_PT_INSN_DESC_MAX]; 134 char desc[INTEL_PT_INSN_DESC_MAX];
134 135
@@ -142,7 +143,7 @@ void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
142 fprintf(f, "Bad instruction!\n"); 143 fprintf(f, "Bad instruction!\n");
143} 144}
144 145
145void intel_pt_log(const char *fmt, ...) 146void __intel_pt_log(const char *fmt, ...)
146{ 147{
147 va_list args; 148 va_list args;
148 149
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
index db3942f83677..debe751dc3d6 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
@@ -25,20 +25,46 @@ void intel_pt_log_enable(void);
25void intel_pt_log_disable(void); 25void intel_pt_log_disable(void);
26void intel_pt_log_set_name(const char *name); 26void intel_pt_log_set_name(const char *name);
27 27
28void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, 28void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
29 uint64_t pos, const unsigned char *buf); 29 uint64_t pos, const unsigned char *buf);
30 30
31struct intel_pt_insn; 31struct intel_pt_insn;
32 32
33void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip); 33void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip);
34void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, 34void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
35 uint64_t ip); 35 uint64_t ip);
36 36
37__attribute__((format(printf, 1, 2))) 37__attribute__((format(printf, 1, 2)))
38void intel_pt_log(const char *fmt, ...); 38void __intel_pt_log(const char *fmt, ...);
39
40#define intel_pt_log(fmt, ...) \
41 do { \
42 if (intel_pt_enable_logging) \
43 __intel_pt_log(fmt, ##__VA_ARGS__); \
44 } while (0)
45
46#define intel_pt_log_packet(arg, ...) \
47 do { \
48 if (intel_pt_enable_logging) \
49 __intel_pt_log_packet(arg, ##__VA_ARGS__); \
50 } while (0)
51
52#define intel_pt_log_insn(arg, ...) \
53 do { \
54 if (intel_pt_enable_logging) \
55 __intel_pt_log_insn(arg, ##__VA_ARGS__); \
56 } while (0)
57
58#define intel_pt_log_insn_no_data(arg, ...) \
59 do { \
60 if (intel_pt_enable_logging) \
61 __intel_pt_log_insn_no_data(arg, ##__VA_ARGS__); \
62 } while (0)
39 63
40#define x64_fmt "0x%" PRIx64 64#define x64_fmt "0x%" PRIx64
41 65
66extern bool intel_pt_enable_logging;
67
42static inline void intel_pt_log_at(const char *msg, uint64_t u) 68static inline void intel_pt_log_at(const char *msg, uint64_t u)
43{ 69{
44 intel_pt_log("%s at " x64_fmt "\n", msg, u); 70 intel_pt_log("%s at " x64_fmt "\n", msg, u);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 38942e1eac8f..03ff072b5993 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -22,6 +22,7 @@
22#include "../perf.h" 22#include "../perf.h"
23#include "session.h" 23#include "session.h"
24#include "machine.h" 24#include "machine.h"
25#include "sort.h"
25#include "tool.h" 26#include "tool.h"
26#include "event.h" 27#include "event.h"
27#include "evlist.h" 28#include "evlist.h"
@@ -63,6 +64,7 @@ struct intel_pt {
63 bool data_queued; 64 bool data_queued;
64 bool est_tsc; 65 bool est_tsc;
65 bool sync_switch; 66 bool sync_switch;
67 bool mispred_all;
66 int have_sched_switch; 68 int have_sched_switch;
67 u32 pmu_type; 69 u32 pmu_type;
68 u64 kernel_start; 70 u64 kernel_start;
@@ -115,6 +117,9 @@ struct intel_pt_queue {
115 void *decoder; 117 void *decoder;
116 const struct intel_pt_state *state; 118 const struct intel_pt_state *state;
117 struct ip_callchain *chain; 119 struct ip_callchain *chain;
120 struct branch_stack *last_branch;
121 struct branch_stack *last_branch_rb;
122 size_t last_branch_pos;
118 union perf_event *event_buf; 123 union perf_event *event_buf;
119 bool on_heap; 124 bool on_heap;
120 bool stop; 125 bool stop;
@@ -675,6 +680,19 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
675 goto out_free; 680 goto out_free;
676 } 681 }
677 682
683 if (pt->synth_opts.last_branch) {
684 size_t sz = sizeof(struct branch_stack);
685
686 sz += pt->synth_opts.last_branch_sz *
687 sizeof(struct branch_entry);
688 ptq->last_branch = zalloc(sz);
689 if (!ptq->last_branch)
690 goto out_free;
691 ptq->last_branch_rb = zalloc(sz);
692 if (!ptq->last_branch_rb)
693 goto out_free;
694 }
695
678 ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE); 696 ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
679 if (!ptq->event_buf) 697 if (!ptq->event_buf)
680 goto out_free; 698 goto out_free;
@@ -720,7 +738,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
720 738
721 if (!params.period) { 739 if (!params.period) {
722 params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS; 740 params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS;
723 params.period = 1000; 741 params.period = 1;
724 } 742 }
725 } 743 }
726 744
@@ -732,6 +750,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
732 750
733out_free: 751out_free:
734 zfree(&ptq->event_buf); 752 zfree(&ptq->event_buf);
753 zfree(&ptq->last_branch);
754 zfree(&ptq->last_branch_rb);
735 zfree(&ptq->chain); 755 zfree(&ptq->chain);
736 free(ptq); 756 free(ptq);
737 return NULL; 757 return NULL;
@@ -746,6 +766,8 @@ static void intel_pt_free_queue(void *priv)
746 thread__zput(ptq->thread); 766 thread__zput(ptq->thread);
747 intel_pt_decoder_free(ptq->decoder); 767 intel_pt_decoder_free(ptq->decoder);
748 zfree(&ptq->event_buf); 768 zfree(&ptq->event_buf);
769 zfree(&ptq->last_branch);
770 zfree(&ptq->last_branch_rb);
749 zfree(&ptq->chain); 771 zfree(&ptq->chain);
750 free(ptq); 772 free(ptq);
751} 773}
@@ -876,6 +898,58 @@ static int intel_pt_setup_queues(struct intel_pt *pt)
876 return 0; 898 return 0;
877} 899}
878 900
901static inline void intel_pt_copy_last_branch_rb(struct intel_pt_queue *ptq)
902{
903 struct branch_stack *bs_src = ptq->last_branch_rb;
904 struct branch_stack *bs_dst = ptq->last_branch;
905 size_t nr = 0;
906
907 bs_dst->nr = bs_src->nr;
908
909 if (!bs_src->nr)
910 return;
911
912 nr = ptq->pt->synth_opts.last_branch_sz - ptq->last_branch_pos;
913 memcpy(&bs_dst->entries[0],
914 &bs_src->entries[ptq->last_branch_pos],
915 sizeof(struct branch_entry) * nr);
916
917 if (bs_src->nr >= ptq->pt->synth_opts.last_branch_sz) {
918 memcpy(&bs_dst->entries[nr],
919 &bs_src->entries[0],
920 sizeof(struct branch_entry) * ptq->last_branch_pos);
921 }
922}
923
924static inline void intel_pt_reset_last_branch_rb(struct intel_pt_queue *ptq)
925{
926 ptq->last_branch_pos = 0;
927 ptq->last_branch_rb->nr = 0;
928}
929
930static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq)
931{
932 const struct intel_pt_state *state = ptq->state;
933 struct branch_stack *bs = ptq->last_branch_rb;
934 struct branch_entry *be;
935
936 if (!ptq->last_branch_pos)
937 ptq->last_branch_pos = ptq->pt->synth_opts.last_branch_sz;
938
939 ptq->last_branch_pos -= 1;
940
941 be = &bs->entries[ptq->last_branch_pos];
942 be->from = state->from_ip;
943 be->to = state->to_ip;
944 be->flags.abort = !!(state->flags & INTEL_PT_ABORT_TX);
945 be->flags.in_tx = !!(state->flags & INTEL_PT_IN_TX);
946 /* No support for mispredict */
947 be->flags.mispred = ptq->pt->mispred_all;
948
949 if (bs->nr < ptq->pt->synth_opts.last_branch_sz)
950 bs->nr += 1;
951}
952
879static int intel_pt_inject_event(union perf_event *event, 953static int intel_pt_inject_event(union perf_event *event,
880 struct perf_sample *sample, u64 type, 954 struct perf_sample *sample, u64 type,
881 bool swapped) 955 bool swapped)
@@ -890,6 +964,13 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
890 struct intel_pt *pt = ptq->pt; 964 struct intel_pt *pt = ptq->pt;
891 union perf_event *event = ptq->event_buf; 965 union perf_event *event = ptq->event_buf;
892 struct perf_sample sample = { .ip = 0, }; 966 struct perf_sample sample = { .ip = 0, };
967 struct dummy_branch_stack {
968 u64 nr;
969 struct branch_entry entries;
970 } dummy_bs;
971
972 if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
973 return 0;
893 974
894 event->sample.header.type = PERF_RECORD_SAMPLE; 975 event->sample.header.type = PERF_RECORD_SAMPLE;
895 event->sample.header.misc = PERF_RECORD_MISC_USER; 976 event->sample.header.misc = PERF_RECORD_MISC_USER;
@@ -909,8 +990,20 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
909 sample.flags = ptq->flags; 990 sample.flags = ptq->flags;
910 sample.insn_len = ptq->insn_len; 991 sample.insn_len = ptq->insn_len;
911 992
912 if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) 993 /*
913 return 0; 994 * perf report cannot handle events without a branch stack when using
995 * SORT_MODE__BRANCH so make a dummy one.
996 */
997 if (pt->synth_opts.last_branch && sort__mode == SORT_MODE__BRANCH) {
998 dummy_bs = (struct dummy_branch_stack){
999 .nr = 1,
1000 .entries = {
1001 .from = sample.ip,
1002 .to = sample.addr,
1003 },
1004 };
1005 sample.branch_stack = (struct branch_stack *)&dummy_bs;
1006 }
914 1007
915 if (pt->synth_opts.inject) { 1008 if (pt->synth_opts.inject) {
916 ret = intel_pt_inject_event(event, &sample, 1009 ret = intel_pt_inject_event(event, &sample,
@@ -961,6 +1054,11 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
961 sample.callchain = ptq->chain; 1054 sample.callchain = ptq->chain;
962 } 1055 }
963 1056
1057 if (pt->synth_opts.last_branch) {
1058 intel_pt_copy_last_branch_rb(ptq);
1059 sample.branch_stack = ptq->last_branch;
1060 }
1061
964 if (pt->synth_opts.inject) { 1062 if (pt->synth_opts.inject) {
965 ret = intel_pt_inject_event(event, &sample, 1063 ret = intel_pt_inject_event(event, &sample,
966 pt->instructions_sample_type, 1064 pt->instructions_sample_type,
@@ -974,6 +1072,9 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
974 pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n", 1072 pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n",
975 ret); 1073 ret);
976 1074
1075 if (pt->synth_opts.last_branch)
1076 intel_pt_reset_last_branch_rb(ptq);
1077
977 return ret; 1078 return ret;
978} 1079}
979 1080
@@ -1008,6 +1109,11 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1008 sample.callchain = ptq->chain; 1109 sample.callchain = ptq->chain;
1009 } 1110 }
1010 1111
1112 if (pt->synth_opts.last_branch) {
1113 intel_pt_copy_last_branch_rb(ptq);
1114 sample.branch_stack = ptq->last_branch;
1115 }
1116
1011 if (pt->synth_opts.inject) { 1117 if (pt->synth_opts.inject) {
1012 ret = intel_pt_inject_event(event, &sample, 1118 ret = intel_pt_inject_event(event, &sample,
1013 pt->transactions_sample_type, 1119 pt->transactions_sample_type,
@@ -1021,6 +1127,9 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1021 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n", 1127 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n",
1022 ret); 1128 ret);
1023 1129
1130 if (pt->synth_opts.callchain)
1131 intel_pt_reset_last_branch_rb(ptq);
1132
1024 return ret; 1133 return ret;
1025} 1134}
1026 1135
@@ -1116,6 +1225,9 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1116 return err; 1225 return err;
1117 } 1226 }
1118 1227
1228 if (pt->synth_opts.last_branch)
1229 intel_pt_update_last_branch_rb(ptq);
1230
1119 if (!pt->sync_switch) 1231 if (!pt->sync_switch)
1120 return 0; 1232 return 0;
1121 1233
@@ -1763,6 +1875,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1763 pt->instructions_sample_period = attr.sample_period; 1875 pt->instructions_sample_period = attr.sample_period;
1764 if (pt->synth_opts.callchain) 1876 if (pt->synth_opts.callchain)
1765 attr.sample_type |= PERF_SAMPLE_CALLCHAIN; 1877 attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
1878 if (pt->synth_opts.last_branch)
1879 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
1766 pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", 1880 pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
1767 id, (u64)attr.sample_type); 1881 id, (u64)attr.sample_type);
1768 err = intel_pt_synth_event(session, &attr, id); 1882 err = intel_pt_synth_event(session, &attr, id);
@@ -1782,6 +1896,8 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1782 attr.sample_period = 1; 1896 attr.sample_period = 1;
1783 if (pt->synth_opts.callchain) 1897 if (pt->synth_opts.callchain)
1784 attr.sample_type |= PERF_SAMPLE_CALLCHAIN; 1898 attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
1899 if (pt->synth_opts.last_branch)
1900 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
1785 pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", 1901 pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
1786 id, (u64)attr.sample_type); 1902 id, (u64)attr.sample_type);
1787 err = intel_pt_synth_event(session, &attr, id); 1903 err = intel_pt_synth_event(session, &attr, id);
@@ -1808,6 +1924,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1808 attr.sample_period = 1; 1924 attr.sample_period = 1;
1809 attr.sample_type |= PERF_SAMPLE_ADDR; 1925 attr.sample_type |= PERF_SAMPLE_ADDR;
1810 attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN; 1926 attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN;
1927 attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK;
1811 pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n", 1928 pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
1812 id, (u64)attr.sample_type); 1929 id, (u64)attr.sample_type);
1813 err = intel_pt_synth_event(session, &attr, id); 1930 err = intel_pt_synth_event(session, &attr, id);
@@ -1852,6 +1969,16 @@ static bool intel_pt_find_switch(struct perf_evlist *evlist)
1852 return false; 1969 return false;
1853} 1970}
1854 1971
1972static int intel_pt_perf_config(const char *var, const char *value, void *data)
1973{
1974 struct intel_pt *pt = data;
1975
1976 if (!strcmp(var, "intel-pt.mispred-all"))
1977 pt->mispred_all = perf_config_bool(var, value);
1978
1979 return 0;
1980}
1981
1855static const char * const intel_pt_info_fmts[] = { 1982static const char * const intel_pt_info_fmts[] = {
1856 [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", 1983 [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n",
1857 [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", 1984 [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n",
@@ -1896,6 +2023,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
1896 if (!pt) 2023 if (!pt)
1897 return -ENOMEM; 2024 return -ENOMEM;
1898 2025
2026 perf_config(intel_pt_perf_config, pt);
2027
1899 err = auxtrace_queues__init(&pt->queues); 2028 err = auxtrace_queues__init(&pt->queues);
1900 if (err) 2029 if (err)
1901 goto err_free; 2030 goto err_free;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 61c2bc20926d..5ffb356cbcc6 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -27,6 +27,8 @@
27extern int parse_events_debug; 27extern int parse_events_debug;
28#endif 28#endif
29int parse_events_parse(void *data, void *scanner); 29int parse_events_parse(void *data, void *scanner);
30static int get_config_terms(struct list_head *head_config,
31 struct list_head *head_terms __maybe_unused);
30 32
31static struct perf_pmu_event_symbol *perf_pmu_events_list; 33static struct perf_pmu_event_symbol *perf_pmu_events_list;
32/* 34/*
@@ -416,7 +418,8 @@ static void tracepoint_error(struct parse_events_error *error, int err,
416 418
417static int add_tracepoint(struct list_head *list, int *idx, 419static int add_tracepoint(struct list_head *list, int *idx,
418 char *sys_name, char *evt_name, 420 char *sys_name, char *evt_name,
419 struct parse_events_error *error __maybe_unused) 421 struct parse_events_error *error __maybe_unused,
422 struct list_head *head_config)
420{ 423{
421 struct perf_evsel *evsel; 424 struct perf_evsel *evsel;
422 425
@@ -426,13 +429,22 @@ static int add_tracepoint(struct list_head *list, int *idx,
426 return PTR_ERR(evsel); 429 return PTR_ERR(evsel);
427 } 430 }
428 431
432 if (head_config) {
433 LIST_HEAD(config_terms);
434
435 if (get_config_terms(head_config, &config_terms))
436 return -ENOMEM;
437 list_splice(&config_terms, &evsel->config_terms);
438 }
439
429 list_add_tail(&evsel->node, list); 440 list_add_tail(&evsel->node, list);
430 return 0; 441 return 0;
431} 442}
432 443
433static int add_tracepoint_multi_event(struct list_head *list, int *idx, 444static int add_tracepoint_multi_event(struct list_head *list, int *idx,
434 char *sys_name, char *evt_name, 445 char *sys_name, char *evt_name,
435 struct parse_events_error *error) 446 struct parse_events_error *error,
447 struct list_head *head_config)
436{ 448{
437 char evt_path[MAXPATHLEN]; 449 char evt_path[MAXPATHLEN];
438 struct dirent *evt_ent; 450 struct dirent *evt_ent;
@@ -456,7 +468,8 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
456 if (!strglobmatch(evt_ent->d_name, evt_name)) 468 if (!strglobmatch(evt_ent->d_name, evt_name))
457 continue; 469 continue;
458 470
459 ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, error); 471 ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name,
472 error, head_config);
460 } 473 }
461 474
462 closedir(evt_dir); 475 closedir(evt_dir);
@@ -465,16 +478,20 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
465 478
466static int add_tracepoint_event(struct list_head *list, int *idx, 479static int add_tracepoint_event(struct list_head *list, int *idx,
467 char *sys_name, char *evt_name, 480 char *sys_name, char *evt_name,
468 struct parse_events_error *error) 481 struct parse_events_error *error,
482 struct list_head *head_config)
469{ 483{
470 return strpbrk(evt_name, "*?") ? 484 return strpbrk(evt_name, "*?") ?
471 add_tracepoint_multi_event(list, idx, sys_name, evt_name, error) : 485 add_tracepoint_multi_event(list, idx, sys_name, evt_name,
472 add_tracepoint(list, idx, sys_name, evt_name, error); 486 error, head_config) :
487 add_tracepoint(list, idx, sys_name, evt_name,
488 error, head_config);
473} 489}
474 490
475static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 491static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
476 char *sys_name, char *evt_name, 492 char *sys_name, char *evt_name,
477 struct parse_events_error *error) 493 struct parse_events_error *error,
494 struct list_head *head_config)
478{ 495{
479 struct dirent *events_ent; 496 struct dirent *events_ent;
480 DIR *events_dir; 497 DIR *events_dir;
@@ -498,23 +515,13 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
498 continue; 515 continue;
499 516
500 ret = add_tracepoint_event(list, idx, events_ent->d_name, 517 ret = add_tracepoint_event(list, idx, events_ent->d_name,
501 evt_name, error); 518 evt_name, error, head_config);
502 } 519 }
503 520
504 closedir(events_dir); 521 closedir(events_dir);
505 return ret; 522 return ret;
506} 523}
507 524
508int parse_events_add_tracepoint(struct list_head *list, int *idx,
509 char *sys, char *event,
510 struct parse_events_error *error)
511{
512 if (strpbrk(sys, "*?"))
513 return add_tracepoint_multi_sys(list, idx, sys, event, error);
514 else
515 return add_tracepoint_event(list, idx, sys, event, error);
516}
517
518static int 525static int
519parse_breakpoint_type(const char *type, struct perf_event_attr *attr) 526parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
520{ 527{
@@ -599,9 +606,13 @@ static int check_type_val(struct parse_events_term *term,
599 return -EINVAL; 606 return -EINVAL;
600} 607}
601 608
602static int config_term(struct perf_event_attr *attr, 609typedef int config_term_func_t(struct perf_event_attr *attr,
603 struct parse_events_term *term, 610 struct parse_events_term *term,
604 struct parse_events_error *err) 611 struct parse_events_error *err);
612
613static int config_term_common(struct perf_event_attr *attr,
614 struct parse_events_term *term,
615 struct parse_events_error *err)
605{ 616{
606#define CHECK_TYPE_VAL(type) \ 617#define CHECK_TYPE_VAL(type) \
607do { \ 618do { \
@@ -610,12 +621,6 @@ do { \
610} while (0) 621} while (0)
611 622
612 switch (term->type_term) { 623 switch (term->type_term) {
613 case PARSE_EVENTS__TERM_TYPE_USER:
614 /*
615 * Always succeed for sysfs terms, as we dont know
616 * at this point what type they need to have.
617 */
618 return 0;
619 case PARSE_EVENTS__TERM_TYPE_CONFIG: 624 case PARSE_EVENTS__TERM_TYPE_CONFIG:
620 CHECK_TYPE_VAL(NUM); 625 CHECK_TYPE_VAL(NUM);
621 attr->config = term->val.num; 626 attr->config = term->val.num;
@@ -658,6 +663,9 @@ do { \
658 CHECK_TYPE_VAL(STR); 663 CHECK_TYPE_VAL(STR);
659 break; 664 break;
660 default: 665 default:
666 err->str = strdup("unknown term");
667 err->idx = term->err_term;
668 err->help = parse_events_formats_error_string(NULL);
661 return -EINVAL; 669 return -EINVAL;
662 } 670 }
663 671
@@ -665,9 +673,44 @@ do { \
665#undef CHECK_TYPE_VAL 673#undef CHECK_TYPE_VAL
666} 674}
667 675
676static int config_term_pmu(struct perf_event_attr *attr,
677 struct parse_events_term *term,
678 struct parse_events_error *err)
679{
680 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER)
681 /*
682 * Always succeed for sysfs terms, as we dont know
683 * at this point what type they need to have.
684 */
685 return 0;
686 else
687 return config_term_common(attr, term, err);
688}
689
690static int config_term_tracepoint(struct perf_event_attr *attr,
691 struct parse_events_term *term,
692 struct parse_events_error *err)
693{
694 switch (term->type_term) {
695 case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
696 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
697 return config_term_common(attr, term, err);
698 default:
699 if (err) {
700 err->idx = term->err_term;
701 err->str = strdup("unknown term");
702 err->help = strdup("valid terms: call-graph,stack-size\n");
703 }
704 return -EINVAL;
705 }
706
707 return 0;
708}
709
668static int config_attr(struct perf_event_attr *attr, 710static int config_attr(struct perf_event_attr *attr,
669 struct list_head *head, 711 struct list_head *head,
670 struct parse_events_error *err) 712 struct parse_events_error *err,
713 config_term_func_t config_term)
671{ 714{
672 struct parse_events_term *term; 715 struct parse_events_term *term;
673 716
@@ -722,6 +765,27 @@ do { \
722 return 0; 765 return 0;
723} 766}
724 767
768int parse_events_add_tracepoint(struct list_head *list, int *idx,
769 char *sys, char *event,
770 struct parse_events_error *error,
771 struct list_head *head_config)
772{
773 if (head_config) {
774 struct perf_event_attr attr;
775
776 if (config_attr(&attr, head_config, error,
777 config_term_tracepoint))
778 return -EINVAL;
779 }
780
781 if (strpbrk(sys, "*?"))
782 return add_tracepoint_multi_sys(list, idx, sys, event,
783 error, head_config);
784 else
785 return add_tracepoint_event(list, idx, sys, event,
786 error, head_config);
787}
788
725int parse_events_add_numeric(struct parse_events_evlist *data, 789int parse_events_add_numeric(struct parse_events_evlist *data,
726 struct list_head *list, 790 struct list_head *list,
727 u32 type, u64 config, 791 u32 type, u64 config,
@@ -735,7 +799,8 @@ int parse_events_add_numeric(struct parse_events_evlist *data,
735 attr.config = config; 799 attr.config = config;
736 800
737 if (head_config) { 801 if (head_config) {
738 if (config_attr(&attr, head_config, data->error)) 802 if (config_attr(&attr, head_config, data->error,
803 config_term_common))
739 return -EINVAL; 804 return -EINVAL;
740 805
741 if (get_config_terms(head_config, &config_terms)) 806 if (get_config_terms(head_config, &config_terms))
@@ -795,7 +860,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
795 * Configure hardcoded terms first, no need to check 860 * Configure hardcoded terms first, no need to check
796 * return value when called with fail == 0 ;) 861 * return value when called with fail == 0 ;)
797 */ 862 */
798 if (config_attr(&attr, head_config, data->error)) 863 if (config_attr(&attr, head_config, data->error, config_term_pmu))
799 return -EINVAL; 864 return -EINVAL;
800 865
801 if (get_config_terms(head_config, &config_terms)) 866 if (get_config_terms(head_config, &config_terms))
@@ -1861,3 +1926,29 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
1861 err->str = strdup(str); 1926 err->str = strdup(str);
1862 WARN_ONCE(!err->str, "WARNING: failed to allocate error string"); 1927 WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
1863} 1928}
1929
1930/*
1931 * Return string contains valid config terms of an event.
1932 * @additional_terms: For terms such as PMU sysfs terms.
1933 */
1934char *parse_events_formats_error_string(char *additional_terms)
1935{
1936 char *str;
1937 static const char *static_terms = "config,config1,config2,name,"
1938 "period,freq,branch_type,time,"
1939 "call-graph,stack-size\n";
1940
1941 /* valid terms */
1942 if (additional_terms) {
1943 if (!asprintf(&str, "valid terms: %s,%s",
1944 additional_terms, static_terms))
1945 goto fail;
1946 } else {
1947 if (!asprintf(&str, "valid terms: %s", static_terms))
1948 goto fail;
1949 }
1950 return str;
1951
1952fail:
1953 return NULL;
1954}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ffee7ece75a6..f13d3ccda444 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -119,7 +119,8 @@ int parse_events__modifier_group(struct list_head *list, char *event_mod);
119int parse_events_name(struct list_head *list, char *name); 119int parse_events_name(struct list_head *list, char *name);
120int parse_events_add_tracepoint(struct list_head *list, int *idx, 120int parse_events_add_tracepoint(struct list_head *list, int *idx,
121 char *sys, char *event, 121 char *sys, char *event,
122 struct parse_events_error *error); 122 struct parse_events_error *error,
123 struct list_head *head_config);
123int parse_events_add_numeric(struct parse_events_evlist *data, 124int parse_events_add_numeric(struct parse_events_evlist *data,
124 struct list_head *list, 125 struct list_head *list,
125 u32 type, u64 config, 126 u32 type, u64 config,
@@ -156,5 +157,6 @@ int print_hwcache_events(const char *event_glob, bool name_only);
156extern int is_valid_tracepoint(const char *event_string); 157extern int is_valid_tracepoint(const char *event_string);
157 158
158int valid_event_mount(const char *eventfs); 159int valid_event_mount(const char *eventfs);
160char *parse_events_formats_error_string(char *additional_terms);
159 161
160#endif /* __PERF_PARSE_EVENTS_H */ 162#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 936d566f48d8..c29832bce496 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -174,7 +174,7 @@ modifier_bp [rwx]{1,3}
174 174
175<config>{ 175<config>{
176 /* 176 /*
177 * Please update formats_error_string any time 177 * Please update parse_events_formats_error_string any time
178 * new static term is added. 178 * new static term is added.
179 */ 179 */
180config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } 180config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 8bcc45868457..ae6af269f9c9 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -67,6 +67,7 @@ static inc_group_count(struct list_head *list,
67%type <head> event_legacy_cache 67%type <head> event_legacy_cache
68%type <head> event_legacy_mem 68%type <head> event_legacy_mem
69%type <head> event_legacy_tracepoint 69%type <head> event_legacy_tracepoint
70%type <tracepoint_name> tracepoint_name
70%type <head> event_legacy_numeric 71%type <head> event_legacy_numeric
71%type <head> event_legacy_raw 72%type <head> event_legacy_raw
72%type <head> event_def 73%type <head> event_def
@@ -84,6 +85,10 @@ static inc_group_count(struct list_head *list,
84 u64 num; 85 u64 num;
85 struct list_head *head; 86 struct list_head *head;
86 struct parse_events_term *term; 87 struct parse_events_term *term;
88 struct tracepoint_name {
89 char *sys;
90 char *event;
91 } tracepoint_name;
87} 92}
88%% 93%%
89 94
@@ -368,38 +373,60 @@ PE_PREFIX_MEM PE_VALUE sep_dc
368} 373}
369 374
370event_legacy_tracepoint: 375event_legacy_tracepoint:
371PE_NAME '-' PE_NAME ':' PE_NAME 376tracepoint_name
372{ 377{
373 struct parse_events_evlist *data = _data; 378 struct parse_events_evlist *data = _data;
374 struct parse_events_error *error = data->error; 379 struct parse_events_error *error = data->error;
375 struct list_head *list; 380 struct list_head *list;
376 char sys_name[128];
377 snprintf(&sys_name, 128, "%s-%s", $1, $3);
378 381
379 ALLOC_LIST(list); 382 ALLOC_LIST(list);
380 if (parse_events_add_tracepoint(list, &data->idx, &sys_name, $5, error)) { 383 if (error)
381 if (error) 384 error->idx = @1.first_column;
382 error->idx = @1.first_column; 385
386 if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
387 error, NULL))
383 return -1; 388 return -1;
384 } 389
385 $$ = list; 390 $$ = list;
386} 391}
387| 392|
388PE_NAME ':' PE_NAME 393tracepoint_name '/' event_config '/'
389{ 394{
390 struct parse_events_evlist *data = _data; 395 struct parse_events_evlist *data = _data;
391 struct parse_events_error *error = data->error; 396 struct parse_events_error *error = data->error;
392 struct list_head *list; 397 struct list_head *list;
393 398
394 ALLOC_LIST(list); 399 ALLOC_LIST(list);
395 if (parse_events_add_tracepoint(list, &data->idx, $1, $3, error)) { 400 if (error)
396 if (error) 401 error->idx = @1.first_column;
397 error->idx = @1.first_column; 402
403 if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
404 error, $3))
398 return -1; 405 return -1;
399 } 406
400 $$ = list; 407 $$ = list;
401} 408}
402 409
410tracepoint_name:
411PE_NAME '-' PE_NAME ':' PE_NAME
412{
413 char sys_name[128];
414 struct tracepoint_name tracepoint;
415
416 snprintf(&sys_name, 128, "%s-%s", $1, $3);
417 tracepoint.sys = &sys_name;
418 tracepoint.event = $5;
419
420 $$ = tracepoint;
421}
422|
423PE_NAME ':' PE_NAME
424{
425 struct tracepoint_name tracepoint = {$1, $3};
426
427 $$ = tracepoint;
428}
429
403event_legacy_numeric: 430event_legacy_numeric:
404PE_VALUE ':' PE_VALUE 431PE_VALUE ':' PE_VALUE
405{ 432{
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 89c91a1a67e7..ac42c97be9e4 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -626,38 +626,26 @@ static int pmu_resolve_param_term(struct parse_events_term *term,
626 return -1; 626 return -1;
627} 627}
628 628
629static char *formats_error_string(struct list_head *formats) 629static char *pmu_formats_string(struct list_head *formats)
630{ 630{
631 struct perf_pmu_format *format; 631 struct perf_pmu_format *format;
632 char *err, *str; 632 char *str;
633 static const char *static_terms = "config,config1,config2,name," 633 struct strbuf buf;
634 "period,freq,branch_type,time,"
635 "call-graph,stack-size\n";
636 unsigned i = 0; 634 unsigned i = 0;
637 635
638 if (!asprintf(&str, "valid terms:")) 636 if (!formats)
639 return NULL; 637 return NULL;
640 638
639 strbuf_init(&buf, 0);
641 /* sysfs exported terms */ 640 /* sysfs exported terms */
642 list_for_each_entry(format, formats, list) { 641 list_for_each_entry(format, formats, list)
643 char c = i++ ? ',' : ' '; 642 strbuf_addf(&buf, i++ ? ",%s" : "%s",
644 643 format->name);
645 err = str;
646 if (!asprintf(&str, "%s%c%s", err, c, format->name))
647 goto fail;
648 free(err);
649 }
650 644
651 /* static terms */ 645 str = strbuf_detach(&buf, NULL);
652 err = str; 646 strbuf_release(&buf);
653 if (!asprintf(&str, "%s,%s", err, static_terms))
654 goto fail;
655 647
656 free(err);
657 return str; 648 return str;
658fail:
659 free(err);
660 return NULL;
661} 649}
662 650
663/* 651/*
@@ -693,9 +681,12 @@ static int pmu_config_term(struct list_head *formats,
693 if (verbose) 681 if (verbose)
694 printf("Invalid event/parameter '%s'\n", term->config); 682 printf("Invalid event/parameter '%s'\n", term->config);
695 if (err) { 683 if (err) {
684 char *pmu_term = pmu_formats_string(formats);
685
696 err->idx = term->err_term; 686 err->idx = term->err_term;
697 err->str = strdup("unknown term"); 687 err->str = strdup("unknown term");
698 err->help = formats_error_string(formats); 688 err->help = parse_events_formats_error_string(pmu_term);
689 free(pmu_term);
699 } 690 }
700 return -EINVAL; 691 return -EINVAL;
701 } 692 }
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index aa9e1257c1ee..a8e825fca42a 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -319,7 +319,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
319 319
320 if (thread__resolve_callchain(al->thread, evsel, 320 if (thread__resolve_callchain(al->thread, evsel,
321 sample, NULL, NULL, 321 sample, NULL, NULL,
322 PERF_MAX_STACK_DEPTH) != 0) { 322 scripting_max_stack) != 0) {
323 pr_err("Failed to resolve callchain. Skipping\n"); 323 pr_err("Failed to resolve callchain. Skipping\n");
324 goto exit; 324 goto exit;
325 } 325 }
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f5e000030a5e..84a02eae4394 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1101,6 +1101,9 @@ static int machines__deliver_event(struct machines *machines,
1101 case PERF_RECORD_UNTHROTTLE: 1101 case PERF_RECORD_UNTHROTTLE:
1102 return tool->unthrottle(tool, event, sample, machine); 1102 return tool->unthrottle(tool, event, sample, machine);
1103 case PERF_RECORD_AUX: 1103 case PERF_RECORD_AUX:
1104 if (tool->aux == perf_event__process_aux &&
1105 (event->aux.flags & PERF_AUX_FLAG_TRUNCATED))
1106 evlist->stats.total_aux_lost += 1;
1104 return tool->aux(tool, event, sample, machine); 1107 return tool->aux(tool, event, sample, machine);
1105 case PERF_RECORD_ITRACE_START: 1108 case PERF_RECORD_ITRACE_START:
1106 return tool->itrace_start(tool, event, sample, machine); 1109 return tool->itrace_start(tool, event, sample, machine);
@@ -1346,6 +1349,13 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1346 } 1349 }
1347 } 1350 }
1348 1351
1352 if (session->tool->aux == perf_event__process_aux &&
1353 stats->total_aux_lost != 0) {
1354 ui__warning("AUX data lost %" PRIu64 " times out of %u!\n\n",
1355 stats->total_aux_lost,
1356 stats->nr_events[PERF_RECORD_AUX]);
1357 }
1358
1349 if (stats->nr_unknown_events != 0) { 1359 if (stats->nr_unknown_events != 0) {
1350 ui__warning("Found %u unknown events!\n\n" 1360 ui__warning("Found %u unknown events!\n\n"
1351 "Is this an older tool processing a perf.data " 1361 "Is this an older tool processing a perf.data "
@@ -1790,7 +1800,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1790 1800
1791 if (thread__resolve_callchain(al->thread, evsel, 1801 if (thread__resolve_callchain(al->thread, evsel,
1792 sample, NULL, NULL, 1802 sample, NULL, NULL,
1793 PERF_MAX_STACK_DEPTH) != 0) { 1803 stack_depth) != 0) {
1794 if (verbose) 1804 if (verbose)
1795 error("Failed to resolve callchain. Skipping\n"); 1805 error("Failed to resolve callchain. Skipping\n");
1796 return; 1806 return;
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index da6cc4cc2a4f..b85ee55cca0c 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -78,6 +78,8 @@ struct scripting_ops {
78 int (*generate_script) (struct pevent *pevent, const char *outfile); 78 int (*generate_script) (struct pevent *pevent, const char *outfile);
79}; 79};
80 80
81extern unsigned int scripting_max_stack;
82
81int script_spec_register(const char *spec, struct scripting_ops *ops); 83int script_spec_register(const char *spec, struct scripting_ops *ops);
82 84
83void setup_perl_scripting(void); 85void setup_perl_scripting(void);