aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-11-15 03:45:04 -0500
committerIngo Molnar <mingo@kernel.org>2016-11-15 03:45:04 -0500
commit6a6b12e2125591e24891e6860410795ea53aed11 (patch)
tree9c186d798b75b708f663cbd286d0b842768fb873 /tools
parent91a79e5fa696fa626bfbd47f827eaf3eb7d76dc5 (diff)
parentfef51ecd1056b5e090c9fb73e0833bd751389572 (diff)
Merge tag 'perf-core-for-mingo-20161114' 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: New features: - Allow querying and setting .perfconfig variables (Taeung Song) - Show branch information in callchains (predicted, TSX aborts, loop iteractions, etc) (Jin Yao) Infrastructure changes: - Support kbuild's CFLAGS_REMOVE_ in tools/build (Jiri Olsa) - Plug building jvmti to the main perf Makefile (Jiri Olsa) Documentation changes: - Update Intel PT documentation about context switch events (Arnaldo Carvalho de Melo) - Fix 'perf record --call-graph dwarf' help/config in builds not linking with a unwind library, mentioning that is a possible record option (Rabin Vincent) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/build/Build.include4
-rw-r--r--tools/build/Documentation/Build.txt6
-rw-r--r--tools/build/feature/Makefile6
-rw-r--r--tools/build/feature/test-jvmti.c13
-rw-r--r--tools/perf/Documentation/intel-pt.txt19
-rw-r--r--tools/perf/Documentation/perf-config.txt35
-rw-r--r--tools/perf/Makefile.config26
-rw-r--r--tools/perf/Makefile.perf24
-rw-r--r--tools/perf/builtin-config.c137
-rw-r--r--tools/perf/builtin-report.c3
-rw-r--r--tools/perf/jvmti/Build8
-rw-r--r--tools/perf/jvmti/Makefile89
-rw-r--r--tools/perf/tests/make2
-rw-r--r--tools/perf/ui/browsers/hists.c20
-rw-r--r--tools/perf/ui/stdio/hist.c35
-rw-r--r--tools/perf/util/callchain.c205
-rw-r--r--tools/perf/util/callchain.h26
-rw-r--r--tools/perf/util/config.c20
-rw-r--r--tools/perf/util/config.h4
-rw-r--r--tools/perf/util/machine.c82
-rw-r--r--tools/perf/util/symbol.h1
21 files changed, 634 insertions, 131 deletions
diff --git a/tools/build/Build.include b/tools/build/Build.include
index 1dcb95e76f70..c4ae12a5d0a5 100644
--- a/tools/build/Build.include
+++ b/tools/build/Build.include
@@ -89,7 +89,9 @@ if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
89# - per target C flags 89# - per target C flags
90# - per object C flags 90# - per object C flags
91# - BUILD_STR macro to allow '-D"$(variable)"' constructs 91# - BUILD_STR macro to allow '-D"$(variable)"' constructs
92c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj)) 92c_flags_1 = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
93c_flags_2 = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(c_flags_1))
94c_flags = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2))
93cxx_flags = -Wp,-MD,$(depfile),-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj)) 95cxx_flags = -Wp,-MD,$(depfile),-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj))
94 96
95### 97###
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
index a47bffbae159..a22587475dbe 100644
--- a/tools/build/Documentation/Build.txt
+++ b/tools/build/Documentation/Build.txt
@@ -135,8 +135,10 @@ CFLAGS
135 135
136It'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:
137 137
138 CFLAGS_perf.o += '...' - alters CFLAGS for perf.o object 138 CFLAGS_perf.o += '...' - adds CFLAGS for perf.o object
139 CFLAGS_gtk += '...' - alters CFLAGS for gtk build object 139 CFLAGS_gtk += '...' - adds CFLAGS for gtk build object
140 CFLAGS_REMOVE_perf.o += '...' - removes CFLAGS for perf.o object
141 CFLAGS_REMOVE_gtk += '...' - removes CFLAGS for gtk build object
140 142
141This C flags changes has the scope of the Build makefile they are defined in. 143This C flags changes has the scope of the Build makefile they are defined in.
142 144
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index ac9c477a2a48..8f668bce8996 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -47,7 +47,8 @@ FILES= \
47 test-bpf.bin \ 47 test-bpf.bin \
48 test-get_cpuid.bin \ 48 test-get_cpuid.bin \
49 test-sdt.bin \ 49 test-sdt.bin \
50 test-cxx.bin 50 test-cxx.bin \
51 test-jvmti.bin
51 52
52FILES := $(addprefix $(OUTPUT),$(FILES)) 53FILES := $(addprefix $(OUTPUT),$(FILES))
53 54
@@ -225,6 +226,9 @@ $(OUTPUT)test-sdt.bin:
225$(OUTPUT)test-cxx.bin: 226$(OUTPUT)test-cxx.bin:
226 $(BUILDXX) -std=gnu++11 227 $(BUILDXX) -std=gnu++11
227 228
229$(OUTPUT)test-jvmti.bin:
230 $(BUILD)
231
228-include $(OUTPUT)*.d 232-include $(OUTPUT)*.d
229 233
230############################### 234###############################
diff --git a/tools/build/feature/test-jvmti.c b/tools/build/feature/test-jvmti.c
new file mode 100644
index 000000000000..1c665f09b9d6
--- /dev/null
+++ b/tools/build/feature/test-jvmti.c
@@ -0,0 +1,13 @@
1#include <jvmti.h>
2#include <jvmticmlr.h>
3
4int main(void)
5{
6 JavaVM jvm __attribute__((unused));
7 jvmtiEventCallbacks cb __attribute__((unused));
8 jvmtiCapabilities caps __attribute__((unused));
9 jvmtiJlocationFormat format __attribute__((unused));
10 jvmtiEnv jvmti __attribute__((unused));
11
12 return 0;
13}
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index c6c8318e38a2..b0b3007d3c9c 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -550,6 +550,18 @@ Unless /proc/sys/kernel/perf_event_paranoid is set to -1, unprivileged users
550have memory limits imposed upon them. That affects what buffer sizes they can 550have memory limits imposed upon them. That affects what buffer sizes they can
551have as outlined above. 551have as outlined above.
552 552
553The v4.2 kernel introduced support for a context switch metadata event,
554PERF_RECORD_SWITCH, which allows unprivileged users to see when their processes
555are scheduled out and in, just not by whom, which is left for the
556PERF_RECORD_SWITCH_CPU_WIDE, that is only accessible in system wide context,
557which in turn requires CAP_SYS_ADMIN.
558
559Please see the 45ac1403f564 ("perf: Add PERF_RECORD_SWITCH to indicate context
560switches") commit, that introduces these metadata events for further info.
561
562When working with kernels < v4.2, the following considerations must be taken,
563as the sched:sched_switch tracepoints will be used to receive such information:
564
553Unless /proc/sys/kernel/perf_event_paranoid is set to -1, unprivileged users are 565Unless /proc/sys/kernel/perf_event_paranoid is set to -1, unprivileged users are
554not permitted to use tracepoints which means there is insufficient side-band 566not permitted to use tracepoints which means there is insufficient side-band
555information to decode Intel PT in per-cpu mode, and potentially workload-only 567information to decode Intel PT in per-cpu mode, and potentially workload-only
@@ -564,8 +576,11 @@ sched_switch tracepoint
564----------------------- 576-----------------------
565 577
566The sched_switch tracepoint is used to provide side-band data for Intel PT 578The sched_switch tracepoint is used to provide side-band data for Intel PT
567decoding. sched_switch events are automatically added. e.g. the second event 579decoding in kernels where the PERF_RECORD_SWITCH metadata event isn't
568shown below 580available.
581
582The sched_switch events are automatically added. e.g. the second event shown
583below:
569 584
570 $ perf record -vv -e intel_pt//u uname 585 $ perf record -vv -e intel_pt//u uname
571 ------------------------------------------------------------ 586 ------------------------------------------------------------
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index cb081ac59fd1..9365b75fd04f 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -8,6 +8,8 @@ perf-config - Get and set variables in a configuration file.
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf config' [<file-option>] [section.name[=value] ...]
12or
11'perf config' [<file-option>] -l | --list 13'perf config' [<file-option>] -l | --list
12 14
13DESCRIPTION 15DESCRIPTION
@@ -118,6 +120,39 @@ Given a $HOME/.perfconfig like this:
118 children = true 120 children = true
119 group = true 121 group = true
120 122
123You can hide source code of annotate feature setting the config to false with
124
125 % perf config annotate.hide_src_code=true
126
127If you want to add or modify several config items, you can do like
128
129 % perf config ui.show-headers=false kmem.default=slab
130
131To modify the sort order of report functionality in user config file(i.e. `~/.perfconfig`), do
132
133 % perf config --user report sort-order=srcline
134
135To change colors of selected line to other foreground and background colors
136in system config file (i.e. `$(sysconf)/perfconfig`), do
137
138 % perf config --system colors.selected=yellow,green
139
140To query the record mode of call graph, do
141
142 % perf config call-graph.record-mode
143
144If you want to know multiple config key/value pairs, you can do like
145
146 % perf config report.queue-size call-graph.order report.children
147
148To query the config value of sort order of call graph in user config file (i.e. `~/.perfconfig`), do
149
150 % perf config --user call-graph.sort-order
151
152To query the config value of buildid directory in system config file (i.e. `$(sysconf)/perfconfig`), do
153
154 % perf config --system buildid.dir
155
121Variables 156Variables
122~~~~~~~~~ 157~~~~~~~~~
123 158
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index cffdd9cf3ebf..8a493d46fab9 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -758,6 +758,31 @@ ifndef NO_AUXTRACE
758 endif 758 endif
759endif 759endif
760 760
761ifndef NO_JVMTI
762 ifneq (,$(wildcard /usr/sbin/update-java-alternatives))
763 JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
764 else
765 ifneq (,$(wildcard /usr/sbin/alternatives))
766 JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
767 endif
768 endif
769 ifndef JDIR
770 $(warning No alternatives command found, you need to set JDIR= to point to the root of your Java directory)
771 NO_JVMTI := 1
772 endif
773endif
774
775ifndef NO_JVMTI
776 FEATURE_CHECK_CFLAGS-jvmti := -I$(JDIR)/include -I$(JDIR)/include/linux
777 $(call feature_check,jvmti)
778 ifeq ($(feature-jvmti), 1)
779 $(call detected_var,JDIR)
780 else
781 $(warning No openjdk development package found, please install JDK package)
782 NO_JVMTI := 1
783 endif
784endif
785
761# Among the variables below, these: 786# Among the variables below, these:
762# perfexecdir 787# perfexecdir
763# template_dir 788# template_dir
@@ -850,6 +875,7 @@ ifeq ($(VF),1)
850 $(call print_var,sysconfdir) 875 $(call print_var,sysconfdir)
851 $(call print_var,LIBUNWIND_DIR) 876 $(call print_var,LIBUNWIND_DIR)
852 $(call print_var,LIBDW_DIR) 877 $(call print_var,LIBDW_DIR)
878 $(call print_var,JDIR)
853 879
854 ifeq ($(dwarf-post-unwind),1) 880 ifeq ($(dwarf-post-unwind),1)
855 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text)) 881 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 7de14f470f3c..3cb1df43ad3e 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -86,6 +86,8 @@ include ../scripts/utilities.mak
86# 86#
87# Define FEATURES_DUMP to provide features detection dump file 87# Define FEATURES_DUMP to provide features detection dump file
88# and bypass the feature detection 88# and bypass the feature detection
89#
90# Define NO_JVMTI if you do not want jvmti agent built
89 91
90# As per kernel Makefile, avoid funny character set dependencies 92# As per kernel Makefile, avoid funny character set dependencies
91unexport LC_ALL 93unexport LC_ALL
@@ -283,6 +285,12 @@ ifndef NO_PERF_READ_VDSOX32
283PROGRAMS += $(OUTPUT)perf-read-vdsox32 285PROGRAMS += $(OUTPUT)perf-read-vdsox32
284endif 286endif
285 287
288LIBJVMTI = libperf-jvmti.so
289
290ifndef NO_JVMTI
291PROGRAMS += $(OUTPUT)$(LIBJVMTI)
292endif
293
286# what 'all' will build and 'install' will install, in perfexecdir 294# what 'all' will build and 'install' will install, in perfexecdir
287ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) 295ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
288 296
@@ -551,6 +559,16 @@ $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
551 $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c 559 $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
552endif 560endif
553 561
562ifndef NO_JVMTI
563LIBJVMTI_IN := $(OUTPUT)jvmti/jvmti-in.o
564
565$(LIBJVMTI_IN): FORCE
566 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti
567
568$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN)
569 $(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< -lelf -lrt
570endif
571
554$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) 572$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
555 573
556LIBPERF_IN := $(OUTPUT)libperf-in.o 574LIBPERF_IN := $(OUTPUT)libperf-in.o
@@ -688,6 +706,10 @@ ifndef NO_PERF_READ_VDSOX32
688 $(call QUIET_INSTALL, perf-read-vdsox32) \ 706 $(call QUIET_INSTALL, perf-read-vdsox32) \
689 $(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)'; 707 $(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)';
690endif 708endif
709ifndef NO_JVMTI
710 $(call QUIET_INSTALL, $(LIBJVMTI)) \
711 $(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)';
712endif
691 $(call QUIET_INSTALL, libexec) \ 713 $(call QUIET_INSTALL, libexec) \
692 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 714 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
693 $(call QUIET_INSTALL, perf-archive) \ 715 $(call QUIET_INSTALL, perf-archive) \
@@ -754,7 +776,7 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
754 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) 776 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
755 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 777 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
756 $(Q)$(RM) $(OUTPUT).config-detected 778 $(Q)$(RM) $(OUTPUT).config-detected
757 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents 779 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents $(OUTPUT)$(LIBJVMTI).so
758 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \ 780 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
759 $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \ 781 $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \
760 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ 782 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index e4207a23b52c..8c0d93b7c2f0 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -17,7 +17,7 @@
17static bool use_system_config, use_user_config; 17static bool use_system_config, use_user_config;
18 18
19static const char * const config_usage[] = { 19static const char * const config_usage[] = {
20 "perf config [<file-option>] [options]", 20 "perf config [<file-option>] [options] [section.name[=value] ...]",
21 NULL 21 NULL
22}; 22};
23 23
@@ -33,6 +33,73 @@ static struct option config_options[] = {
33 OPT_END() 33 OPT_END()
34}; 34};
35 35
36static int set_config(struct perf_config_set *set, const char *file_name,
37 const char *var, const char *value)
38{
39 struct perf_config_section *section = NULL;
40 struct perf_config_item *item = NULL;
41 const char *first_line = "# this file is auto-generated.";
42 FILE *fp;
43
44 if (set == NULL)
45 return -1;
46
47 fp = fopen(file_name, "w");
48 if (!fp)
49 return -1;
50
51 perf_config_set__collect(set, file_name, var, value);
52 fprintf(fp, "%s\n", first_line);
53
54 /* overwrite configvariables */
55 perf_config_items__for_each_entry(&set->sections, section) {
56 if (!use_system_config && section->from_system_config)
57 continue;
58 fprintf(fp, "[%s]\n", section->name);
59
60 perf_config_items__for_each_entry(&section->items, item) {
61 if (!use_system_config && section->from_system_config)
62 continue;
63 if (item->value)
64 fprintf(fp, "\t%s = %s\n",
65 item->name, item->value);
66 }
67 }
68 fclose(fp);
69
70 return 0;
71}
72
73static int show_spec_config(struct perf_config_set *set, const char *var)
74{
75 struct perf_config_section *section;
76 struct perf_config_item *item;
77
78 if (set == NULL)
79 return -1;
80
81 perf_config_items__for_each_entry(&set->sections, section) {
82 if (prefixcmp(var, section->name) != 0)
83 continue;
84
85 perf_config_items__for_each_entry(&section->items, item) {
86 const char *name = var + strlen(section->name) + 1;
87
88 if (strcmp(name, item->name) == 0) {
89 char *value = item->value;
90
91 if (value) {
92 printf("%s=%s\n", var, value);
93 return 0;
94 }
95 }
96
97 }
98 }
99
100 return 0;
101}
102
36static int show_config(struct perf_config_set *set) 103static int show_config(struct perf_config_set *set)
37{ 104{
38 struct perf_config_section *section; 105 struct perf_config_section *section;
@@ -52,9 +119,44 @@ static int show_config(struct perf_config_set *set)
52 return 0; 119 return 0;
53} 120}
54 121
122static int parse_config_arg(char *arg, char **var, char **value)
123{
124 const char *last_dot = strchr(arg, '.');
125
126 /*
127 * Since "var" actually contains the section name and the real
128 * config variable name separated by a dot, we have to know where the dot is.
129 */
130 if (last_dot == NULL || last_dot == arg) {
131 pr_err("The config variable does not contain a section name: %s\n", arg);
132 return -1;
133 }
134 if (!last_dot[1]) {
135 pr_err("The config variable does not contain a variable name: %s\n", arg);
136 return -1;
137 }
138
139 *value = strchr(arg, '=');
140 if (*value == NULL)
141 *var = arg;
142 else if (!strcmp(*value, "=")) {
143 pr_err("The config variable does not contain a value: %s\n", arg);
144 return -1;
145 } else {
146 *value = *value + 1; /* excluding a first character '=' */
147 *var = strsep(&arg, "=");
148 if (*var[0] == '\0') {
149 pr_err("invalid config variable: %s\n", arg);
150 return -1;
151 }
152 }
153
154 return 0;
155}
156
55int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) 157int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
56{ 158{
57 int ret = 0; 159 int i, ret = 0;
58 struct perf_config_set *set; 160 struct perf_config_set *set;
59 char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); 161 char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
60 162
@@ -100,7 +202,36 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
100 } 202 }
101 break; 203 break;
102 default: 204 default:
103 usage_with_options(config_usage, config_options); 205 if (argc) {
206 for (i = 0; argv[i]; i++) {
207 char *var, *value;
208 char *arg = strdup(argv[i]);
209
210 if (!arg) {
211 pr_err("%s: strdup failed\n", __func__);
212 ret = -1;
213 break;
214 }
215
216 if (parse_config_arg(arg, &var, &value) < 0) {
217 free(arg);
218 ret = -1;
219 break;
220 }
221
222 if (value == NULL)
223 ret = show_spec_config(set, var);
224 else {
225 const char *config_filename = config_exclusive_filename;
226
227 if (!config_exclusive_filename)
228 config_filename = user_config;
229 ret = set_config(set, config_filename, var, value);
230 }
231 free(arg);
232 }
233 } else
234 usage_with_options(config_usage, config_options);
104 } 235 }
105 236
106 perf_config_set__delete(set); 237 perf_config_set__delete(set);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8064de8ceedc..3dfbfffe2ecd 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -911,6 +911,9 @@ repeat:
911 if (itrace_synth_opts.last_branch) 911 if (itrace_synth_opts.last_branch)
912 has_br_stack = true; 912 has_br_stack = true;
913 913
914 if (has_br_stack && branch_call_mode)
915 symbol_conf.show_branchflag_count = true;
916
914 /* 917 /*
915 * Branch mode is a tristate: 918 * Branch mode is a tristate:
916 * -1 means default, so decide based on the file having branch data. 919 * -1 means default, so decide based on the file having branch data.
diff --git a/tools/perf/jvmti/Build b/tools/perf/jvmti/Build
new file mode 100644
index 000000000000..eaeb8cb5379b
--- /dev/null
+++ b/tools/perf/jvmti/Build
@@ -0,0 +1,8 @@
1jvmti-y += libjvmti.o
2jvmti-y += jvmti_agent.o
3
4CFLAGS_jvmti = -fPIC -DPIC -I$(JDIR)/include -I$(JDIR)/include/linux
5CFLAGS_REMOVE_jvmti = -Wmissing-declarations
6CFLAGS_REMOVE_jvmti += -Wstrict-prototypes
7CFLAGS_REMOVE_jvmti += -Wextra
8CFLAGS_REMOVE_jvmti += -Wwrite-strings
diff --git a/tools/perf/jvmti/Makefile b/tools/perf/jvmti/Makefile
deleted file mode 100644
index df14e6b67b63..000000000000
--- a/tools/perf/jvmti/Makefile
+++ /dev/null
@@ -1,89 +0,0 @@
1ARCH=$(shell uname -m)
2
3ifeq ($(ARCH), x86_64)
4JARCH=amd64
5endif
6ifeq ($(ARCH), armv7l)
7JARCH=armhf
8endif
9ifeq ($(ARCH), armv6l)
10JARCH=armhf
11endif
12ifeq ($(ARCH), aarch64)
13JARCH=aarch64
14endif
15ifeq ($(ARCH), ppc64)
16JARCH=powerpc
17endif
18ifeq ($(ARCH), ppc64le)
19JARCH=powerpc
20endif
21
22DESTDIR=/usr/local
23
24VERSION=1
25REVISION=0
26AGE=0
27
28LN=ln -sf
29RM=rm
30
31SLIBJVMTI=libjvmti.so.$(VERSION).$(REVISION).$(AGE)
32VLIBJVMTI=libjvmti.so.$(VERSION)
33SLDFLAGS=-shared -Wl,-soname -Wl,$(VLIBJVMTI)
34SOLIBEXT=so
35
36# The following works at least on fedora 23, you may need the next
37# line for other distros.
38ifneq (,$(wildcard /usr/sbin/update-java-alternatives))
39JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
40else
41 ifneq (,$(wildcard /usr/sbin/alternatives))
42 JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
43 endif
44endif
45ifndef JDIR
46$(error Could not find alternatives command, you need to set JDIR= to point to the root of your Java directory)
47else
48 ifeq (,$(wildcard $(JDIR)/include/jvmti.h))
49 $(error the openjdk development package appears to me missing, install and try again)
50 endif
51endif
52$(info Using Java from $(JDIR))
53# -lrt required in 32-bit mode for clock_gettime()
54LIBS=-lelf -lrt
55INCDIR=-I $(JDIR)/include -I $(JDIR)/include/linux
56
57TARGETS=$(SLIBJVMTI)
58
59SRCS=libjvmti.c jvmti_agent.c
60OBJS=$(SRCS:.c=.o)
61SOBJS=$(OBJS:.o=.lo)
62OPT=-O2 -g -Werror -Wall
63
64CFLAGS=$(INCDIR) $(OPT)
65
66all: $(TARGETS)
67
68.c.o:
69 $(CC) $(CFLAGS) -c $*.c
70.c.lo:
71 $(CC) -fPIC -DPIC $(CFLAGS) -c $*.c -o $*.lo
72
73$(OBJS) $(SOBJS): Makefile jvmti_agent.h ../util/jitdump.h
74
75$(SLIBJVMTI): $(SOBJS)
76 $(CC) $(CFLAGS) $(SLDFLAGS) -o $@ $(SOBJS) $(LIBS)
77 $(LN) $@ libjvmti.$(SOLIBEXT)
78
79clean:
80 $(RM) -f *.o *.so.* *.so *.lo
81
82install:
83 -mkdir -p $(DESTDIR)/lib
84 install -m 755 $(SLIBJVMTI) $(DESTDIR)/lib/
85 (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) $(VLIBJVMTI))
86 (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) libjvmti.$(SOLIBEXT))
87 ldconfig
88
89.SUFFIXES: .c .S .o .lo
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 143f4d549769..08ed7f12cc37 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -106,7 +106,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
106make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 106make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
107make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 107make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
108make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 108make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
109make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 109make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1
110 110
111# $(run) contains all available tests 111# $(run) contains all available tests
112run := make_pure 112run := make_pure
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 84f5dd2fb59c..66676cb8effe 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -738,6 +738,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
738 struct callchain_print_arg *arg) 738 struct callchain_print_arg *arg)
739{ 739{
740 char bf[1024], *alloc_str; 740 char bf[1024], *alloc_str;
741 char buf[64], *alloc_str2;
741 const char *str; 742 const char *str;
742 743
743 if (arg->row_offset != 0) { 744 if (arg->row_offset != 0) {
@@ -746,12 +747,26 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
746 } 747 }
747 748
748 alloc_str = NULL; 749 alloc_str = NULL;
750 alloc_str2 = NULL;
751
749 str = callchain_list__sym_name(chain, bf, sizeof(bf), 752 str = callchain_list__sym_name(chain, bf, sizeof(bf),
750 browser->show_dso); 753 browser->show_dso);
751 754
752 if (need_percent) { 755 if (symbol_conf.show_branchflag_count) {
753 char buf[64]; 756 if (need_percent)
757 callchain_list_counts__printf_value(node, chain, NULL,
758 buf, sizeof(buf));
759 else
760 callchain_list_counts__printf_value(NULL, chain, NULL,
761 buf, sizeof(buf));
762
763 if (asprintf(&alloc_str2, "%s%s", str, buf) < 0)
764 str = "Not enough memory!";
765 else
766 str = alloc_str2;
767 }
754 768
769 if (need_percent) {
755 callchain_node__scnprintf_value(node, buf, sizeof(buf), 770 callchain_node__scnprintf_value(node, buf, sizeof(buf),
756 total); 771 total);
757 772
@@ -764,6 +779,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
764 print(browser, chain, str, offset, row, arg); 779 print(browser, chain, str, offset, row, arg);
765 780
766 free(alloc_str); 781 free(alloc_str);
782 free(alloc_str2);
767 return 1; 783 return 1;
768} 784}
769 785
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 89d8441f9890..668f4aecf2e6 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -41,7 +41,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
41{ 41{
42 int i; 42 int i;
43 size_t ret = 0; 43 size_t ret = 0;
44 char bf[1024]; 44 char bf[1024], *alloc_str = NULL;
45 char buf[64];
46 const char *str;
45 47
46 ret += callchain__fprintf_left_margin(fp, left_margin); 48 ret += callchain__fprintf_left_margin(fp, left_margin);
47 for (i = 0; i < depth; i++) { 49 for (i = 0; i < depth; i++) {
@@ -56,8 +58,26 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
56 } else 58 } else
57 ret += fprintf(fp, "%s", " "); 59 ret += fprintf(fp, "%s", " ");
58 } 60 }
59 fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp); 61
62 str = callchain_list__sym_name(chain, bf, sizeof(bf), false);
63
64 if (symbol_conf.show_branchflag_count) {
65 if (!period)
66 callchain_list_counts__printf_value(node, chain, NULL,
67 buf, sizeof(buf));
68 else
69 callchain_list_counts__printf_value(NULL, chain, NULL,
70 buf, sizeof(buf));
71
72 if (asprintf(&alloc_str, "%s%s", str, buf) < 0)
73 str = "Not enough memory!";
74 else
75 str = alloc_str;
76 }
77
78 fputs(str, fp);
60 fputc('\n', fp); 79 fputc('\n', fp);
80 free(alloc_str);
61 return ret; 81 return ret;
62} 82}
63 83
@@ -219,8 +239,15 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
219 } else 239 } else
220 ret += callchain__fprintf_left_margin(fp, left_margin); 240 ret += callchain__fprintf_left_margin(fp, left_margin);
221 241
222 ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf), 242 ret += fprintf(fp, "%s",
223 false)); 243 callchain_list__sym_name(chain, bf,
244 sizeof(bf),
245 false));
246
247 if (symbol_conf.show_branchflag_count)
248 ret += callchain_list_counts__printf_value(
249 NULL, chain, fp, NULL, 0);
250 ret += fprintf(fp, "\n");
224 251
225 if (++entries_printed == callchain_param.print_limit) 252 if (++entries_printed == callchain_param.print_limit)
226 break; 253 break;
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 07fd30bc2f81..823befd8209a 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -193,7 +193,6 @@ int perf_callchain_config(const char *var, const char *value)
193 193
194 if (!strcmp(var, "record-mode")) 194 if (!strcmp(var, "record-mode"))
195 return parse_callchain_record_opt(value, &callchain_param); 195 return parse_callchain_record_opt(value, &callchain_param);
196#ifdef HAVE_DWARF_UNWIND_SUPPORT
197 if (!strcmp(var, "dump-size")) { 196 if (!strcmp(var, "dump-size")) {
198 unsigned long size = 0; 197 unsigned long size = 0;
199 int ret; 198 int ret;
@@ -203,7 +202,6 @@ int perf_callchain_config(const char *var, const char *value)
203 202
204 return ret; 203 return ret;
205 } 204 }
206#endif
207 if (!strcmp(var, "print-type")) 205 if (!strcmp(var, "print-type"))
208 return parse_callchain_mode(value); 206 return parse_callchain_mode(value);
209 if (!strcmp(var, "order")) 207 if (!strcmp(var, "order"))
@@ -440,6 +438,21 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
440 call->ip = cursor_node->ip; 438 call->ip = cursor_node->ip;
441 call->ms.sym = cursor_node->sym; 439 call->ms.sym = cursor_node->sym;
442 call->ms.map = cursor_node->map; 440 call->ms.map = cursor_node->map;
441
442 if (cursor_node->branch) {
443 call->branch_count = 1;
444
445 if (cursor_node->branch_flags.predicted)
446 call->predicted_count = 1;
447
448 if (cursor_node->branch_flags.abort)
449 call->abort_count = 1;
450
451 call->cycles_count = cursor_node->branch_flags.cycles;
452 call->iter_count = cursor_node->nr_loop_iter;
453 call->samples_count = cursor_node->samples;
454 }
455
443 list_add_tail(&call->list, &node->val); 456 list_add_tail(&call->list, &node->val);
444 457
445 callchain_cursor_advance(cursor); 458 callchain_cursor_advance(cursor);
@@ -499,8 +512,23 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
499 right = node->ip; 512 right = node->ip;
500 } 513 }
501 514
502 if (left == right) 515 if (left == right) {
516 if (node->branch) {
517 cnode->branch_count++;
518
519 if (node->branch_flags.predicted)
520 cnode->predicted_count++;
521
522 if (node->branch_flags.abort)
523 cnode->abort_count++;
524
525 cnode->cycles_count += node->branch_flags.cycles;
526 cnode->iter_count += node->nr_loop_iter;
527 cnode->samples_count += node->samples;
528 }
529
503 return MATCH_EQ; 530 return MATCH_EQ;
531 }
504 532
505 return left > right ? MATCH_GT : MATCH_LT; 533 return left > right ? MATCH_GT : MATCH_LT;
506} 534}
@@ -730,7 +758,8 @@ merge_chain_branch(struct callchain_cursor *cursor,
730 758
731 list_for_each_entry_safe(list, next_list, &src->val, list) { 759 list_for_each_entry_safe(list, next_list, &src->val, list) {
732 callchain_cursor_append(cursor, list->ip, 760 callchain_cursor_append(cursor, list->ip,
733 list->ms.map, list->ms.sym); 761 list->ms.map, list->ms.sym,
762 false, NULL, 0, 0);
734 list_del(&list->list); 763 list_del(&list->list);
735 free(list); 764 free(list);
736 } 765 }
@@ -767,7 +796,9 @@ int callchain_merge(struct callchain_cursor *cursor,
767} 796}
768 797
769int callchain_cursor_append(struct callchain_cursor *cursor, 798int callchain_cursor_append(struct callchain_cursor *cursor,
770 u64 ip, struct map *map, struct symbol *sym) 799 u64 ip, struct map *map, struct symbol *sym,
800 bool branch, struct branch_flags *flags,
801 int nr_loop_iter, int samples)
771{ 802{
772 struct callchain_cursor_node *node = *cursor->last; 803 struct callchain_cursor_node *node = *cursor->last;
773 804
@@ -782,6 +813,13 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
782 node->ip = ip; 813 node->ip = ip;
783 node->map = map; 814 node->map = map;
784 node->sym = sym; 815 node->sym = sym;
816 node->branch = branch;
817 node->nr_loop_iter = nr_loop_iter;
818 node->samples = samples;
819
820 if (flags)
821 memcpy(&node->branch_flags, flags,
822 sizeof(struct branch_flags));
785 823
786 cursor->nr++; 824 cursor->nr++;
787 825
@@ -939,6 +977,163 @@ int callchain_node__fprintf_value(struct callchain_node *node,
939 return 0; 977 return 0;
940} 978}
941 979
980static void callchain_counts_value(struct callchain_node *node,
981 u64 *branch_count, u64 *predicted_count,
982 u64 *abort_count, u64 *cycles_count)
983{
984 struct callchain_list *clist;
985
986 list_for_each_entry(clist, &node->val, list) {
987 if (branch_count)
988 *branch_count += clist->branch_count;
989
990 if (predicted_count)
991 *predicted_count += clist->predicted_count;
992
993 if (abort_count)
994 *abort_count += clist->abort_count;
995
996 if (cycles_count)
997 *cycles_count += clist->cycles_count;
998 }
999}
1000
1001static int callchain_node_branch_counts_cumul(struct callchain_node *node,
1002 u64 *branch_count,
1003 u64 *predicted_count,
1004 u64 *abort_count,
1005 u64 *cycles_count)
1006{
1007 struct callchain_node *child;
1008 struct rb_node *n;
1009
1010 n = rb_first(&node->rb_root_in);
1011 while (n) {
1012 child = rb_entry(n, struct callchain_node, rb_node_in);
1013 n = rb_next(n);
1014
1015 callchain_node_branch_counts_cumul(child, branch_count,
1016 predicted_count,
1017 abort_count,
1018 cycles_count);
1019
1020 callchain_counts_value(child, branch_count,
1021 predicted_count, abort_count,
1022 cycles_count);
1023 }
1024
1025 return 0;
1026}
1027
1028int callchain_branch_counts(struct callchain_root *root,
1029 u64 *branch_count, u64 *predicted_count,
1030 u64 *abort_count, u64 *cycles_count)
1031{
1032 if (branch_count)
1033 *branch_count = 0;
1034
1035 if (predicted_count)
1036 *predicted_count = 0;
1037
1038 if (abort_count)
1039 *abort_count = 0;
1040
1041 if (cycles_count)
1042 *cycles_count = 0;
1043
1044 return callchain_node_branch_counts_cumul(&root->node,
1045 branch_count,
1046 predicted_count,
1047 abort_count,
1048 cycles_count);
1049}
1050
1051static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1052 u64 branch_count, u64 predicted_count,
1053 u64 abort_count, u64 cycles_count,
1054 u64 iter_count, u64 samples_count)
1055{
1056 double predicted_percent = 0.0;
1057 const char *null_str = "";
1058 char iter_str[32];
1059 char *str;
1060 u64 cycles = 0;
1061
1062 if (branch_count == 0) {
1063 if (fp)
1064 return fprintf(fp, " (calltrace)");
1065
1066 return scnprintf(bf, bfsize, " (calltrace)");
1067 }
1068
1069 if (iter_count && samples_count) {
1070 scnprintf(iter_str, sizeof(iter_str),
1071 ", iterations:%" PRId64 "",
1072 iter_count / samples_count);
1073 str = iter_str;
1074 } else
1075 str = (char *)null_str;
1076
1077 predicted_percent = predicted_count * 100.0 / branch_count;
1078 cycles = cycles_count / branch_count;
1079
1080 if ((predicted_percent >= 100.0) && (abort_count == 0)) {
1081 if (fp)
1082 return fprintf(fp, " (cycles:%" PRId64 "%s)",
1083 cycles, str);
1084
1085 return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)",
1086 cycles, str);
1087 }
1088
1089 if ((predicted_percent < 100.0) && (abort_count == 0)) {
1090 if (fp)
1091 return fprintf(fp,
1092 " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
1093 predicted_percent, cycles, str);
1094
1095 return scnprintf(bf, bfsize,
1096 " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
1097 predicted_percent, cycles, str);
1098 }
1099
1100 if (fp)
1101 return fprintf(fp,
1102 " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
1103 predicted_percent, abort_count, cycles, str);
1104
1105 return scnprintf(bf, bfsize,
1106 " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
1107 predicted_percent, abort_count, cycles, str);
1108}
1109
1110int callchain_list_counts__printf_value(struct callchain_node *node,
1111 struct callchain_list *clist,
1112 FILE *fp, char *bf, int bfsize)
1113{
1114 u64 branch_count, predicted_count;
1115 u64 abort_count, cycles_count;
1116 u64 iter_count = 0, samples_count = 0;
1117
1118 branch_count = clist->branch_count;
1119 predicted_count = clist->predicted_count;
1120 abort_count = clist->abort_count;
1121 cycles_count = clist->cycles_count;
1122
1123 if (node) {
1124 struct callchain_list *call;
1125
1126 list_for_each_entry(call, &node->val, list) {
1127 iter_count += call->iter_count;
1128 samples_count += call->samples_count;
1129 }
1130 }
1131
1132 return callchain_counts_printf(fp, bf, bfsize, branch_count,
1133 predicted_count, abort_count,
1134 cycles_count, iter_count, samples_count);
1135}
1136
942static void free_callchain_node(struct callchain_node *node) 1137static void free_callchain_node(struct callchain_node *node)
943{ 1138{
944 struct callchain_list *list, *tmp; 1139 struct callchain_list *list, *tmp;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 13e75549c440..d9c70dccf06a 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -11,11 +11,7 @@
11 11
12#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n" 12#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n"
13 13
14#ifdef HAVE_DWARF_UNWIND_SUPPORT
15# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n" 14# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n"
16#else
17# define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|lbr)\n"
18#endif
19 15
20#define RECORD_SIZE_HELP \ 16#define RECORD_SIZE_HELP \
21 HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \ 17 HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \
@@ -115,6 +111,12 @@ struct callchain_list {
115 bool unfolded; 111 bool unfolded;
116 bool has_children; 112 bool has_children;
117 }; 113 };
114 u64 branch_count;
115 u64 predicted_count;
116 u64 abort_count;
117 u64 cycles_count;
118 u64 iter_count;
119 u64 samples_count;
118 char *srcline; 120 char *srcline;
119 struct list_head list; 121 struct list_head list;
120}; 122};
@@ -129,6 +131,10 @@ struct callchain_cursor_node {
129 u64 ip; 131 u64 ip;
130 struct map *map; 132 struct map *map;
131 struct symbol *sym; 133 struct symbol *sym;
134 bool branch;
135 struct branch_flags branch_flags;
136 int nr_loop_iter;
137 int samples;
132 struct callchain_cursor_node *next; 138 struct callchain_cursor_node *next;
133}; 139};
134 140
@@ -183,7 +189,9 @@ static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
183} 189}
184 190
185int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, 191int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
186 struct map *map, struct symbol *sym); 192 struct map *map, struct symbol *sym,
193 bool branch, struct branch_flags *flags,
194 int nr_loop_iter, int samples);
187 195
188/* Close a cursor writing session. Initialize for the reader */ 196/* Close a cursor writing session. Initialize for the reader */
189static inline void callchain_cursor_commit(struct callchain_cursor *cursor) 197static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
@@ -261,8 +269,16 @@ char *callchain_node__scnprintf_value(struct callchain_node *node,
261int callchain_node__fprintf_value(struct callchain_node *node, 269int callchain_node__fprintf_value(struct callchain_node *node,
262 FILE *fp, u64 total); 270 FILE *fp, u64 total);
263 271
272int callchain_list_counts__printf_value(struct callchain_node *node,
273 struct callchain_list *clist,
274 FILE *fp, char *bf, int bfsize);
275
264void free_callchain(struct callchain_root *root); 276void free_callchain(struct callchain_root *root);
265void decay_callchain(struct callchain_root *root); 277void decay_callchain(struct callchain_root *root);
266int callchain_node__make_parent_list(struct callchain_node *node); 278int callchain_node__make_parent_list(struct callchain_node *node);
267 279
280int callchain_branch_counts(struct callchain_root *root,
281 u64 *branch_count, u64 *predicted_count,
282 u64 *abort_count, u64 *cycles_count);
283
268#endif /* __PERF_CALLCHAIN_H */ 284#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 18dae745034f..3d906dbbef74 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -594,6 +594,19 @@ static int collect_config(const char *var, const char *value,
594 goto out_free; 594 goto out_free;
595 } 595 }
596 596
597 /* perf_config_set can contain both user and system config items.
598 * So we should know where each value is from.
599 * The classification would be needed when a particular config file
600 * is overwrited by setting feature i.e. set_config().
601 */
602 if (strcmp(config_file_name, perf_etc_perfconfig()) == 0) {
603 section->from_system_config = true;
604 item->from_system_config = true;
605 } else {
606 section->from_system_config = false;
607 item->from_system_config = false;
608 }
609
597 ret = set_value(item, value); 610 ret = set_value(item, value);
598 return ret; 611 return ret;
599 612
@@ -602,6 +615,13 @@ out_free:
602 return -1; 615 return -1;
603} 616}
604 617
618int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
619 const char *var, const char *value)
620{
621 config_file_name = file_name;
622 return collect_config(var, value, set);
623}
624
605static int perf_config_set__init(struct perf_config_set *set) 625static int perf_config_set__init(struct perf_config_set *set)
606{ 626{
607 int ret = -1; 627 int ret = -1;
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
index 6f813d46045e..1a59a6b43f8b 100644
--- a/tools/perf/util/config.h
+++ b/tools/perf/util/config.h
@@ -7,12 +7,14 @@
7struct perf_config_item { 7struct perf_config_item {
8 char *name; 8 char *name;
9 char *value; 9 char *value;
10 bool from_system_config;
10 struct list_head node; 11 struct list_head node;
11}; 12};
12 13
13struct perf_config_section { 14struct perf_config_section {
14 char *name; 15 char *name;
15 struct list_head items; 16 struct list_head items;
17 bool from_system_config;
16 struct list_head node; 18 struct list_head node;
17}; 19};
18 20
@@ -33,6 +35,8 @@ const char *perf_etc_perfconfig(void);
33 35
34struct perf_config_set *perf_config_set__new(void); 36struct perf_config_set *perf_config_set__new(void);
35void perf_config_set__delete(struct perf_config_set *set); 37void perf_config_set__delete(struct perf_config_set *set);
38int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
39 const char *var, const char *value);
36void perf_config__init(void); 40void perf_config__init(void);
37void perf_config__exit(void); 41void perf_config__exit(void);
38void perf_config__refresh(void); 42void perf_config__refresh(void);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index df85b9efd80f..9b33bef54581 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1616,7 +1616,11 @@ static int add_callchain_ip(struct thread *thread,
1616 struct symbol **parent, 1616 struct symbol **parent,
1617 struct addr_location *root_al, 1617 struct addr_location *root_al,
1618 u8 *cpumode, 1618 u8 *cpumode,
1619 u64 ip) 1619 u64 ip,
1620 bool branch,
1621 struct branch_flags *flags,
1622 int nr_loop_iter,
1623 int samples)
1620{ 1624{
1621 struct addr_location al; 1625 struct addr_location al;
1622 1626
@@ -1668,7 +1672,8 @@ static int add_callchain_ip(struct thread *thread,
1668 1672
1669 if (symbol_conf.hide_unresolved && al.sym == NULL) 1673 if (symbol_conf.hide_unresolved && al.sym == NULL)
1670 return 0; 1674 return 0;
1671 return callchain_cursor_append(cursor, al.addr, al.map, al.sym); 1675 return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
1676 branch, flags, nr_loop_iter, samples);
1672} 1677}
1673 1678
1674struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1679struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1757,7 +1762,9 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1757 /* LBR only affects the user callchain */ 1762 /* LBR only affects the user callchain */
1758 if (i != chain_nr) { 1763 if (i != chain_nr) {
1759 struct branch_stack *lbr_stack = sample->branch_stack; 1764 struct branch_stack *lbr_stack = sample->branch_stack;
1760 int lbr_nr = lbr_stack->nr, j; 1765 int lbr_nr = lbr_stack->nr, j, k;
1766 bool branch;
1767 struct branch_flags *flags;
1761 /* 1768 /*
1762 * LBR callstack can only get user call chain. 1769 * LBR callstack can only get user call chain.
1763 * The mix_chain_nr is kernel call chain 1770 * The mix_chain_nr is kernel call chain
@@ -1772,23 +1779,41 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1772 1779
1773 for (j = 0; j < mix_chain_nr; j++) { 1780 for (j = 0; j < mix_chain_nr; j++) {
1774 int err; 1781 int err;
1782 branch = false;
1783 flags = NULL;
1784
1775 if (callchain_param.order == ORDER_CALLEE) { 1785 if (callchain_param.order == ORDER_CALLEE) {
1776 if (j < i + 1) 1786 if (j < i + 1)
1777 ip = chain->ips[j]; 1787 ip = chain->ips[j];
1778 else if (j > i + 1) 1788 else if (j > i + 1) {
1779 ip = lbr_stack->entries[j - i - 2].from; 1789 k = j - i - 2;
1780 else 1790 ip = lbr_stack->entries[k].from;
1791 branch = true;
1792 flags = &lbr_stack->entries[k].flags;
1793 } else {
1781 ip = lbr_stack->entries[0].to; 1794 ip = lbr_stack->entries[0].to;
1795 branch = true;
1796 flags = &lbr_stack->entries[0].flags;
1797 }
1782 } else { 1798 } else {
1783 if (j < lbr_nr) 1799 if (j < lbr_nr) {
1784 ip = lbr_stack->entries[lbr_nr - j - 1].from; 1800 k = lbr_nr - j - 1;
1801 ip = lbr_stack->entries[k].from;
1802 branch = true;
1803 flags = &lbr_stack->entries[k].flags;
1804 }
1785 else if (j > lbr_nr) 1805 else if (j > lbr_nr)
1786 ip = chain->ips[i + 1 - (j - lbr_nr)]; 1806 ip = chain->ips[i + 1 - (j - lbr_nr)];
1787 else 1807 else {
1788 ip = lbr_stack->entries[0].to; 1808 ip = lbr_stack->entries[0].to;
1809 branch = true;
1810 flags = &lbr_stack->entries[0].flags;
1811 }
1789 } 1812 }
1790 1813
1791 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); 1814 err = add_callchain_ip(thread, cursor, parent,
1815 root_al, &cpumode, ip,
1816 branch, flags, 0, 0);
1792 if (err) 1817 if (err)
1793 return (err < 0) ? err : 0; 1818 return (err < 0) ? err : 0;
1794 } 1819 }
@@ -1813,6 +1838,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1813 int i, j, err, nr_entries; 1838 int i, j, err, nr_entries;
1814 int skip_idx = -1; 1839 int skip_idx = -1;
1815 int first_call = 0; 1840 int first_call = 0;
1841 int nr_loop_iter;
1816 1842
1817 if (perf_evsel__has_branch_callstack(evsel)) { 1843 if (perf_evsel__has_branch_callstack(evsel)) {
1818 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent, 1844 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
@@ -1868,14 +1894,37 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1868 be[i] = branch->entries[branch->nr - i - 1]; 1894 be[i] = branch->entries[branch->nr - i - 1];
1869 } 1895 }
1870 1896
1897 nr_loop_iter = nr;
1871 nr = remove_loops(be, nr); 1898 nr = remove_loops(be, nr);
1872 1899
1900 /*
1901 * Get the number of iterations.
1902 * It's only approximation, but good enough in practice.
1903 */
1904 if (nr_loop_iter > nr)
1905 nr_loop_iter = nr_loop_iter - nr + 1;
1906 else
1907 nr_loop_iter = 0;
1908
1873 for (i = 0; i < nr; i++) { 1909 for (i = 0; i < nr; i++) {
1874 err = add_callchain_ip(thread, cursor, parent, root_al, 1910 if (i == nr - 1)
1875 NULL, be[i].to); 1911 err = add_callchain_ip(thread, cursor, parent,
1912 root_al,
1913 NULL, be[i].to,
1914 true, &be[i].flags,
1915 nr_loop_iter, 1);
1916 else
1917 err = add_callchain_ip(thread, cursor, parent,
1918 root_al,
1919 NULL, be[i].to,
1920 true, &be[i].flags,
1921 0, 0);
1922
1876 if (!err) 1923 if (!err)
1877 err = add_callchain_ip(thread, cursor, parent, root_al, 1924 err = add_callchain_ip(thread, cursor, parent, root_al,
1878 NULL, be[i].from); 1925 NULL, be[i].from,
1926 true, &be[i].flags,
1927 0, 0);
1879 if (err == -EINVAL) 1928 if (err == -EINVAL)
1880 break; 1929 break;
1881 if (err) 1930 if (err)
@@ -1903,7 +1952,9 @@ check_calls:
1903 if (ip < PERF_CONTEXT_MAX) 1952 if (ip < PERF_CONTEXT_MAX)
1904 ++nr_entries; 1953 ++nr_entries;
1905 1954
1906 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip); 1955 err = add_callchain_ip(thread, cursor, parent,
1956 root_al, &cpumode, ip,
1957 false, NULL, 0, 0);
1907 1958
1908 if (err) 1959 if (err)
1909 return (err < 0) ? err : 0; 1960 return (err < 0) ? err : 0;
@@ -1919,7 +1970,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
1919 if (symbol_conf.hide_unresolved && entry->sym == NULL) 1970 if (symbol_conf.hide_unresolved && entry->sym == NULL)
1920 return 0; 1971 return 0;
1921 return callchain_cursor_append(cursor, entry->ip, 1972 return callchain_cursor_append(cursor, entry->ip,
1922 entry->map, entry->sym); 1973 entry->map, entry->sym,
1974 false, NULL, 0, 0);
1923} 1975}
1924 1976
1925static int thread__resolve_callchain_unwind(struct thread *thread, 1977static int thread__resolve_callchain_unwind(struct thread *thread,
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index d964844eb314..2d0a905c879a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -100,6 +100,7 @@ struct symbol_conf {
100 show_total_period, 100 show_total_period,
101 use_callchain, 101 use_callchain,
102 cumulate_callchain, 102 cumulate_callchain,
103 show_branchflag_count,
103 exclude_other, 104 exclude_other,
104 show_cpu_utilization, 105 show_cpu_utilization,
105 initialized, 106 initialized,