aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/Makefile2
-rw-r--r--tools/perf/Makefile.config2
-rw-r--r--tools/perf/Makefile.perf18
-rw-r--r--tools/perf/arch/arm64/Makefile5
-rw-r--r--tools/perf/arch/arm64/annotate/instructions.c59
-rwxr-xr-xtools/perf/arch/arm64/entry/syscalls/mksyscalltbl6
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c4
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c2
-rw-r--r--tools/perf/arch/x86/include/arch-tests.h1
-rw-r--r--tools/perf/arch/x86/tests/Build1
-rw-r--r--tools/perf/arch/x86/tests/arch-tests.c6
-rw-r--r--tools/perf/arch/x86/tests/bp-modify.c213
-rw-r--r--tools/perf/builtin-annotate.c7
-rw-r--r--tools/perf/builtin-inject.c40
-rw-r--r--tools/perf/builtin-record.c53
-rw-r--r--tools/perf/builtin-report.c12
-rw-r--r--tools/perf/builtin-script.c110
-rw-r--r--tools/perf/builtin-stat.c1463
-rw-r--r--tools/perf/builtin-trace.c179
-rwxr-xr-xtools/perf/check-headers.sh1
-rw-r--r--tools/perf/command-list.txt1
-rw-r--r--tools/perf/examples/bpf/augmented_syscalls.c154
-rw-r--r--tools/perf/examples/bpf/etcsnoop.c80
-rw-r--r--tools/perf/include/bpf/bpf.h3
-rw-r--r--tools/perf/include/bpf/linux/socket.h24
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json23
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json26
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json191
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json20
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json32
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json50
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json89
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json14
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json29
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json50
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json16
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json16
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py9
-rw-r--r--tools/perf/scripts/python/export-to-sqlite.py6
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/builtin-test.c10
-rw-r--r--tools/perf/tests/evsel-tp-sched.c4
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh2
-rw-r--r--tools/perf/tests/tests.h4
-rw-r--r--tools/perf/tests/wp.c241
-rw-r--r--tools/perf/trace/beauty/Build1
-rw-r--r--tools/perf/trace/beauty/beauty.h34
-rw-r--r--tools/perf/trace/beauty/sockaddr.c76
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c32
-rw-r--r--tools/perf/util/annotate.h1
-rw-r--r--tools/perf/util/auxtrace.c30
-rw-r--r--tools/perf/util/auxtrace.h41
-rw-r--r--tools/perf/util/bpf-loader.c2
-rw-r--r--tools/perf/util/data-convert-bt.c58
-rw-r--r--tools/perf/util/db-export.c22
-rw-r--r--tools/perf/util/event.c22
-rw-r--r--tools/perf/util/evsel.c47
-rw-r--r--tools/perf/util/evsel.h11
-rw-r--r--tools/perf/util/evsel_fprintf.c2
-rw-r--r--tools/perf/util/header.c24
-rw-r--r--tools/perf/util/header.h17
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c34
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h2
-rw-r--r--tools/perf/util/intel-pt.c5
-rw-r--r--tools/perf/util/llvm-utils.c2
-rw-r--r--tools/perf/util/machine.c8
-rw-r--r--tools/perf/util/map.c26
-rw-r--r--tools/perf/util/mmap.c6
-rw-r--r--tools/perf/util/mmap.h17
-rw-r--r--tools/perf/util/ordered-events.c87
-rw-r--r--tools/perf/util/ordered-events.h37
-rw-r--r--tools/perf/util/pmu.c13
-rw-r--r--tools/perf/util/python.c20
-rw-r--r--tools/perf/util/s390-cpumsf.c94
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c66
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c100
-rw-r--r--tools/perf/util/session.c75
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/setup.py18
-rw-r--r--tools/perf/util/sort.c22
-rw-r--r--tools/perf/util/srcline.c3
-rw-r--r--tools/perf/util/stat-display.c1166
-rw-r--r--tools/perf/util/stat-shadow.c147
-rw-r--r--tools/perf/util/stat.c100
-rw-r--r--tools/perf/util/stat.h77
-rw-r--r--tools/perf/util/strbuf.c10
-rw-r--r--tools/perf/util/thread-stack.c51
-rw-r--r--tools/perf/util/tool.h7
-rw-r--r--tools/perf/util/trace-event-info.c4
-rw-r--r--tools/perf/util/trace-event-parse.c51
-rw-r--r--tools/perf/util/trace-event-read.c15
-rw-r--r--tools/perf/util/trace-event.c8
-rw-r--r--tools/perf/util/trace-event.h21
-rw-r--r--tools/perf/util/util.c2
-rw-r--r--tools/perf/util/util.h2
96 files changed, 3921 insertions, 2080 deletions
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 42261a9b280e..ac841bc5c35b 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -280,7 +280,7 @@ $(MAN_HTML): $(OUTPUT)%.html : %.txt
280 mv $@+ $@ 280 mv $@+ $@
281 281
282ifdef USE_ASCIIDOCTOR 282ifdef USE_ASCIIDOCTOR
283$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.txt 283$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : %.txt
284 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 284 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
285 $(ASCIIDOC) -b manpage -d manpage \ 285 $(ASCIIDOC) -b manpage -d manpage \
286 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \ 286 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index f6d1a03c7523..e30d20fb482d 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -833,7 +833,7 @@ ifndef NO_JVMTI
833 JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}') 833 JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
834 else 834 else
835 ifneq (,$(wildcard /usr/sbin/alternatives)) 835 ifneq (,$(wildcard /usr/sbin/alternatives))
836 JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g') 836 JDIR=$(shell /usr/sbin/alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
837 endif 837 endif
838 endif 838 endif
839 ifndef JDIR 839 ifndef JDIR
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index b3d1b12a5081..2f3bf025e305 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -635,7 +635,7 @@ $(LIBPERF_IN): prepare FORCE
635$(LIB_FILE): $(LIBPERF_IN) 635$(LIB_FILE): $(LIBPERF_IN)
636 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS) 636 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS)
637 637
638LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 638LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 'EXTRA_CFLAGS=$(EXTRA_CFLAGS)' 'LDFLAGS=$(LDFLAGS)'
639 639
640$(LIBTRACEEVENT): FORCE 640$(LIBTRACEEVENT): FORCE
641 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a 641 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a
@@ -777,14 +777,14 @@ endif
777 $(call QUIET_INSTALL, libexec) \ 777 $(call QUIET_INSTALL, libexec) \
778 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 778 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
779ifndef NO_LIBBPF 779ifndef NO_LIBBPF
780 $(call QUIET_INSTALL, lib) \ 780 $(call QUIET_INSTALL, bpf-headers) \
781 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf' 781 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
782 $(call QUIET_INSTALL, include/bpf) \ 782 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'; \
783 $(INSTALL) include/bpf/*.h '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf' 783 $(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
784 $(call QUIET_INSTALL, lib) \ 784 $(INSTALL) include/bpf/linux/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'
785 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf' 785 $(call QUIET_INSTALL, bpf-examples) \
786 $(call QUIET_INSTALL, examples/bpf) \ 786 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'; \
787 $(INSTALL) examples/bpf/*.c '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf' 787 $(INSTALL) examples/bpf/*.c -t '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
788endif 788endif
789 $(call QUIET_INSTALL, perf-archive) \ 789 $(call QUIET_INSTALL, perf-archive) \
790 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 790 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
diff --git a/tools/perf/arch/arm64/Makefile b/tools/perf/arch/arm64/Makefile
index f013b115dc86..dbef716a1913 100644
--- a/tools/perf/arch/arm64/Makefile
+++ b/tools/perf/arch/arm64/Makefile
@@ -11,7 +11,8 @@ PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
11 11
12out := $(OUTPUT)arch/arm64/include/generated/asm 12out := $(OUTPUT)arch/arm64/include/generated/asm
13header := $(out)/syscalls.c 13header := $(out)/syscalls.c
14sysdef := $(srctree)/tools/include/uapi/asm-generic/unistd.h 14incpath := $(srctree)/tools
15sysdef := $(srctree)/tools/arch/arm64/include/uapi/asm/unistd.h
15sysprf := $(srctree)/tools/perf/arch/arm64/entry/syscalls/ 16sysprf := $(srctree)/tools/perf/arch/arm64/entry/syscalls/
16systbl := $(sysprf)/mksyscalltbl 17systbl := $(sysprf)/mksyscalltbl
17 18
@@ -19,7 +20,7 @@ systbl := $(sysprf)/mksyscalltbl
19_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)') 20_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
20 21
21$(header): $(sysdef) $(systbl) 22$(header): $(sysdef) $(systbl)
22 $(Q)$(SHELL) '$(systbl)' '$(CC)' '$(HOSTCC)' $(sysdef) > $@ 23 $(Q)$(SHELL) '$(systbl)' '$(CC)' '$(HOSTCC)' $(incpath) $(sysdef) > $@
23 24
24clean:: 25clean::
25 $(call QUIET_CLEAN, arm64) $(RM) $(header) 26 $(call QUIET_CLEAN, arm64) $(RM) $(header)
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 6688977e4ac7..76c6345a57d5 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -8,6 +8,63 @@ struct arm64_annotate {
8 jump_insn; 8 jump_insn;
9}; 9};
10 10
11static int arm64_mov__parse(struct arch *arch __maybe_unused,
12 struct ins_operands *ops,
13 struct map_symbol *ms __maybe_unused)
14{
15 char *s = strchr(ops->raw, ','), *target, *endptr;
16
17 if (s == NULL)
18 return -1;
19
20 *s = '\0';
21 ops->source.raw = strdup(ops->raw);
22 *s = ',';
23
24 if (ops->source.raw == NULL)
25 return -1;
26
27 target = ++s;
28 ops->target.raw = strdup(target);
29 if (ops->target.raw == NULL)
30 goto out_free_source;
31
32 ops->target.addr = strtoull(target, &endptr, 16);
33 if (endptr == target)
34 goto out_free_target;
35
36 s = strchr(endptr, '<');
37 if (s == NULL)
38 goto out_free_target;
39 endptr = strchr(s + 1, '>');
40 if (endptr == NULL)
41 goto out_free_target;
42
43 *endptr = '\0';
44 *s = ' ';
45 ops->target.name = strdup(s);
46 *s = '<';
47 *endptr = '>';
48 if (ops->target.name == NULL)
49 goto out_free_target;
50
51 return 0;
52
53out_free_target:
54 zfree(&ops->target.raw);
55out_free_source:
56 zfree(&ops->source.raw);
57 return -1;
58}
59
60static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
61 struct ins_operands *ops);
62
63static struct ins_ops arm64_mov_ops = {
64 .parse = arm64_mov__parse,
65 .scnprintf = mov__scnprintf,
66};
67
11static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name) 68static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
12{ 69{
13 struct arm64_annotate *arm = arch->priv; 70 struct arm64_annotate *arm = arch->priv;
@@ -21,7 +78,7 @@ static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const
21 else if (!strcmp(name, "ret")) 78 else if (!strcmp(name, "ret"))
22 ops = &ret_ops; 79 ops = &ret_ops;
23 else 80 else
24 return NULL; 81 ops = &arm64_mov_ops;
25 82
26 arch__associate_ins_ops(arch, name, ops); 83 arch__associate_ins_ops(arch, name, ops);
27 return ops; 84 return ops;
diff --git a/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl b/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
index 52e197317d3e..2dbb8cade048 100755
--- a/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
+++ b/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
@@ -11,7 +11,8 @@
11 11
12gcc=$1 12gcc=$1
13hostcc=$2 13hostcc=$2
14input=$3 14incpath=$3
15input=$4
15 16
16if ! test -r $input; then 17if ! test -r $input; then
17 echo "Could not read input file" >&2 18 echo "Could not read input file" >&2
@@ -28,7 +29,6 @@ create_table_from_c()
28 29
29 cat <<-_EoHEADER 30 cat <<-_EoHEADER
30 #include <stdio.h> 31 #include <stdio.h>
31 #define __ARCH_WANT_RENAMEAT
32 #include "$input" 32 #include "$input"
33 int main(int argc, char *argv[]) 33 int main(int argc, char *argv[])
34 { 34 {
@@ -42,7 +42,7 @@ create_table_from_c()
42 printf "%s\n" " printf(\"#define SYSCALLTBL_ARM64_MAX_ID %d\\n\", __NR_$last_sc);" 42 printf "%s\n" " printf(\"#define SYSCALLTBL_ARM64_MAX_ID %d\\n\", __NR_$last_sc);"
43 printf "}\n" 43 printf "}\n"
44 44
45 } | $hostcc -o $create_table_exe -x c - 45 } | $hostcc -I $incpath/include/uapi -o $create_table_exe -x c -
46 46
47 $create_table_exe 47 $create_table_exe
48 48
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index 20e7d74d86cd..10a44e946f77 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -22,15 +22,16 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
22 22
23#endif 23#endif
24 24
25#if !defined(_CALL_ELF) || _CALL_ELF != 2
26int arch__choose_best_symbol(struct symbol *syma, 25int arch__choose_best_symbol(struct symbol *syma,
27 struct symbol *symb __maybe_unused) 26 struct symbol *symb __maybe_unused)
28{ 27{
29 char *sym = syma->name; 28 char *sym = syma->name;
30 29
30#if !defined(_CALL_ELF) || _CALL_ELF != 2
31 /* Skip over any initial dot */ 31 /* Skip over any initial dot */
32 if (*sym == '.') 32 if (*sym == '.')
33 sym++; 33 sym++;
34#endif
34 35
35 /* Avoid "SyS" kernel syscall aliases */ 36 /* Avoid "SyS" kernel syscall aliases */
36 if (strlen(sym) >= 3 && !strncmp(sym, "SyS", 3)) 37 if (strlen(sym) >= 3 && !strncmp(sym, "SyS", 3))
@@ -41,6 +42,7 @@ int arch__choose_best_symbol(struct symbol *syma,
41 return SYMBOL_A; 42 return SYMBOL_A;
42} 43}
43 44
45#if !defined(_CALL_ELF) || _CALL_ELF != 2
44/* Allow matching against dot variants */ 46/* Allow matching against dot variants */
45int arch__compare_symbol_names(const char *namea, const char *nameb) 47int arch__compare_symbol_names(const char *namea, const char *nameb)
46{ 48{
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index cee4e2f7c057..de0dd66dbb48 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -100,8 +100,6 @@ out_free_source:
100 return -1; 100 return -1;
101} 101}
102 102
103static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
104 struct ins_operands *ops);
105 103
106static struct ins_ops s390_mov_ops = { 104static struct ins_ops s390_mov_ops = {
107 .parse = s390_mov__parse, 105 .parse = s390_mov__parse,
diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h
index c1bd979b957b..613709cfbbd0 100644
--- a/tools/perf/arch/x86/include/arch-tests.h
+++ b/tools/perf/arch/x86/include/arch-tests.h
@@ -9,6 +9,7 @@ struct test;
9int test__rdpmc(struct test *test __maybe_unused, int subtest); 9int test__rdpmc(struct test *test __maybe_unused, int subtest);
10int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest); 10int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest);
11int test__insn_x86(struct test *test __maybe_unused, int subtest); 11int test__insn_x86(struct test *test __maybe_unused, int subtest);
12int test__bp_modify(struct test *test, int subtest);
12 13
13#ifdef HAVE_DWARF_UNWIND_SUPPORT 14#ifdef HAVE_DWARF_UNWIND_SUPPORT
14struct thread; 15struct thread;
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
index 8e2c5a38c3b9..586849ff83a0 100644
--- a/tools/perf/arch/x86/tests/Build
+++ b/tools/perf/arch/x86/tests/Build
@@ -5,3 +5,4 @@ libperf-y += arch-tests.o
5libperf-y += rdpmc.o 5libperf-y += rdpmc.o
6libperf-y += perf-time-to-tsc.o 6libperf-y += perf-time-to-tsc.o
7libperf-$(CONFIG_AUXTRACE) += insn-x86.o 7libperf-$(CONFIG_AUXTRACE) += insn-x86.o
8libperf-$(CONFIG_X86_64) += bp-modify.o
diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c
index cc1802ff5410..d47d3f8e3c8e 100644
--- a/tools/perf/arch/x86/tests/arch-tests.c
+++ b/tools/perf/arch/x86/tests/arch-tests.c
@@ -24,6 +24,12 @@ struct test arch_tests[] = {
24 .func = test__insn_x86, 24 .func = test__insn_x86,
25 }, 25 },
26#endif 26#endif
27#if defined(__x86_64__)
28 {
29 .desc = "x86 bp modify",
30 .func = test__bp_modify,
31 },
32#endif
27 { 33 {
28 .func = NULL, 34 .func = NULL,
29 }, 35 },
diff --git a/tools/perf/arch/x86/tests/bp-modify.c b/tools/perf/arch/x86/tests/bp-modify.c
new file mode 100644
index 000000000000..f53e4406709f
--- /dev/null
+++ b/tools/perf/arch/x86/tests/bp-modify.c
@@ -0,0 +1,213 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compiler.h>
3#include <sys/types.h>
4#include <sys/wait.h>
5#include <sys/user.h>
6#include <syscall.h>
7#include <unistd.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <sys/ptrace.h>
11#include <asm/ptrace.h>
12#include <errno.h>
13#include "debug.h"
14#include "tests/tests.h"
15#include "arch-tests.h"
16
17static noinline int bp_1(void)
18{
19 pr_debug("in %s\n", __func__);
20 return 0;
21}
22
23static noinline int bp_2(void)
24{
25 pr_debug("in %s\n", __func__);
26 return 0;
27}
28
29static int spawn_child(void)
30{
31 int child = fork();
32
33 if (child == 0) {
34 /*
35 * The child sets itself for as tracee and
36 * waits in signal for parent to trace it,
37 * then it calls bp_1 and quits.
38 */
39 int err = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
40
41 if (err) {
42 pr_debug("failed to PTRACE_TRACEME\n");
43 exit(1);
44 }
45
46 raise(SIGCONT);
47 bp_1();
48 exit(0);
49 }
50
51 return child;
52}
53
54/*
55 * This tests creates HW breakpoint, tries to
56 * change it and checks it was properly changed.
57 */
58static int bp_modify1(void)
59{
60 pid_t child;
61 int status;
62 unsigned long rip = 0, dr7 = 1;
63
64 child = spawn_child();
65
66 waitpid(child, &status, 0);
67 if (WIFEXITED(status)) {
68 pr_debug("tracee exited prematurely 1\n");
69 return TEST_FAIL;
70 }
71
72 /*
73 * The parent does following steps:
74 * - creates a new breakpoint (id 0) for bp_2 function
75 * - changes that breakponit to bp_1 function
76 * - waits for the breakpoint to hit and checks
77 * it has proper rip of bp_1 function
78 * - detaches the child
79 */
80 if (ptrace(PTRACE_POKEUSER, child,
81 offsetof(struct user, u_debugreg[0]), bp_2)) {
82 pr_debug("failed to set breakpoint, 1st time: %s\n",
83 strerror(errno));
84 goto out;
85 }
86
87 if (ptrace(PTRACE_POKEUSER, child,
88 offsetof(struct user, u_debugreg[0]), bp_1)) {
89 pr_debug("failed to set breakpoint, 2nd time: %s\n",
90 strerror(errno));
91 goto out;
92 }
93
94 if (ptrace(PTRACE_POKEUSER, child,
95 offsetof(struct user, u_debugreg[7]), dr7)) {
96 pr_debug("failed to set dr7: %s\n", strerror(errno));
97 goto out;
98 }
99
100 if (ptrace(PTRACE_CONT, child, NULL, NULL)) {
101 pr_debug("failed to PTRACE_CONT: %s\n", strerror(errno));
102 goto out;
103 }
104
105 waitpid(child, &status, 0);
106 if (WIFEXITED(status)) {
107 pr_debug("tracee exited prematurely 2\n");
108 return TEST_FAIL;
109 }
110
111 rip = ptrace(PTRACE_PEEKUSER, child,
112 offsetof(struct user_regs_struct, rip), NULL);
113 if (rip == (unsigned long) -1) {
114 pr_debug("failed to PTRACE_PEEKUSER: %s\n",
115 strerror(errno));
116 goto out;
117 }
118
119 pr_debug("rip %lx, bp_1 %p\n", rip, bp_1);
120
121out:
122 if (ptrace(PTRACE_DETACH, child, NULL, NULL)) {
123 pr_debug("failed to PTRACE_DETACH: %s", strerror(errno));
124 return TEST_FAIL;
125 }
126
127 return rip == (unsigned long) bp_1 ? TEST_OK : TEST_FAIL;
128}
129
130/*
131 * This tests creates HW breakpoint, tries to
132 * change it to bogus value and checks the original
133 * breakpoint is hit.
134 */
135static int bp_modify2(void)
136{
137 pid_t child;
138 int status;
139 unsigned long rip = 0, dr7 = 1;
140
141 child = spawn_child();
142
143 waitpid(child, &status, 0);
144 if (WIFEXITED(status)) {
145 pr_debug("tracee exited prematurely 1\n");
146 return TEST_FAIL;
147 }
148
149 /*
150 * The parent does following steps:
151 * - creates a new breakpoint (id 0) for bp_1 function
152 * - tries to change that breakpoint to (-1) address
153 * - waits for the breakpoint to hit and checks
154 * it has proper rip of bp_1 function
155 * - detaches the child
156 */
157 if (ptrace(PTRACE_POKEUSER, child,
158 offsetof(struct user, u_debugreg[0]), bp_1)) {
159 pr_debug("failed to set breakpoint: %s\n",
160 strerror(errno));
161 goto out;
162 }
163
164 if (ptrace(PTRACE_POKEUSER, child,
165 offsetof(struct user, u_debugreg[7]), dr7)) {
166 pr_debug("failed to set dr7: %s\n", strerror(errno));
167 goto out;
168 }
169
170 if (!ptrace(PTRACE_POKEUSER, child,
171 offsetof(struct user, u_debugreg[0]), (unsigned long) (-1))) {
172 pr_debug("failed, breakpoint set to bogus address\n");
173 goto out;
174 }
175
176 if (ptrace(PTRACE_CONT, child, NULL, NULL)) {
177 pr_debug("failed to PTRACE_CONT: %s\n", strerror(errno));
178 goto out;
179 }
180
181 waitpid(child, &status, 0);
182 if (WIFEXITED(status)) {
183 pr_debug("tracee exited prematurely 2\n");
184 return TEST_FAIL;
185 }
186
187 rip = ptrace(PTRACE_PEEKUSER, child,
188 offsetof(struct user_regs_struct, rip), NULL);
189 if (rip == (unsigned long) -1) {
190 pr_debug("failed to PTRACE_PEEKUSER: %s\n",
191 strerror(errno));
192 goto out;
193 }
194
195 pr_debug("rip %lx, bp_1 %p\n", rip, bp_1);
196
197out:
198 if (ptrace(PTRACE_DETACH, child, NULL, NULL)) {
199 pr_debug("failed to PTRACE_DETACH: %s", strerror(errno));
200 return TEST_FAIL;
201 }
202
203 return rip == (unsigned long) bp_1 ? TEST_OK : TEST_FAIL;
204}
205
206int test__bp_modify(struct test *test __maybe_unused,
207 int subtest __maybe_unused)
208{
209 TEST_ASSERT_VAL("modify test 1 failed\n", !bp_modify1());
210 TEST_ASSERT_VAL("modify test 2 failed\n", !bp_modify2());
211
212 return 0;
213}
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 830481b8db26..93d679eaf1f4 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -283,12 +283,11 @@ out_put:
283 return ret; 283 return ret;
284} 284}
285 285
286static int process_feature_event(struct perf_tool *tool, 286static int process_feature_event(struct perf_session *session,
287 union perf_event *event, 287 union perf_event *event)
288 struct perf_session *session)
289{ 288{
290 if (event->feat.feat_id < HEADER_LAST_FEATURE) 289 if (event->feat.feat_id < HEADER_LAST_FEATURE)
291 return perf_event__process_feature(tool, event, session); 290 return perf_event__process_feature(session, event);
292 return 0; 291 return 0;
293} 292}
294 293
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index a3b346359ba0..eda41673c4f3 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -86,12 +86,10 @@ static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused,
86} 86}
87#endif 87#endif
88 88
89static int perf_event__repipe_op2_synth(struct perf_tool *tool, 89static int perf_event__repipe_op2_synth(struct perf_session *session,
90 union perf_event *event, 90 union perf_event *event)
91 struct perf_session *session
92 __maybe_unused)
93{ 91{
94 return perf_event__repipe_synth(tool, event); 92 return perf_event__repipe_synth(session->tool, event);
95} 93}
96 94
97static int perf_event__repipe_attr(struct perf_tool *tool, 95static int perf_event__repipe_attr(struct perf_tool *tool,
@@ -133,10 +131,10 @@ static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
133 return 0; 131 return 0;
134} 132}
135 133
136static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, 134static s64 perf_event__repipe_auxtrace(struct perf_session *session,
137 union perf_event *event, 135 union perf_event *event)
138 struct perf_session *session)
139{ 136{
137 struct perf_tool *tool = session->tool;
140 struct perf_inject *inject = container_of(tool, struct perf_inject, 138 struct perf_inject *inject = container_of(tool, struct perf_inject,
141 tool); 139 tool);
142 int ret; 140 int ret;
@@ -174,9 +172,8 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
174#else 172#else
175 173
176static s64 174static s64
177perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused, 175perf_event__repipe_auxtrace(struct perf_session *session __maybe_unused,
178 union perf_event *event __maybe_unused, 176 union perf_event *event __maybe_unused)
179 struct perf_session *session __maybe_unused)
180{ 177{
181 pr_err("AUX area tracing not supported\n"); 178 pr_err("AUX area tracing not supported\n");
182 return -EINVAL; 179 return -EINVAL;
@@ -362,26 +359,24 @@ static int perf_event__repipe_exit(struct perf_tool *tool,
362 return err; 359 return err;
363} 360}
364 361
365static int perf_event__repipe_tracing_data(struct perf_tool *tool, 362static int perf_event__repipe_tracing_data(struct perf_session *session,
366 union perf_event *event, 363 union perf_event *event)
367 struct perf_session *session)
368{ 364{
369 int err; 365 int err;
370 366
371 perf_event__repipe_synth(tool, event); 367 perf_event__repipe_synth(session->tool, event);
372 err = perf_event__process_tracing_data(tool, event, session); 368 err = perf_event__process_tracing_data(session, event);
373 369
374 return err; 370 return err;
375} 371}
376 372
377static int perf_event__repipe_id_index(struct perf_tool *tool, 373static int perf_event__repipe_id_index(struct perf_session *session,
378 union perf_event *event, 374 union perf_event *event)
379 struct perf_session *session)
380{ 375{
381 int err; 376 int err;
382 377
383 perf_event__repipe_synth(tool, event); 378 perf_event__repipe_synth(session->tool, event);
384 err = perf_event__process_id_index(tool, event, session); 379 err = perf_event__process_id_index(session, event);
385 380
386 return err; 381 return err;
387} 382}
@@ -803,7 +798,8 @@ int cmd_inject(int argc, const char **argv)
803 "kallsyms pathname"), 798 "kallsyms pathname"),
804 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), 799 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
805 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, 800 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
806 NULL, "opts", "Instruction Tracing options", 801 NULL, "opts", "Instruction Tracing options\n"
802 ITRACE_HELP,
807 itrace_parse_synth_opts), 803 itrace_parse_synth_opts),
808 OPT_BOOLEAN(0, "strip", &inject.strip, 804 OPT_BOOLEAN(0, "strip", &inject.strip,
809 "strip non-synthesized events (use with --itrace)"), 805 "strip non-synthesized events (use with --itrace)"),
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 22ebeb92ac51..0980dfe3396b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -106,9 +106,12 @@ static bool switch_output_time(struct record *rec)
106 trigger_is_ready(&switch_output_trigger); 106 trigger_is_ready(&switch_output_trigger);
107} 107}
108 108
109static int record__write(struct record *rec, void *bf, size_t size) 109static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
110 void *bf, size_t size)
110{ 111{
111 if (perf_data__write(rec->session->data, bf, size) < 0) { 112 struct perf_data_file *file = &rec->session->data->file;
113
114 if (perf_data_file__write(file, bf, size) < 0) {
112 pr_err("failed to write perf data, error: %m\n"); 115 pr_err("failed to write perf data, error: %m\n");
113 return -1; 116 return -1;
114 } 117 }
@@ -127,15 +130,15 @@ static int process_synthesized_event(struct perf_tool *tool,
127 struct machine *machine __maybe_unused) 130 struct machine *machine __maybe_unused)
128{ 131{
129 struct record *rec = container_of(tool, struct record, tool); 132 struct record *rec = container_of(tool, struct record, tool);
130 return record__write(rec, event, event->header.size); 133 return record__write(rec, NULL, event, event->header.size);
131} 134}
132 135
133static int record__pushfn(void *to, void *bf, size_t size) 136static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size)
134{ 137{
135 struct record *rec = to; 138 struct record *rec = to;
136 139
137 rec->samples++; 140 rec->samples++;
138 return record__write(rec, bf, size); 141 return record__write(rec, map, bf, size);
139} 142}
140 143
141static volatile int done; 144static volatile int done;
@@ -170,6 +173,7 @@ static void record__sig_exit(void)
170#ifdef HAVE_AUXTRACE_SUPPORT 173#ifdef HAVE_AUXTRACE_SUPPORT
171 174
172static int record__process_auxtrace(struct perf_tool *tool, 175static int record__process_auxtrace(struct perf_tool *tool,
176 struct perf_mmap *map,
173 union perf_event *event, void *data1, 177 union perf_event *event, void *data1,
174 size_t len1, void *data2, size_t len2) 178 size_t len1, void *data2, size_t len2)
175{ 179{
@@ -197,21 +201,21 @@ static int record__process_auxtrace(struct perf_tool *tool,
197 if (padding) 201 if (padding)
198 padding = 8 - padding; 202 padding = 8 - padding;
199 203
200 record__write(rec, event, event->header.size); 204 record__write(rec, map, event, event->header.size);
201 record__write(rec, data1, len1); 205 record__write(rec, map, data1, len1);
202 if (len2) 206 if (len2)
203 record__write(rec, data2, len2); 207 record__write(rec, map, data2, len2);
204 record__write(rec, &pad, padding); 208 record__write(rec, map, &pad, padding);
205 209
206 return 0; 210 return 0;
207} 211}
208 212
209static int record__auxtrace_mmap_read(struct record *rec, 213static int record__auxtrace_mmap_read(struct record *rec,
210 struct auxtrace_mmap *mm) 214 struct perf_mmap *map)
211{ 215{
212 int ret; 216 int ret;
213 217
214 ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 218 ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
215 record__process_auxtrace); 219 record__process_auxtrace);
216 if (ret < 0) 220 if (ret < 0)
217 return ret; 221 return ret;
@@ -223,11 +227,11 @@ static int record__auxtrace_mmap_read(struct record *rec,
223} 227}
224 228
225static int record__auxtrace_mmap_read_snapshot(struct record *rec, 229static int record__auxtrace_mmap_read_snapshot(struct record *rec,
226 struct auxtrace_mmap *mm) 230 struct perf_mmap *map)
227{ 231{
228 int ret; 232 int ret;
229 233
230 ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 234 ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
231 record__process_auxtrace, 235 record__process_auxtrace,
232 rec->opts.auxtrace_snapshot_size); 236 rec->opts.auxtrace_snapshot_size);
233 if (ret < 0) 237 if (ret < 0)
@@ -245,13 +249,12 @@ static int record__auxtrace_read_snapshot_all(struct record *rec)
245 int rc = 0; 249 int rc = 0;
246 250
247 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 251 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
248 struct auxtrace_mmap *mm = 252 struct perf_mmap *map = &rec->evlist->mmap[i];
249 &rec->evlist->mmap[i].auxtrace_mmap;
250 253
251 if (!mm->base) 254 if (!map->auxtrace_mmap.base)
252 continue; 255 continue;
253 256
254 if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 257 if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
255 rc = -1; 258 rc = -1;
256 goto out; 259 goto out;
257 } 260 }
@@ -295,7 +298,7 @@ static int record__auxtrace_init(struct record *rec)
295 298
296static inline 299static inline
297int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 300int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
298 struct auxtrace_mmap *mm __maybe_unused) 301 struct perf_mmap *map __maybe_unused)
299{ 302{
300 return 0; 303 return 0;
301} 304}
@@ -529,17 +532,17 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
529 return 0; 532 return 0;
530 533
531 for (i = 0; i < evlist->nr_mmaps; i++) { 534 for (i = 0; i < evlist->nr_mmaps; i++) {
532 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 535 struct perf_mmap *map = &maps[i];
533 536
534 if (maps[i].base) { 537 if (map->base) {
535 if (perf_mmap__push(&maps[i], rec, record__pushfn) != 0) { 538 if (perf_mmap__push(map, rec, record__pushfn) != 0) {
536 rc = -1; 539 rc = -1;
537 goto out; 540 goto out;
538 } 541 }
539 } 542 }
540 543
541 if (mm->base && !rec->opts.auxtrace_snapshot_mode && 544 if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
542 record__auxtrace_mmap_read(rec, mm) != 0) { 545 record__auxtrace_mmap_read(rec, map) != 0) {
543 rc = -1; 546 rc = -1;
544 goto out; 547 goto out;
545 } 548 }
@@ -550,7 +553,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
550 * at least one event. 553 * at least one event.
551 */ 554 */
552 if (bytes_written != rec->bytes_written) 555 if (bytes_written != rec->bytes_written)
553 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 556 rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
554 557
555 if (overwrite) 558 if (overwrite)
556 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 559 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
@@ -758,7 +761,7 @@ static int record__synthesize(struct record *rec, bool tail)
758 * We need to synthesize events first, because some 761 * We need to synthesize events first, because some
759 * features works on top of them (on report side). 762 * features works on top of them (on report side).
760 */ 763 */
761 err = perf_event__synthesize_attrs(tool, session, 764 err = perf_event__synthesize_attrs(tool, rec->evlist,
762 process_synthesized_event); 765 process_synthesized_event);
763 if (err < 0) { 766 if (err < 0) {
764 pr_err("Couldn't synthesize attrs.\n"); 767 pr_err("Couldn't synthesize attrs.\n");
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 76e12bcd1765..257c9c18cb7e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -201,14 +201,13 @@ static void setup_forced_leader(struct report *report,
201 perf_evlist__force_leader(evlist); 201 perf_evlist__force_leader(evlist);
202} 202}
203 203
204static int process_feature_event(struct perf_tool *tool, 204static int process_feature_event(struct perf_session *session,
205 union perf_event *event, 205 union perf_event *event)
206 struct perf_session *session __maybe_unused)
207{ 206{
208 struct report *rep = container_of(tool, struct report, tool); 207 struct report *rep = container_of(session->tool, struct report, tool);
209 208
210 if (event->feat.feat_id < HEADER_LAST_FEATURE) 209 if (event->feat.feat_id < HEADER_LAST_FEATURE)
211 return perf_event__process_feature(tool, event, session); 210 return perf_event__process_feature(session, event);
212 211
213 if (event->feat.feat_id != HEADER_LAST_FEATURE) { 212 if (event->feat.feat_id != HEADER_LAST_FEATURE) {
214 pr_err("failed: wrong feature ID: %" PRIu64 "\n", 213 pr_err("failed: wrong feature ID: %" PRIu64 "\n",
@@ -981,6 +980,7 @@ int cmd_report(int argc, const char **argv)
981 .id_index = perf_event__process_id_index, 980 .id_index = perf_event__process_id_index,
982 .auxtrace_info = perf_event__process_auxtrace_info, 981 .auxtrace_info = perf_event__process_auxtrace_info,
983 .auxtrace = perf_event__process_auxtrace, 982 .auxtrace = perf_event__process_auxtrace,
983 .event_update = perf_event__process_event_update,
984 .feature = process_feature_event, 984 .feature = process_feature_event,
985 .ordered_events = true, 985 .ordered_events = true,
986 .ordering_requires_timestamps = true, 986 .ordering_requires_timestamps = true,
@@ -1105,7 +1105,7 @@ int cmd_report(int argc, const char **argv)
1105 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 1105 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1106 "how to display percentage of filtered entries", parse_filter_percentage), 1106 "how to display percentage of filtered entries", parse_filter_percentage),
1107 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 1107 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
1108 "Instruction Tracing options", 1108 "Instruction Tracing options\n" ITRACE_HELP,
1109 itrace_parse_synth_opts), 1109 itrace_parse_synth_opts),
1110 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, 1110 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
1111 "Show full source file name path for source lines"), 1111 "Show full source file name path for source lines"),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ba481d73f910..4da5e32b9e03 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -406,9 +406,10 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
406 PERF_OUTPUT_WEIGHT)) 406 PERF_OUTPUT_WEIGHT))
407 return -EINVAL; 407 return -EINVAL;
408 408
409 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 409 if (PRINT_FIELD(SYM) &&
410 !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
410 pr_err("Display of symbols requested but neither sample IP nor " 411 pr_err("Display of symbols requested but neither sample IP nor "
411 "sample address\nis selected. Hence, no addresses to convert " 412 "sample address\navailable. Hence, no addresses to convert "
412 "to symbols.\n"); 413 "to symbols.\n");
413 return -EINVAL; 414 return -EINVAL;
414 } 415 }
@@ -417,10 +418,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
417 "selected.\n"); 418 "selected.\n");
418 return -EINVAL; 419 return -EINVAL;
419 } 420 }
420 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) && 421 if (PRINT_FIELD(DSO) &&
421 !PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM) && !PRINT_FIELD(BRSTACKOFF)) { 422 !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
422 pr_err("Display of DSO requested but no address to convert. Select\n" 423 pr_err("Display of DSO requested but no address to convert.\n");
423 "sample IP, sample address, brstack, brstacksym, or brstackoff.\n");
424 return -EINVAL; 424 return -EINVAL;
425 } 425 }
426 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { 426 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
@@ -1115,6 +1115,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1115 const char *name = NULL; 1115 const char *name = NULL;
1116 static int spacing; 1116 static int spacing;
1117 int len = 0; 1117 int len = 0;
1118 int dlen = 0;
1118 u64 ip = 0; 1119 u64 ip = 0;
1119 1120
1120 /* 1121 /*
@@ -1141,6 +1142,12 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1141 ip = sample->ip; 1142 ip = sample->ip;
1142 } 1143 }
1143 1144
1145 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
1146 dlen += fprintf(fp, "(");
1147 dlen += map__fprintf_dsoname(al->map, fp);
1148 dlen += fprintf(fp, ")\t");
1149 }
1150
1144 if (name) 1151 if (name)
1145 len = fprintf(fp, "%*s%s", (int)depth * 4, "", name); 1152 len = fprintf(fp, "%*s%s", (int)depth * 4, "", name);
1146 else if (ip) 1153 else if (ip)
@@ -1159,7 +1166,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1159 if (len < spacing) 1166 if (len < spacing)
1160 len += fprintf(fp, "%*s", spacing - len, ""); 1167 len += fprintf(fp, "%*s", spacing - len, "");
1161 1168
1162 return len; 1169 return len + dlen;
1163} 1170}
1164 1171
1165static int perf_sample__fprintf_insn(struct perf_sample *sample, 1172static int perf_sample__fprintf_insn(struct perf_sample *sample,
@@ -1255,6 +1262,18 @@ static struct {
1255 {0, NULL} 1262 {0, NULL}
1256}; 1263};
1257 1264
1265static const char *sample_flags_to_name(u32 flags)
1266{
1267 int i;
1268
1269 for (i = 0; sample_flags[i].name ; i++) {
1270 if (sample_flags[i].flags == flags)
1271 return sample_flags[i].name;
1272 }
1273
1274 return NULL;
1275}
1276
1258static int perf_sample__fprintf_flags(u32 flags, FILE *fp) 1277static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
1259{ 1278{
1260 const char *chars = PERF_IP_FLAG_CHARS; 1279 const char *chars = PERF_IP_FLAG_CHARS;
@@ -1264,11 +1283,20 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
1264 char str[33]; 1283 char str[33];
1265 int i, pos = 0; 1284 int i, pos = 0;
1266 1285
1267 for (i = 0; sample_flags[i].name ; i++) { 1286 name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX);
1268 if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) { 1287 if (name)
1269 name = sample_flags[i].name; 1288 return fprintf(fp, " %-15s%4s ", name, in_tx ? "(x)" : "");
1270 break; 1289
1271 } 1290 if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
1291 name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN));
1292 if (name)
1293 return fprintf(fp, " tr strt %-7s%4s ", name, in_tx ? "(x)" : "");
1294 }
1295
1296 if (flags & PERF_IP_FLAG_TRACE_END) {
1297 name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END));
1298 if (name)
1299 return fprintf(fp, " tr end %-7s%4s ", name, in_tx ? "(x)" : "");
1272 } 1300 }
1273 1301
1274 for (i = 0; i < n; i++, flags >>= 1) { 1302 for (i = 0; i < n; i++, flags >>= 1) {
@@ -1281,10 +1309,7 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
1281 } 1309 }
1282 str[pos] = 0; 1310 str[pos] = 0;
1283 1311
1284 if (name) 1312 return fprintf(fp, " %-19s ", str);
1285 return fprintf(fp, " %-7s%4s ", name, in_tx ? "(x)" : "");
1286
1287 return fprintf(fp, " %-11s ", str);
1288} 1313}
1289 1314
1290struct printer_data { 1315struct printer_data {
@@ -1544,7 +1569,8 @@ struct metric_ctx {
1544 FILE *fp; 1569 FILE *fp;
1545}; 1570};
1546 1571
1547static void script_print_metric(void *ctx, const char *color, 1572static void script_print_metric(struct perf_stat_config *config __maybe_unused,
1573 void *ctx, const char *color,
1548 const char *fmt, 1574 const char *fmt,
1549 const char *unit, double val) 1575 const char *unit, double val)
1550{ 1576{
@@ -1562,7 +1588,8 @@ static void script_print_metric(void *ctx, const char *color,
1562 fprintf(mctx->fp, " %s\n", unit); 1588 fprintf(mctx->fp, " %s\n", unit);
1563} 1589}
1564 1590
1565static void script_new_line(void *ctx) 1591static void script_new_line(struct perf_stat_config *config __maybe_unused,
1592 void *ctx)
1566{ 1593{
1567 struct metric_ctx *mctx = ctx; 1594 struct metric_ctx *mctx = ctx;
1568 1595
@@ -1608,7 +1635,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
1608 evsel_script(evsel)->val = val; 1635 evsel_script(evsel)->val = val;
1609 if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) { 1636 if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
1610 for_each_group_member (ev2, evsel->leader) { 1637 for_each_group_member (ev2, evsel->leader) {
1611 perf_stat__print_shadow_stats(ev2, 1638 perf_stat__print_shadow_stats(&stat_config, ev2,
1612 evsel_script(ev2)->val, 1639 evsel_script(ev2)->val,
1613 sample->cpu, 1640 sample->cpu,
1614 &ctx, 1641 &ctx,
@@ -2489,6 +2516,8 @@ parse:
2489 output[j].fields &= ~all_output_options[i].field; 2516 output[j].fields &= ~all_output_options[i].field;
2490 else 2517 else
2491 output[j].fields |= all_output_options[i].field; 2518 output[j].fields |= all_output_options[i].field;
2519 output[j].user_set = true;
2520 output[j].wildcard_set = true;
2492 } 2521 }
2493 } 2522 }
2494 } else { 2523 } else {
@@ -2499,7 +2528,8 @@ parse:
2499 rc = -EINVAL; 2528 rc = -EINVAL;
2500 goto out; 2529 goto out;
2501 } 2530 }
2502 output[type].fields |= all_output_options[i].field; 2531 output[type].user_set = true;
2532 output[type].wildcard_set = true;
2503 } 2533 }
2504 } 2534 }
2505 2535
@@ -2963,9 +2993,8 @@ static void script__setup_sample_type(struct perf_script *script)
2963 } 2993 }
2964} 2994}
2965 2995
2966static int process_stat_round_event(struct perf_tool *tool __maybe_unused, 2996static int process_stat_round_event(struct perf_session *session,
2967 union perf_event *event, 2997 union perf_event *event)
2968 struct perf_session *session)
2969{ 2998{
2970 struct stat_round_event *round = &event->stat_round; 2999 struct stat_round_event *round = &event->stat_round;
2971 struct perf_evsel *counter; 3000 struct perf_evsel *counter;
@@ -2979,9 +3008,8 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2979 return 0; 3008 return 0;
2980} 3009}
2981 3010
2982static int process_stat_config_event(struct perf_tool *tool __maybe_unused, 3011static int process_stat_config_event(struct perf_session *session __maybe_unused,
2983 union perf_event *event, 3012 union perf_event *event)
2984 struct perf_session *session __maybe_unused)
2985{ 3013{
2986 perf_event__read_stat_config(&stat_config, &event->stat_config); 3014 perf_event__read_stat_config(&stat_config, &event->stat_config);
2987 return 0; 3015 return 0;
@@ -3007,10 +3035,10 @@ static int set_maps(struct perf_script *script)
3007} 3035}
3008 3036
3009static 3037static
3010int process_thread_map_event(struct perf_tool *tool, 3038int process_thread_map_event(struct perf_session *session,
3011 union perf_event *event, 3039 union perf_event *event)
3012 struct perf_session *session __maybe_unused)
3013{ 3040{
3041 struct perf_tool *tool = session->tool;
3014 struct perf_script *script = container_of(tool, struct perf_script, tool); 3042 struct perf_script *script = container_of(tool, struct perf_script, tool);
3015 3043
3016 if (script->threads) { 3044 if (script->threads) {
@@ -3026,10 +3054,10 @@ int process_thread_map_event(struct perf_tool *tool,
3026} 3054}
3027 3055
3028static 3056static
3029int process_cpu_map_event(struct perf_tool *tool __maybe_unused, 3057int process_cpu_map_event(struct perf_session *session,
3030 union perf_event *event, 3058 union perf_event *event)
3031 struct perf_session *session __maybe_unused)
3032{ 3059{
3060 struct perf_tool *tool = session->tool;
3033 struct perf_script *script = container_of(tool, struct perf_script, tool); 3061 struct perf_script *script = container_of(tool, struct perf_script, tool);
3034 3062
3035 if (script->cpus) { 3063 if (script->cpus) {
@@ -3044,21 +3072,21 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
3044 return set_maps(script); 3072 return set_maps(script);
3045} 3073}
3046 3074
3047static int process_feature_event(struct perf_tool *tool, 3075static int process_feature_event(struct perf_session *session,
3048 union perf_event *event, 3076 union perf_event *event)
3049 struct perf_session *session)
3050{ 3077{
3051 if (event->feat.feat_id < HEADER_LAST_FEATURE) 3078 if (event->feat.feat_id < HEADER_LAST_FEATURE)
3052 return perf_event__process_feature(tool, event, session); 3079 return perf_event__process_feature(session, event);
3053 return 0; 3080 return 0;
3054} 3081}
3055 3082
3056#ifdef HAVE_AUXTRACE_SUPPORT 3083#ifdef HAVE_AUXTRACE_SUPPORT
3057static int perf_script__process_auxtrace_info(struct perf_tool *tool, 3084static int perf_script__process_auxtrace_info(struct perf_session *session,
3058 union perf_event *event, 3085 union perf_event *event)
3059 struct perf_session *session)
3060{ 3086{
3061 int ret = perf_event__process_auxtrace_info(tool, event, session); 3087 struct perf_tool *tool = session->tool;
3088
3089 int ret = perf_event__process_auxtrace_info(session, event);
3062 3090
3063 if (ret == 0) { 3091 if (ret == 0) {
3064 struct perf_script *script = container_of(tool, struct perf_script, tool); 3092 struct perf_script *script = container_of(tool, struct perf_script, tool);
@@ -3193,7 +3221,7 @@ int cmd_script(int argc, const char **argv)
3193 OPT_BOOLEAN(0, "ns", &nanosecs, 3221 OPT_BOOLEAN(0, "ns", &nanosecs,
3194 "Use 9 decimal places when displaying time"), 3222 "Use 9 decimal places when displaying time"),
3195 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 3223 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
3196 "Instruction Tracing options", 3224 "Instruction Tracing options\n" ITRACE_HELP,
3197 itrace_parse_synth_opts), 3225 itrace_parse_synth_opts),
3198 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, 3226 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
3199 "Show full source file name path for source lines"), 3227 "Show full source file name path for source lines"),
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d097b5b47eb8..b86aba1c8028 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -88,8 +88,6 @@
88#include "sane_ctype.h" 88#include "sane_ctype.h"
89 89
90#define DEFAULT_SEPARATOR " " 90#define DEFAULT_SEPARATOR " "
91#define CNTR_NOT_SUPPORTED "<not supported>"
92#define CNTR_NOT_COUNTED "<not counted>"
93#define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi" 91#define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi"
94 92
95static void print_counters(struct timespec *ts, int argc, const char **argv); 93static void print_counters(struct timespec *ts, int argc, const char **argv);
@@ -137,54 +135,30 @@ static const char *smi_cost_attrs = {
137 135
138static struct perf_evlist *evsel_list; 136static struct perf_evlist *evsel_list;
139 137
140static struct rblist metric_events;
141
142static struct target target = { 138static struct target target = {
143 .uid = UINT_MAX, 139 .uid = UINT_MAX,
144}; 140};
145 141
146typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
147
148#define METRIC_ONLY_LEN 20 142#define METRIC_ONLY_LEN 20
149 143
150static int run_count = 1;
151static bool no_inherit = false;
152static volatile pid_t child_pid = -1; 144static volatile pid_t child_pid = -1;
153static bool null_run = false;
154static int detailed_run = 0; 145static int detailed_run = 0;
155static bool transaction_run; 146static bool transaction_run;
156static bool topdown_run = false; 147static bool topdown_run = false;
157static bool smi_cost = false; 148static bool smi_cost = false;
158static bool smi_reset = false; 149static bool smi_reset = false;
159static bool big_num = true;
160static int big_num_opt = -1; 150static int big_num_opt = -1;
161static const char *csv_sep = NULL;
162static bool csv_output = false;
163static bool group = false; 151static bool group = false;
164static const char *pre_cmd = NULL; 152static const char *pre_cmd = NULL;
165static const char *post_cmd = NULL; 153static const char *post_cmd = NULL;
166static bool sync_run = false; 154static bool sync_run = false;
167static unsigned int initial_delay = 0;
168static unsigned int unit_width = 4; /* strlen("unit") */
169static bool forever = false; 155static bool forever = false;
170static bool metric_only = false;
171static bool force_metric_only = false; 156static bool force_metric_only = false;
172static bool no_merge = false;
173static bool walltime_run_table = false;
174static struct timespec ref_time; 157static struct timespec ref_time;
175static struct cpu_map *aggr_map;
176static aggr_get_id_t aggr_get_id;
177static bool append_file; 158static bool append_file;
178static bool interval_count; 159static bool interval_count;
179static bool interval_clear;
180static const char *output_name; 160static const char *output_name;
181static int output_fd; 161static int output_fd;
182static int print_free_counters_hint;
183static int print_mixed_hw_group_error;
184static u64 *walltime_run;
185static bool ru_display = false;
186static struct rusage ru_data;
187static unsigned int metric_only_len = METRIC_ONLY_LEN;
188 162
189struct perf_stat { 163struct perf_stat {
190 bool record; 164 bool record;
@@ -204,15 +178,15 @@ static struct perf_stat perf_stat;
204static volatile int done = 0; 178static volatile int done = 0;
205 179
206static struct perf_stat_config stat_config = { 180static struct perf_stat_config stat_config = {
207 .aggr_mode = AGGR_GLOBAL, 181 .aggr_mode = AGGR_GLOBAL,
208 .scale = true, 182 .scale = true,
183 .unit_width = 4, /* strlen("unit") */
184 .run_count = 1,
185 .metric_only_len = METRIC_ONLY_LEN,
186 .walltime_nsecs_stats = &walltime_nsecs_stats,
187 .big_num = true,
209}; 188};
210 189
211static bool is_duration_time(struct perf_evsel *evsel)
212{
213 return !strcmp(evsel->name, "duration_time");
214}
215
216static inline void diff_timespec(struct timespec *r, struct timespec *a, 190static inline void diff_timespec(struct timespec *r, struct timespec *a,
217 struct timespec *b) 191 struct timespec *b)
218{ 192{
@@ -236,66 +210,6 @@ static void perf_stat__reset_stats(void)
236 perf_stat__reset_shadow_per_stat(&stat_config.stats[i]); 210 perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
237} 211}
238 212
239static int create_perf_stat_counter(struct perf_evsel *evsel)
240{
241 struct perf_event_attr *attr = &evsel->attr;
242 struct perf_evsel *leader = evsel->leader;
243
244 if (stat_config.scale) {
245 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
246 PERF_FORMAT_TOTAL_TIME_RUNNING;
247 }
248
249 /*
250 * The event is part of non trivial group, let's enable
251 * the group read (for leader) and ID retrieval for all
252 * members.
253 */
254 if (leader->nr_members > 1)
255 attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
256
257 attr->inherit = !no_inherit;
258
259 /*
260 * Some events get initialized with sample_(period/type) set,
261 * like tracepoints. Clear it up for counting.
262 */
263 attr->sample_period = 0;
264
265 /*
266 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
267 * while avoiding that older tools show confusing messages.
268 *
269 * However for pipe sessions we need to keep it zero,
270 * because script's perf_evsel__check_attr is triggered
271 * by attr->sample_type != 0, and we can't run it on
272 * stat sessions.
273 */
274 if (!(STAT_RECORD && perf_stat.data.is_pipe))
275 attr->sample_type = PERF_SAMPLE_IDENTIFIER;
276
277 /*
278 * Disabling all counters initially, they will be enabled
279 * either manually by us or by kernel via enable_on_exec
280 * set later.
281 */
282 if (perf_evsel__is_group_leader(evsel)) {
283 attr->disabled = 1;
284
285 /*
286 * In case of initial_delay we enable tracee
287 * events manually.
288 */
289 if (target__none(&target) && !initial_delay)
290 attr->enable_on_exec = 1;
291 }
292
293 if (target__has_cpu(&target) && !target__has_per_thread(&target))
294 return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
295
296 return perf_evsel__open_per_thread(evsel, evsel_list->threads);
297}
298
299static int process_synthesized_event(struct perf_tool *tool __maybe_unused, 213static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
300 union perf_event *event, 214 union perf_event *event,
301 struct perf_sample *sample __maybe_unused, 215 struct perf_sample *sample __maybe_unused,
@@ -428,15 +342,15 @@ static void process_interval(void)
428 342
429static void enable_counters(void) 343static void enable_counters(void)
430{ 344{
431 if (initial_delay) 345 if (stat_config.initial_delay)
432 usleep(initial_delay * USEC_PER_MSEC); 346 usleep(stat_config.initial_delay * USEC_PER_MSEC);
433 347
434 /* 348 /*
435 * We need to enable counters only if: 349 * We need to enable counters only if:
436 * - we don't have tracee (attaching to task or cpu) 350 * - we don't have tracee (attaching to task or cpu)
437 * - we have initial delay configured 351 * - we have initial delay configured
438 */ 352 */
439 if (!target__none(&target) || initial_delay) 353 if (!target__none(&target) || stat_config.initial_delay)
440 perf_evlist__enable(evsel_list); 354 perf_evlist__enable(evsel_list);
441} 355}
442 356
@@ -464,80 +378,6 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
464 workload_exec_errno = info->si_value.sival_int; 378 workload_exec_errno = info->si_value.sival_int;
465} 379}
466 380
467static int perf_stat_synthesize_config(bool is_pipe)
468{
469 int err;
470
471 if (is_pipe) {
472 err = perf_event__synthesize_attrs(NULL, perf_stat.session,
473 process_synthesized_event);
474 if (err < 0) {
475 pr_err("Couldn't synthesize attrs.\n");
476 return err;
477 }
478 }
479
480 err = perf_event__synthesize_extra_attr(NULL,
481 evsel_list,
482 process_synthesized_event,
483 is_pipe);
484
485 err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
486 process_synthesized_event,
487 NULL);
488 if (err < 0) {
489 pr_err("Couldn't synthesize thread map.\n");
490 return err;
491 }
492
493 err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
494 process_synthesized_event, NULL);
495 if (err < 0) {
496 pr_err("Couldn't synthesize thread map.\n");
497 return err;
498 }
499
500 err = perf_event__synthesize_stat_config(NULL, &stat_config,
501 process_synthesized_event, NULL);
502 if (err < 0) {
503 pr_err("Couldn't synthesize config.\n");
504 return err;
505 }
506
507 return 0;
508}
509
510#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
511
512static int __store_counter_ids(struct perf_evsel *counter)
513{
514 int cpu, thread;
515
516 for (cpu = 0; cpu < xyarray__max_x(counter->fd); cpu++) {
517 for (thread = 0; thread < xyarray__max_y(counter->fd);
518 thread++) {
519 int fd = FD(counter, cpu, thread);
520
521 if (perf_evlist__id_add_fd(evsel_list, counter,
522 cpu, thread, fd) < 0)
523 return -1;
524 }
525 }
526
527 return 0;
528}
529
530static int store_counter_ids(struct perf_evsel *counter)
531{
532 struct cpu_map *cpus = counter->cpus;
533 struct thread_map *threads = counter->threads;
534
535 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
536 return -ENOMEM;
537
538 return __store_counter_ids(counter);
539}
540
541static bool perf_evsel__should_store_id(struct perf_evsel *counter) 381static bool perf_evsel__should_store_id(struct perf_evsel *counter)
542{ 382{
543 return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID; 383 return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
@@ -609,7 +449,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
609 449
610 evlist__for_each_entry(evsel_list, counter) { 450 evlist__for_each_entry(evsel_list, counter) {
611try_again: 451try_again:
612 if (create_perf_stat_counter(counter) < 0) { 452 if (create_perf_stat_counter(counter, &stat_config, &target) < 0) {
613 453
614 /* Weak group failed. Reset the group. */ 454 /* Weak group failed. Reset the group. */
615 if ((errno == EINVAL || errno == EBADF) && 455 if ((errno == EINVAL || errno == EBADF) &&
@@ -664,11 +504,11 @@ try_again:
664 counter->supported = true; 504 counter->supported = true;
665 505
666 l = strlen(counter->unit); 506 l = strlen(counter->unit);
667 if (l > unit_width) 507 if (l > stat_config.unit_width)
668 unit_width = l; 508 stat_config.unit_width = l;
669 509
670 if (perf_evsel__should_store_id(counter) && 510 if (perf_evsel__should_store_id(counter) &&
671 store_counter_ids(counter)) 511 perf_evsel__store_ids(counter, evsel_list))
672 return -1; 512 return -1;
673 } 513 }
674 514
@@ -699,7 +539,8 @@ try_again:
699 if (err < 0) 539 if (err < 0)
700 return err; 540 return err;
701 541
702 err = perf_stat_synthesize_config(is_pipe); 542 err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list,
543 process_synthesized_event, is_pipe);
703 if (err < 0) 544 if (err < 0)
704 return err; 545 return err;
705 } 546 }
@@ -724,7 +565,7 @@ try_again:
724 break; 565 break;
725 } 566 }
726 } 567 }
727 wait4(child_pid, &status, 0, &ru_data); 568 wait4(child_pid, &status, 0, &stat_config.ru_data);
728 569
729 if (workload_exec_errno) { 570 if (workload_exec_errno) {
730 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 571 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -752,8 +593,8 @@ try_again:
752 593
753 t1 = rdclock(); 594 t1 = rdclock();
754 595
755 if (walltime_run_table) 596 if (stat_config.walltime_run_table)
756 walltime_run[run_idx] = t1 - t0; 597 stat_config.walltime_run[run_idx] = t1 - t0;
757 598
758 update_stats(&walltime_nsecs_stats, t1 - t0); 599 update_stats(&walltime_nsecs_stats, t1 - t0);
759 600
@@ -795,1105 +636,14 @@ static int run_perf_stat(int argc, const char **argv, int run_idx)
795 return ret; 636 return ret;
796} 637}
797 638
798static void print_running(u64 run, u64 ena)
799{
800 if (csv_output) {
801 fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f",
802 csv_sep,
803 run,
804 csv_sep,
805 ena ? 100.0 * run / ena : 100.0);
806 } else if (run != ena) {
807 fprintf(stat_config.output, " (%.2f%%)", 100.0 * run / ena);
808 }
809}
810
811static void print_noise_pct(double total, double avg)
812{
813 double pct = rel_stddev_stats(total, avg);
814
815 if (csv_output)
816 fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct);
817 else if (pct)
818 fprintf(stat_config.output, " ( +-%6.2f%% )", pct);
819}
820
821static void print_noise(struct perf_evsel *evsel, double avg)
822{
823 struct perf_stat_evsel *ps;
824
825 if (run_count == 1)
826 return;
827
828 ps = evsel->stats;
829 print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
830}
831
832static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
833{
834 switch (stat_config.aggr_mode) {
835 case AGGR_CORE:
836 fprintf(stat_config.output, "S%d-C%*d%s%*d%s",
837 cpu_map__id_to_socket(id),
838 csv_output ? 0 : -8,
839 cpu_map__id_to_cpu(id),
840 csv_sep,
841 csv_output ? 0 : 4,
842 nr,
843 csv_sep);
844 break;
845 case AGGR_SOCKET:
846 fprintf(stat_config.output, "S%*d%s%*d%s",
847 csv_output ? 0 : -5,
848 id,
849 csv_sep,
850 csv_output ? 0 : 4,
851 nr,
852 csv_sep);
853 break;
854 case AGGR_NONE:
855 fprintf(stat_config.output, "CPU%*d%s",
856 csv_output ? 0 : -4,
857 perf_evsel__cpus(evsel)->map[id], csv_sep);
858 break;
859 case AGGR_THREAD:
860 fprintf(stat_config.output, "%*s-%*d%s",
861 csv_output ? 0 : 16,
862 thread_map__comm(evsel->threads, id),
863 csv_output ? 0 : -8,
864 thread_map__pid(evsel->threads, id),
865 csv_sep);
866 break;
867 case AGGR_GLOBAL:
868 case AGGR_UNSET:
869 default:
870 break;
871 }
872}
873
874struct outstate {
875 FILE *fh;
876 bool newline;
877 const char *prefix;
878 int nfields;
879 int id, nr;
880 struct perf_evsel *evsel;
881};
882
883#define METRIC_LEN 35
884
885static void new_line_std(void *ctx)
886{
887 struct outstate *os = ctx;
888
889 os->newline = true;
890}
891
892static void do_new_line_std(struct outstate *os)
893{
894 fputc('\n', os->fh);
895 fputs(os->prefix, os->fh);
896 aggr_printout(os->evsel, os->id, os->nr);
897 if (stat_config.aggr_mode == AGGR_NONE)
898 fprintf(os->fh, " ");
899 fprintf(os->fh, " ");
900}
901
902static void print_metric_std(void *ctx, const char *color, const char *fmt,
903 const char *unit, double val)
904{
905 struct outstate *os = ctx;
906 FILE *out = os->fh;
907 int n;
908 bool newline = os->newline;
909
910 os->newline = false;
911
912 if (unit == NULL || fmt == NULL) {
913 fprintf(out, "%-*s", METRIC_LEN, "");
914 return;
915 }
916
917 if (newline)
918 do_new_line_std(os);
919
920 n = fprintf(out, " # ");
921 if (color)
922 n += color_fprintf(out, color, fmt, val);
923 else
924 n += fprintf(out, fmt, val);
925 fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
926}
927
928static void new_line_csv(void *ctx)
929{
930 struct outstate *os = ctx;
931 int i;
932
933 fputc('\n', os->fh);
934 if (os->prefix)
935 fprintf(os->fh, "%s%s", os->prefix, csv_sep);
936 aggr_printout(os->evsel, os->id, os->nr);
937 for (i = 0; i < os->nfields; i++)
938 fputs(csv_sep, os->fh);
939}
940
941static void print_metric_csv(void *ctx,
942 const char *color __maybe_unused,
943 const char *fmt, const char *unit, double val)
944{
945 struct outstate *os = ctx;
946 FILE *out = os->fh;
947 char buf[64], *vals, *ends;
948
949 if (unit == NULL || fmt == NULL) {
950 fprintf(out, "%s%s", csv_sep, csv_sep);
951 return;
952 }
953 snprintf(buf, sizeof(buf), fmt, val);
954 ends = vals = ltrim(buf);
955 while (isdigit(*ends) || *ends == '.')
956 ends++;
957 *ends = 0;
958 while (isspace(*unit))
959 unit++;
960 fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit);
961}
962
963/* Filter out some columns that don't work well in metrics only mode */
964
965static bool valid_only_metric(const char *unit)
966{
967 if (!unit)
968 return false;
969 if (strstr(unit, "/sec") ||
970 strstr(unit, "hz") ||
971 strstr(unit, "Hz") ||
972 strstr(unit, "CPUs utilized"))
973 return false;
974 return true;
975}
976
977static const char *fixunit(char *buf, struct perf_evsel *evsel,
978 const char *unit)
979{
980 if (!strncmp(unit, "of all", 6)) {
981 snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
982 unit);
983 return buf;
984 }
985 return unit;
986}
987
988static void print_metric_only(void *ctx, const char *color, const char *fmt,
989 const char *unit, double val)
990{
991 struct outstate *os = ctx;
992 FILE *out = os->fh;
993 char buf[1024], str[1024];
994 unsigned mlen = metric_only_len;
995
996 if (!valid_only_metric(unit))
997 return;
998 unit = fixunit(buf, os->evsel, unit);
999 if (mlen < strlen(unit))
1000 mlen = strlen(unit) + 1;
1001
1002 if (color)
1003 mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
1004
1005 color_snprintf(str, sizeof(str), color ?: "", fmt, val);
1006 fprintf(out, "%*s ", mlen, str);
1007}
1008
1009static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
1010 const char *fmt,
1011 const char *unit, double val)
1012{
1013 struct outstate *os = ctx;
1014 FILE *out = os->fh;
1015 char buf[64], *vals, *ends;
1016 char tbuf[1024];
1017
1018 if (!valid_only_metric(unit))
1019 return;
1020 unit = fixunit(tbuf, os->evsel, unit);
1021 snprintf(buf, sizeof buf, fmt, val);
1022 ends = vals = ltrim(buf);
1023 while (isdigit(*ends) || *ends == '.')
1024 ends++;
1025 *ends = 0;
1026 fprintf(out, "%s%s", vals, csv_sep);
1027}
1028
1029static void new_line_metric(void *ctx __maybe_unused)
1030{
1031}
1032
1033static void print_metric_header(void *ctx, const char *color __maybe_unused,
1034 const char *fmt __maybe_unused,
1035 const char *unit, double val __maybe_unused)
1036{
1037 struct outstate *os = ctx;
1038 char tbuf[1024];
1039
1040 if (!valid_only_metric(unit))
1041 return;
1042 unit = fixunit(tbuf, os->evsel, unit);
1043 if (csv_output)
1044 fprintf(os->fh, "%s%s", unit, csv_sep);
1045 else
1046 fprintf(os->fh, "%*s ", metric_only_len, unit);
1047}
1048
1049static int first_shadow_cpu(struct perf_evsel *evsel, int id)
1050{
1051 int i;
1052
1053 if (!aggr_get_id)
1054 return 0;
1055
1056 if (stat_config.aggr_mode == AGGR_NONE)
1057 return id;
1058
1059 if (stat_config.aggr_mode == AGGR_GLOBAL)
1060 return 0;
1061
1062 for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
1063 int cpu2 = perf_evsel__cpus(evsel)->map[i];
1064
1065 if (aggr_get_id(evsel_list->cpus, cpu2) == id)
1066 return cpu2;
1067 }
1068 return 0;
1069}
1070
1071static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1072{
1073 FILE *output = stat_config.output;
1074 double sc = evsel->scale;
1075 const char *fmt;
1076
1077 if (csv_output) {
1078 fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
1079 } else {
1080 if (big_num)
1081 fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
1082 else
1083 fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
1084 }
1085
1086 aggr_printout(evsel, id, nr);
1087
1088 fprintf(output, fmt, avg, csv_sep);
1089
1090 if (evsel->unit)
1091 fprintf(output, "%-*s%s",
1092 csv_output ? 0 : unit_width,
1093 evsel->unit, csv_sep);
1094
1095 fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));
1096
1097 if (evsel->cgrp)
1098 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
1099}
1100
1101static bool is_mixed_hw_group(struct perf_evsel *counter)
1102{
1103 struct perf_evlist *evlist = counter->evlist;
1104 u32 pmu_type = counter->attr.type;
1105 struct perf_evsel *pos;
1106
1107 if (counter->nr_members < 2)
1108 return false;
1109
1110 evlist__for_each_entry(evlist, pos) {
1111 /* software events can be part of any hardware group */
1112 if (pos->attr.type == PERF_TYPE_SOFTWARE)
1113 continue;
1114 if (pmu_type == PERF_TYPE_SOFTWARE) {
1115 pmu_type = pos->attr.type;
1116 continue;
1117 }
1118 if (pmu_type != pos->attr.type)
1119 return true;
1120 }
1121
1122 return false;
1123}
1124
1125static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1126 char *prefix, u64 run, u64 ena, double noise,
1127 struct runtime_stat *st)
1128{
1129 struct perf_stat_output_ctx out;
1130 struct outstate os = {
1131 .fh = stat_config.output,
1132 .prefix = prefix ? prefix : "",
1133 .id = id,
1134 .nr = nr,
1135 .evsel = counter,
1136 };
1137 print_metric_t pm = print_metric_std;
1138 void (*nl)(void *);
1139
1140 if (metric_only) {
1141 nl = new_line_metric;
1142 if (csv_output)
1143 pm = print_metric_only_csv;
1144 else
1145 pm = print_metric_only;
1146 } else
1147 nl = new_line_std;
1148
1149 if (csv_output && !metric_only) {
1150 static int aggr_fields[] = {
1151 [AGGR_GLOBAL] = 0,
1152 [AGGR_THREAD] = 1,
1153 [AGGR_NONE] = 1,
1154 [AGGR_SOCKET] = 2,
1155 [AGGR_CORE] = 2,
1156 };
1157
1158 pm = print_metric_csv;
1159 nl = new_line_csv;
1160 os.nfields = 3;
1161 os.nfields += aggr_fields[stat_config.aggr_mode];
1162 if (counter->cgrp)
1163 os.nfields++;
1164 }
1165 if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
1166 if (metric_only) {
1167 pm(&os, NULL, "", "", 0);
1168 return;
1169 }
1170 aggr_printout(counter, id, nr);
1171
1172 fprintf(stat_config.output, "%*s%s",
1173 csv_output ? 0 : 18,
1174 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
1175 csv_sep);
1176
1177 if (counter->supported) {
1178 print_free_counters_hint = 1;
1179 if (is_mixed_hw_group(counter))
1180 print_mixed_hw_group_error = 1;
1181 }
1182
1183 fprintf(stat_config.output, "%-*s%s",
1184 csv_output ? 0 : unit_width,
1185 counter->unit, csv_sep);
1186
1187 fprintf(stat_config.output, "%*s",
1188 csv_output ? 0 : -25,
1189 perf_evsel__name(counter));
1190
1191 if (counter->cgrp)
1192 fprintf(stat_config.output, "%s%s",
1193 csv_sep, counter->cgrp->name);
1194
1195 if (!csv_output)
1196 pm(&os, NULL, NULL, "", 0);
1197 print_noise(counter, noise);
1198 print_running(run, ena);
1199 if (csv_output)
1200 pm(&os, NULL, NULL, "", 0);
1201 return;
1202 }
1203
1204 if (!metric_only)
1205 abs_printout(id, nr, counter, uval);
1206
1207 out.print_metric = pm;
1208 out.new_line = nl;
1209 out.ctx = &os;
1210 out.force_header = false;
1211
1212 if (csv_output && !metric_only) {
1213 print_noise(counter, noise);
1214 print_running(run, ena);
1215 }
1216
1217 perf_stat__print_shadow_stats(counter, uval,
1218 first_shadow_cpu(counter, id),
1219 &out, &metric_events, st);
1220 if (!csv_output && !metric_only) {
1221 print_noise(counter, noise);
1222 print_running(run, ena);
1223 }
1224}
1225
1226static void aggr_update_shadow(void)
1227{
1228 int cpu, s2, id, s;
1229 u64 val;
1230 struct perf_evsel *counter;
1231
1232 for (s = 0; s < aggr_map->nr; s++) {
1233 id = aggr_map->map[s];
1234 evlist__for_each_entry(evsel_list, counter) {
1235 val = 0;
1236 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1237 s2 = aggr_get_id(evsel_list->cpus, cpu);
1238 if (s2 != id)
1239 continue;
1240 val += perf_counts(counter->counts, cpu, 0)->val;
1241 }
1242 perf_stat__update_shadow_stats(counter, val,
1243 first_shadow_cpu(counter, id),
1244 &rt_stat);
1245 }
1246 }
1247}
1248
1249static void uniquify_event_name(struct perf_evsel *counter)
1250{
1251 char *new_name;
1252 char *config;
1253
1254 if (counter->uniquified_name ||
1255 !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
1256 strlen(counter->pmu_name)))
1257 return;
1258
1259 config = strchr(counter->name, '/');
1260 if (config) {
1261 if (asprintf(&new_name,
1262 "%s%s", counter->pmu_name, config) > 0) {
1263 free(counter->name);
1264 counter->name = new_name;
1265 }
1266 } else {
1267 if (asprintf(&new_name,
1268 "%s [%s]", counter->name, counter->pmu_name) > 0) {
1269 free(counter->name);
1270 counter->name = new_name;
1271 }
1272 }
1273
1274 counter->uniquified_name = true;
1275}
1276
1277static void collect_all_aliases(struct perf_evsel *counter,
1278 void (*cb)(struct perf_evsel *counter, void *data,
1279 bool first),
1280 void *data)
1281{
1282 struct perf_evsel *alias;
1283
1284 alias = list_prepare_entry(counter, &(evsel_list->entries), node);
1285 list_for_each_entry_continue (alias, &evsel_list->entries, node) {
1286 if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
1287 alias->scale != counter->scale ||
1288 alias->cgrp != counter->cgrp ||
1289 strcmp(alias->unit, counter->unit) ||
1290 perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
1291 break;
1292 alias->merged_stat = true;
1293 cb(alias, data, false);
1294 }
1295}
1296
1297static bool collect_data(struct perf_evsel *counter,
1298 void (*cb)(struct perf_evsel *counter, void *data,
1299 bool first),
1300 void *data)
1301{
1302 if (counter->merged_stat)
1303 return false;
1304 cb(counter, data, true);
1305 if (no_merge)
1306 uniquify_event_name(counter);
1307 else if (counter->auto_merge_stats)
1308 collect_all_aliases(counter, cb, data);
1309 return true;
1310}
1311
1312struct aggr_data {
1313 u64 ena, run, val;
1314 int id;
1315 int nr;
1316 int cpu;
1317};
1318
1319static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
1320{
1321 struct aggr_data *ad = data;
1322 int cpu, s2;
1323
1324 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1325 struct perf_counts_values *counts;
1326
1327 s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
1328 if (s2 != ad->id)
1329 continue;
1330 if (first)
1331 ad->nr++;
1332 counts = perf_counts(counter->counts, cpu, 0);
1333 /*
1334 * When any result is bad, make them all to give
1335 * consistent output in interval mode.
1336 */
1337 if (counts->ena == 0 || counts->run == 0 ||
1338 counter->counts->scaled == -1) {
1339 ad->ena = 0;
1340 ad->run = 0;
1341 break;
1342 }
1343 ad->val += counts->val;
1344 ad->ena += counts->ena;
1345 ad->run += counts->run;
1346 }
1347}
1348
1349static void print_aggr(char *prefix)
1350{
1351 FILE *output = stat_config.output;
1352 struct perf_evsel *counter;
1353 int s, id, nr;
1354 double uval;
1355 u64 ena, run, val;
1356 bool first;
1357
1358 if (!(aggr_map || aggr_get_id))
1359 return;
1360
1361 aggr_update_shadow();
1362
1363 /*
1364 * With metric_only everything is on a single line.
1365 * Without each counter has its own line.
1366 */
1367 for (s = 0; s < aggr_map->nr; s++) {
1368 struct aggr_data ad;
1369 if (prefix && metric_only)
1370 fprintf(output, "%s", prefix);
1371
1372 ad.id = id = aggr_map->map[s];
1373 first = true;
1374 evlist__for_each_entry(evsel_list, counter) {
1375 if (is_duration_time(counter))
1376 continue;
1377
1378 ad.val = ad.ena = ad.run = 0;
1379 ad.nr = 0;
1380 if (!collect_data(counter, aggr_cb, &ad))
1381 continue;
1382 nr = ad.nr;
1383 ena = ad.ena;
1384 run = ad.run;
1385 val = ad.val;
1386 if (first && metric_only) {
1387 first = false;
1388 aggr_printout(counter, id, nr);
1389 }
1390 if (prefix && !metric_only)
1391 fprintf(output, "%s", prefix);
1392
1393 uval = val * counter->scale;
1394 printout(id, nr, counter, uval, prefix, run, ena, 1.0,
1395 &rt_stat);
1396 if (!metric_only)
1397 fputc('\n', output);
1398 }
1399 if (metric_only)
1400 fputc('\n', output);
1401 }
1402}
1403
1404static int cmp_val(const void *a, const void *b)
1405{
1406 return ((struct perf_aggr_thread_value *)b)->val -
1407 ((struct perf_aggr_thread_value *)a)->val;
1408}
1409
1410static struct perf_aggr_thread_value *sort_aggr_thread(
1411 struct perf_evsel *counter,
1412 int nthreads, int ncpus,
1413 int *ret)
1414{
1415 int cpu, thread, i = 0;
1416 double uval;
1417 struct perf_aggr_thread_value *buf;
1418
1419 buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
1420 if (!buf)
1421 return NULL;
1422
1423 for (thread = 0; thread < nthreads; thread++) {
1424 u64 ena = 0, run = 0, val = 0;
1425
1426 for (cpu = 0; cpu < ncpus; cpu++) {
1427 val += perf_counts(counter->counts, cpu, thread)->val;
1428 ena += perf_counts(counter->counts, cpu, thread)->ena;
1429 run += perf_counts(counter->counts, cpu, thread)->run;
1430 }
1431
1432 uval = val * counter->scale;
1433
1434 /*
1435 * Skip value 0 when enabling --per-thread globally,
1436 * otherwise too many 0 output.
1437 */
1438 if (uval == 0.0 && target__has_per_thread(&target))
1439 continue;
1440
1441 buf[i].counter = counter;
1442 buf[i].id = thread;
1443 buf[i].uval = uval;
1444 buf[i].val = val;
1445 buf[i].run = run;
1446 buf[i].ena = ena;
1447 i++;
1448 }
1449
1450 qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
1451
1452 if (ret)
1453 *ret = i;
1454
1455 return buf;
1456}
1457
1458static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
1459{
1460 FILE *output = stat_config.output;
1461 int nthreads = thread_map__nr(counter->threads);
1462 int ncpus = cpu_map__nr(counter->cpus);
1463 int thread, sorted_threads, id;
1464 struct perf_aggr_thread_value *buf;
1465
1466 buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads);
1467 if (!buf) {
1468 perror("cannot sort aggr thread");
1469 return;
1470 }
1471
1472 for (thread = 0; thread < sorted_threads; thread++) {
1473 if (prefix)
1474 fprintf(output, "%s", prefix);
1475
1476 id = buf[thread].id;
1477 if (stat_config.stats)
1478 printout(id, 0, buf[thread].counter, buf[thread].uval,
1479 prefix, buf[thread].run, buf[thread].ena, 1.0,
1480 &stat_config.stats[id]);
1481 else
1482 printout(id, 0, buf[thread].counter, buf[thread].uval,
1483 prefix, buf[thread].run, buf[thread].ena, 1.0,
1484 &rt_stat);
1485 fputc('\n', output);
1486 }
1487
1488 free(buf);
1489}
1490
1491struct caggr_data {
1492 double avg, avg_enabled, avg_running;
1493};
1494
1495static void counter_aggr_cb(struct perf_evsel *counter, void *data,
1496 bool first __maybe_unused)
1497{
1498 struct caggr_data *cd = data;
1499 struct perf_stat_evsel *ps = counter->stats;
1500
1501 cd->avg += avg_stats(&ps->res_stats[0]);
1502 cd->avg_enabled += avg_stats(&ps->res_stats[1]);
1503 cd->avg_running += avg_stats(&ps->res_stats[2]);
1504}
1505
1506/*
1507 * Print out the results of a single counter:
1508 * aggregated counts in system-wide mode
1509 */
1510static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1511{
1512 FILE *output = stat_config.output;
1513 double uval;
1514 struct caggr_data cd = { .avg = 0.0 };
1515
1516 if (!collect_data(counter, counter_aggr_cb, &cd))
1517 return;
1518
1519 if (prefix && !metric_only)
1520 fprintf(output, "%s", prefix);
1521
1522 uval = cd.avg * counter->scale;
1523 printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
1524 cd.avg, &rt_stat);
1525 if (!metric_only)
1526 fprintf(output, "\n");
1527}
1528
1529static void counter_cb(struct perf_evsel *counter, void *data,
1530 bool first __maybe_unused)
1531{
1532 struct aggr_data *ad = data;
1533
1534 ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
1535 ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
1536 ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
1537}
1538
1539/*
1540 * Print out the results of a single counter:
1541 * does not use aggregated count in system-wide
1542 */
1543static void print_counter(struct perf_evsel *counter, char *prefix)
1544{
1545 FILE *output = stat_config.output;
1546 u64 ena, run, val;
1547 double uval;
1548 int cpu;
1549
1550 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1551 struct aggr_data ad = { .cpu = cpu };
1552
1553 if (!collect_data(counter, counter_cb, &ad))
1554 return;
1555 val = ad.val;
1556 ena = ad.ena;
1557 run = ad.run;
1558
1559 if (prefix)
1560 fprintf(output, "%s", prefix);
1561
1562 uval = val * counter->scale;
1563 printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
1564 &rt_stat);
1565
1566 fputc('\n', output);
1567 }
1568}
1569
1570static void print_no_aggr_metric(char *prefix)
1571{
1572 int cpu;
1573 int nrcpus = 0;
1574 struct perf_evsel *counter;
1575 u64 ena, run, val;
1576 double uval;
1577
1578 nrcpus = evsel_list->cpus->nr;
1579 for (cpu = 0; cpu < nrcpus; cpu++) {
1580 bool first = true;
1581
1582 if (prefix)
1583 fputs(prefix, stat_config.output);
1584 evlist__for_each_entry(evsel_list, counter) {
1585 if (is_duration_time(counter))
1586 continue;
1587 if (first) {
1588 aggr_printout(counter, cpu, 0);
1589 first = false;
1590 }
1591 val = perf_counts(counter->counts, cpu, 0)->val;
1592 ena = perf_counts(counter->counts, cpu, 0)->ena;
1593 run = perf_counts(counter->counts, cpu, 0)->run;
1594
1595 uval = val * counter->scale;
1596 printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
1597 &rt_stat);
1598 }
1599 fputc('\n', stat_config.output);
1600 }
1601}
1602
1603static int aggr_header_lens[] = {
1604 [AGGR_CORE] = 18,
1605 [AGGR_SOCKET] = 12,
1606 [AGGR_NONE] = 6,
1607 [AGGR_THREAD] = 24,
1608 [AGGR_GLOBAL] = 0,
1609};
1610
1611static const char *aggr_header_csv[] = {
1612 [AGGR_CORE] = "core,cpus,",
1613 [AGGR_SOCKET] = "socket,cpus",
1614 [AGGR_NONE] = "cpu,",
1615 [AGGR_THREAD] = "comm-pid,",
1616 [AGGR_GLOBAL] = ""
1617};
1618
1619static void print_metric_headers(const char *prefix, bool no_indent)
1620{
1621 struct perf_stat_output_ctx out;
1622 struct perf_evsel *counter;
1623 struct outstate os = {
1624 .fh = stat_config.output
1625 };
1626
1627 if (prefix)
1628 fprintf(stat_config.output, "%s", prefix);
1629
1630 if (!csv_output && !no_indent)
1631 fprintf(stat_config.output, "%*s",
1632 aggr_header_lens[stat_config.aggr_mode], "");
1633 if (csv_output) {
1634 if (stat_config.interval)
1635 fputs("time,", stat_config.output);
1636 fputs(aggr_header_csv[stat_config.aggr_mode],
1637 stat_config.output);
1638 }
1639
1640 /* Print metrics headers only */
1641 evlist__for_each_entry(evsel_list, counter) {
1642 if (is_duration_time(counter))
1643 continue;
1644 os.evsel = counter;
1645 out.ctx = &os;
1646 out.print_metric = print_metric_header;
1647 out.new_line = new_line_metric;
1648 out.force_header = true;
1649 os.evsel = counter;
1650 perf_stat__print_shadow_stats(counter, 0,
1651 0,
1652 &out,
1653 &metric_events,
1654 &rt_stat);
1655 }
1656 fputc('\n', stat_config.output);
1657}
1658
1659static void print_interval(char *prefix, struct timespec *ts)
1660{
1661 FILE *output = stat_config.output;
1662 static int num_print_interval;
1663
1664 if (interval_clear)
1665 puts(CONSOLE_CLEAR);
1666
1667 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
1668
1669 if ((num_print_interval == 0 && !csv_output) || interval_clear) {
1670 switch (stat_config.aggr_mode) {
1671 case AGGR_SOCKET:
1672 fprintf(output, "# time socket cpus");
1673 if (!metric_only)
1674 fprintf(output, " counts %*s events\n", unit_width, "unit");
1675 break;
1676 case AGGR_CORE:
1677 fprintf(output, "# time core cpus");
1678 if (!metric_only)
1679 fprintf(output, " counts %*s events\n", unit_width, "unit");
1680 break;
1681 case AGGR_NONE:
1682 fprintf(output, "# time CPU ");
1683 if (!metric_only)
1684 fprintf(output, " counts %*s events\n", unit_width, "unit");
1685 break;
1686 case AGGR_THREAD:
1687 fprintf(output, "# time comm-pid");
1688 if (!metric_only)
1689 fprintf(output, " counts %*s events\n", unit_width, "unit");
1690 break;
1691 case AGGR_GLOBAL:
1692 default:
1693 fprintf(output, "# time");
1694 if (!metric_only)
1695 fprintf(output, " counts %*s events\n", unit_width, "unit");
1696 case AGGR_UNSET:
1697 break;
1698 }
1699 }
1700
1701 if ((num_print_interval == 0 || interval_clear) && metric_only)
1702 print_metric_headers(" ", true);
1703 if (++num_print_interval == 25)
1704 num_print_interval = 0;
1705}
1706
1707static void print_header(int argc, const char **argv)
1708{
1709 FILE *output = stat_config.output;
1710 int i;
1711
1712 fflush(stdout);
1713
1714 if (!csv_output) {
1715 fprintf(output, "\n");
1716 fprintf(output, " Performance counter stats for ");
1717 if (target.system_wide)
1718 fprintf(output, "\'system wide");
1719 else if (target.cpu_list)
1720 fprintf(output, "\'CPU(s) %s", target.cpu_list);
1721 else if (!target__has_task(&target)) {
1722 fprintf(output, "\'%s", argv ? argv[0] : "pipe");
1723 for (i = 1; argv && (i < argc); i++)
1724 fprintf(output, " %s", argv[i]);
1725 } else if (target.pid)
1726 fprintf(output, "process id \'%s", target.pid);
1727 else
1728 fprintf(output, "thread id \'%s", target.tid);
1729
1730 fprintf(output, "\'");
1731 if (run_count > 1)
1732 fprintf(output, " (%d runs)", run_count);
1733 fprintf(output, ":\n\n");
1734 }
1735}
1736
1737static int get_precision(double num)
1738{
1739 if (num > 1)
1740 return 0;
1741
1742 return lround(ceil(-log10(num)));
1743}
1744
1745static void print_table(FILE *output, int precision, double avg)
1746{
1747 char tmp[64];
1748 int idx, indent = 0;
1749
1750 scnprintf(tmp, 64, " %17.*f", precision, avg);
1751 while (tmp[indent] == ' ')
1752 indent++;
1753
1754 fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
1755
1756 for (idx = 0; idx < run_count; idx++) {
1757 double run = (double) walltime_run[idx] / NSEC_PER_SEC;
1758 int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
1759
1760 fprintf(output, " %17.*f (%+.*f) ",
1761 precision, run, precision, run - avg);
1762
1763 for (h = 0; h < n; h++)
1764 fprintf(output, "#");
1765
1766 fprintf(output, "\n");
1767 }
1768
1769 fprintf(output, "\n%*s# Final result:\n", indent, "");
1770}
1771
1772static double timeval2double(struct timeval *t)
1773{
1774 return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
1775}
1776
1777static void print_footer(void)
1778{
1779 double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
1780 FILE *output = stat_config.output;
1781 int n;
1782
1783 if (!null_run)
1784 fprintf(output, "\n");
1785
1786 if (run_count == 1) {
1787 fprintf(output, " %17.9f seconds time elapsed", avg);
1788
1789 if (ru_display) {
1790 double ru_utime = timeval2double(&ru_data.ru_utime);
1791 double ru_stime = timeval2double(&ru_data.ru_stime);
1792
1793 fprintf(output, "\n\n");
1794 fprintf(output, " %17.9f seconds user\n", ru_utime);
1795 fprintf(output, " %17.9f seconds sys\n", ru_stime);
1796 }
1797 } else {
1798 double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
1799 /*
1800 * Display at most 2 more significant
1801 * digits than the stddev inaccuracy.
1802 */
1803 int precision = get_precision(sd) + 2;
1804
1805 if (walltime_run_table)
1806 print_table(output, precision, avg);
1807
1808 fprintf(output, " %17.*f +- %.*f seconds time elapsed",
1809 precision, avg, precision, sd);
1810
1811 print_noise_pct(sd, avg);
1812 }
1813 fprintf(output, "\n\n");
1814
1815 if (print_free_counters_hint &&
1816 sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
1817 n > 0)
1818 fprintf(output,
1819"Some events weren't counted. Try disabling the NMI watchdog:\n"
1820" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1821" perf stat ...\n"
1822" echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1823
1824 if (print_mixed_hw_group_error)
1825 fprintf(output,
1826 "The events in group usually have to be from "
1827 "the same PMU. Try reorganizing the group.\n");
1828}
1829
1830static void print_counters(struct timespec *ts, int argc, const char **argv) 639static void print_counters(struct timespec *ts, int argc, const char **argv)
1831{ 640{
1832 int interval = stat_config.interval;
1833 struct perf_evsel *counter;
1834 char buf[64], *prefix = NULL;
1835
1836 /* Do not print anything if we record to the pipe. */ 641 /* Do not print anything if we record to the pipe. */
1837 if (STAT_RECORD && perf_stat.data.is_pipe) 642 if (STAT_RECORD && perf_stat.data.is_pipe)
1838 return; 643 return;
1839 644
1840 if (interval) 645 perf_evlist__print_counters(evsel_list, &stat_config, &target,
1841 print_interval(prefix = buf, ts); 646 ts, argc, argv);
1842 else
1843 print_header(argc, argv);
1844
1845 if (metric_only) {
1846 static int num_print_iv;
1847
1848 if (num_print_iv == 0 && !interval)
1849 print_metric_headers(prefix, false);
1850 if (num_print_iv++ == 25)
1851 num_print_iv = 0;
1852 if (stat_config.aggr_mode == AGGR_GLOBAL && prefix)
1853 fprintf(stat_config.output, "%s", prefix);
1854 }
1855
1856 switch (stat_config.aggr_mode) {
1857 case AGGR_CORE:
1858 case AGGR_SOCKET:
1859 print_aggr(prefix);
1860 break;
1861 case AGGR_THREAD:
1862 evlist__for_each_entry(evsel_list, counter) {
1863 if (is_duration_time(counter))
1864 continue;
1865 print_aggr_thread(counter, prefix);
1866 }
1867 break;
1868 case AGGR_GLOBAL:
1869 evlist__for_each_entry(evsel_list, counter) {
1870 if (is_duration_time(counter))
1871 continue;
1872 print_counter_aggr(counter, prefix);
1873 }
1874 if (metric_only)
1875 fputc('\n', stat_config.output);
1876 break;
1877 case AGGR_NONE:
1878 if (metric_only)
1879 print_no_aggr_metric(prefix);
1880 else {
1881 evlist__for_each_entry(evsel_list, counter) {
1882 if (is_duration_time(counter))
1883 continue;
1884 print_counter(counter, prefix);
1885 }
1886 }
1887 break;
1888 case AGGR_UNSET:
1889 default:
1890 break;
1891 }
1892
1893 if (!interval && !csv_output)
1894 print_footer();
1895
1896 fflush(stat_config.output);
1897} 647}
1898 648
1899static volatile int signr = -1; 649static volatile int signr = -1;
@@ -1950,7 +700,7 @@ static int enable_metric_only(const struct option *opt __maybe_unused,
1950 const char *s __maybe_unused, int unset) 700 const char *s __maybe_unused, int unset)
1951{ 701{
1952 force_metric_only = true; 702 force_metric_only = true;
1953 metric_only = !unset; 703 stat_config.metric_only = !unset;
1954 return 0; 704 return 0;
1955} 705}
1956 706
@@ -1958,7 +708,7 @@ static int parse_metric_groups(const struct option *opt,
1958 const char *str, 708 const char *str,
1959 int unset __maybe_unused) 709 int unset __maybe_unused)
1960{ 710{
1961 return metricgroup__parse_groups(opt, str, &metric_events); 711 return metricgroup__parse_groups(opt, str, &stat_config.metric_events);
1962} 712}
1963 713
1964static const struct option stat_options[] = { 714static const struct option stat_options[] = {
@@ -1969,7 +719,7 @@ static const struct option stat_options[] = {
1969 parse_events_option), 719 parse_events_option),
1970 OPT_CALLBACK(0, "filter", &evsel_list, "filter", 720 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1971 "event filter", parse_filter), 721 "event filter", parse_filter),
1972 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 722 OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit,
1973 "child tasks do not inherit counters"), 723 "child tasks do not inherit counters"),
1974 OPT_STRING('p', "pid", &target.pid, "pid", 724 OPT_STRING('p', "pid", &target.pid, "pid",
1975 "stat events on existing process id"), 725 "stat events on existing process id"),
@@ -1982,11 +732,11 @@ static const struct option stat_options[] = {
1982 OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"), 732 OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
1983 OPT_INCR('v', "verbose", &verbose, 733 OPT_INCR('v', "verbose", &verbose,
1984 "be more verbose (show counter open errors, etc)"), 734 "be more verbose (show counter open errors, etc)"),
1985 OPT_INTEGER('r', "repeat", &run_count, 735 OPT_INTEGER('r', "repeat", &stat_config.run_count,
1986 "repeat command and print average + stddev (max: 100, forever: 0)"), 736 "repeat command and print average + stddev (max: 100, forever: 0)"),
1987 OPT_BOOLEAN(0, "table", &walltime_run_table, 737 OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table,
1988 "display details about each run (only with -r option)"), 738 "display details about each run (only with -r option)"),
1989 OPT_BOOLEAN('n', "null", &null_run, 739 OPT_BOOLEAN('n', "null", &stat_config.null_run,
1990 "null run - dont start any counters"), 740 "null run - dont start any counters"),
1991 OPT_INCR('d', "detailed", &detailed_run, 741 OPT_INCR('d', "detailed", &detailed_run,
1992 "detailed run - start a lot of events"), 742 "detailed run - start a lot of events"),
@@ -1999,8 +749,8 @@ static const struct option stat_options[] = {
1999 "list of cpus to monitor in system-wide"), 749 "list of cpus to monitor in system-wide"),
2000 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode, 750 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
2001 "disable CPU count aggregation", AGGR_NONE), 751 "disable CPU count aggregation", AGGR_NONE),
2002 OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"), 752 OPT_BOOLEAN(0, "no-merge", &stat_config.no_merge, "Do not merge identical named events"),
2003 OPT_STRING('x', "field-separator", &csv_sep, "separator", 753 OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
2004 "print counts with custom separator"), 754 "print counts with custom separator"),
2005 OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 755 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
2006 "monitor event in cgroup name only", parse_cgroups), 756 "monitor event in cgroup name only", parse_cgroups),
@@ -2017,7 +767,7 @@ static const struct option stat_options[] = {
2017 "(overhead is possible for values <= 100ms)"), 767 "(overhead is possible for values <= 100ms)"),
2018 OPT_INTEGER(0, "interval-count", &stat_config.times, 768 OPT_INTEGER(0, "interval-count", &stat_config.times,
2019 "print counts for fixed number of times"), 769 "print counts for fixed number of times"),
2020 OPT_BOOLEAN(0, "interval-clear", &interval_clear, 770 OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear,
2021 "clear screen in between new interval"), 771 "clear screen in between new interval"),
2022 OPT_UINTEGER(0, "timeout", &stat_config.timeout, 772 OPT_UINTEGER(0, "timeout", &stat_config.timeout,
2023 "stop workload and print counts after a timeout period in ms (>= 10ms)"), 773 "stop workload and print counts after a timeout period in ms (>= 10ms)"),
@@ -2027,9 +777,9 @@ static const struct option stat_options[] = {
2027 "aggregate counts per physical processor core", AGGR_CORE), 777 "aggregate counts per physical processor core", AGGR_CORE),
2028 OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode, 778 OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
2029 "aggregate counts per thread", AGGR_THREAD), 779 "aggregate counts per thread", AGGR_THREAD),
2030 OPT_UINTEGER('D', "delay", &initial_delay, 780 OPT_UINTEGER('D', "delay", &stat_config.initial_delay,
2031 "ms to wait before starting measurement after program start"), 781 "ms to wait before starting measurement after program start"),
2032 OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL, 782 OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL,
2033 "Only print computed metrics. No raw values", enable_metric_only), 783 "Only print computed metrics. No raw values", enable_metric_only),
2034 OPT_BOOLEAN(0, "topdown", &topdown_run, 784 OPT_BOOLEAN(0, "topdown", &topdown_run,
2035 "measure topdown level 1 statistics"), 785 "measure topdown level 1 statistics"),
@@ -2041,12 +791,14 @@ static const struct option stat_options[] = {
2041 OPT_END() 791 OPT_END()
2042}; 792};
2043 793
2044static int perf_stat__get_socket(struct cpu_map *map, int cpu) 794static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
795 struct cpu_map *map, int cpu)
2045{ 796{
2046 return cpu_map__get_socket(map, cpu, NULL); 797 return cpu_map__get_socket(map, cpu, NULL);
2047} 798}
2048 799
2049static int perf_stat__get_core(struct cpu_map *map, int cpu) 800static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
801 struct cpu_map *map, int cpu)
2050{ 802{
2051 return cpu_map__get_core(map, cpu, NULL); 803 return cpu_map__get_core(map, cpu, NULL);
2052} 804}
@@ -2063,9 +815,8 @@ static int cpu_map__get_max(struct cpu_map *map)
2063 return max; 815 return max;
2064} 816}
2065 817
2066static struct cpu_map *cpus_aggr_map; 818static int perf_stat__get_aggr(struct perf_stat_config *config,
2067 819 aggr_get_id_t get_id, struct cpu_map *map, int idx)
2068static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
2069{ 820{
2070 int cpu; 821 int cpu;
2071 822
@@ -2074,20 +825,22 @@ static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int id
2074 825
2075 cpu = map->map[idx]; 826 cpu = map->map[idx];
2076 827
2077 if (cpus_aggr_map->map[cpu] == -1) 828 if (config->cpus_aggr_map->map[cpu] == -1)
2078 cpus_aggr_map->map[cpu] = get_id(map, idx); 829 config->cpus_aggr_map->map[cpu] = get_id(config, map, idx);
2079 830
2080 return cpus_aggr_map->map[cpu]; 831 return config->cpus_aggr_map->map[cpu];
2081} 832}
2082 833
2083static int perf_stat__get_socket_cached(struct cpu_map *map, int idx) 834static int perf_stat__get_socket_cached(struct perf_stat_config *config,
835 struct cpu_map *map, int idx)
2084{ 836{
2085 return perf_stat__get_aggr(perf_stat__get_socket, map, idx); 837 return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx);
2086} 838}
2087 839
2088static int perf_stat__get_core_cached(struct cpu_map *map, int idx) 840static int perf_stat__get_core_cached(struct perf_stat_config *config,
841 struct cpu_map *map, int idx)
2089{ 842{
2090 return perf_stat__get_aggr(perf_stat__get_core, map, idx); 843 return perf_stat__get_aggr(config, perf_stat__get_core, map, idx);
2091} 844}
2092 845
2093static int perf_stat_init_aggr_mode(void) 846static int perf_stat_init_aggr_mode(void)
@@ -2096,18 +849,18 @@ static int perf_stat_init_aggr_mode(void)
2096 849
2097 switch (stat_config.aggr_mode) { 850 switch (stat_config.aggr_mode) {
2098 case AGGR_SOCKET: 851 case AGGR_SOCKET:
2099 if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { 852 if (cpu_map__build_socket_map(evsel_list->cpus, &stat_config.aggr_map)) {
2100 perror("cannot build socket map"); 853 perror("cannot build socket map");
2101 return -1; 854 return -1;
2102 } 855 }
2103 aggr_get_id = perf_stat__get_socket_cached; 856 stat_config.aggr_get_id = perf_stat__get_socket_cached;
2104 break; 857 break;
2105 case AGGR_CORE: 858 case AGGR_CORE:
2106 if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { 859 if (cpu_map__build_core_map(evsel_list->cpus, &stat_config.aggr_map)) {
2107 perror("cannot build core map"); 860 perror("cannot build core map");
2108 return -1; 861 return -1;
2109 } 862 }
2110 aggr_get_id = perf_stat__get_core_cached; 863 stat_config.aggr_get_id = perf_stat__get_core_cached;
2111 break; 864 break;
2112 case AGGR_NONE: 865 case AGGR_NONE:
2113 case AGGR_GLOBAL: 866 case AGGR_GLOBAL:
@@ -2123,16 +876,16 @@ static int perf_stat_init_aggr_mode(void)
2123 * the aggregation translate cpumap. 876 * the aggregation translate cpumap.
2124 */ 877 */
2125 nr = cpu_map__get_max(evsel_list->cpus); 878 nr = cpu_map__get_max(evsel_list->cpus);
2126 cpus_aggr_map = cpu_map__empty_new(nr + 1); 879 stat_config.cpus_aggr_map = cpu_map__empty_new(nr + 1);
2127 return cpus_aggr_map ? 0 : -ENOMEM; 880 return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
2128} 881}
2129 882
2130static void perf_stat__exit_aggr_mode(void) 883static void perf_stat__exit_aggr_mode(void)
2131{ 884{
2132 cpu_map__put(aggr_map); 885 cpu_map__put(stat_config.aggr_map);
2133 cpu_map__put(cpus_aggr_map); 886 cpu_map__put(stat_config.cpus_aggr_map);
2134 aggr_map = NULL; 887 stat_config.aggr_map = NULL;
2135 cpus_aggr_map = NULL; 888 stat_config.cpus_aggr_map = NULL;
2136} 889}
2137 890
2138static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx) 891static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx)
@@ -2190,12 +943,14 @@ static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus,
2190 return cpu_map__build_map(cpus, corep, perf_env__get_core, env); 943 return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
2191} 944}
2192 945
2193static int perf_stat__get_socket_file(struct cpu_map *map, int idx) 946static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
947 struct cpu_map *map, int idx)
2194{ 948{
2195 return perf_env__get_socket(map, idx, &perf_stat.session->header.env); 949 return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
2196} 950}
2197 951
2198static int perf_stat__get_core_file(struct cpu_map *map, int idx) 952static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
953 struct cpu_map *map, int idx)
2199{ 954{
2200 return perf_env__get_core(map, idx, &perf_stat.session->header.env); 955 return perf_env__get_core(map, idx, &perf_stat.session->header.env);
2201} 956}
@@ -2206,18 +961,18 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
2206 961
2207 switch (stat_config.aggr_mode) { 962 switch (stat_config.aggr_mode) {
2208 case AGGR_SOCKET: 963 case AGGR_SOCKET:
2209 if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) { 964 if (perf_env__build_socket_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
2210 perror("cannot build socket map"); 965 perror("cannot build socket map");
2211 return -1; 966 return -1;
2212 } 967 }
2213 aggr_get_id = perf_stat__get_socket_file; 968 stat_config.aggr_get_id = perf_stat__get_socket_file;
2214 break; 969 break;
2215 case AGGR_CORE: 970 case AGGR_CORE:
2216 if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) { 971 if (perf_env__build_core_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
2217 perror("cannot build core map"); 972 perror("cannot build core map");
2218 return -1; 973 return -1;
2219 } 974 }
2220 aggr_get_id = perf_stat__get_core_file; 975 stat_config.aggr_get_id = perf_stat__get_core_file;
2221 break; 976 break;
2222 case AGGR_NONE: 977 case AGGR_NONE:
2223 case AGGR_GLOBAL: 978 case AGGR_GLOBAL:
@@ -2401,7 +1156,7 @@ static int add_default_attributes(void)
2401 struct parse_events_error errinfo; 1156 struct parse_events_error errinfo;
2402 1157
2403 /* Set attrs if no event is selected and !null_run: */ 1158 /* Set attrs if no event is selected and !null_run: */
2404 if (null_run) 1159 if (stat_config.null_run)
2405 return 0; 1160 return 0;
2406 1161
2407 if (transaction_run) { 1162 if (transaction_run) {
@@ -2414,7 +1169,7 @@ static int add_default_attributes(void)
2414 struct option opt = { .value = &evsel_list }; 1169 struct option opt = { .value = &evsel_list };
2415 1170
2416 return metricgroup__parse_groups(&opt, "transaction", 1171 return metricgroup__parse_groups(&opt, "transaction",
2417 &metric_events); 1172 &stat_config.metric_events);
2418 } 1173 }
2419 1174
2420 if (pmu_have_event("cpu", "cycles-ct") && 1175 if (pmu_have_event("cpu", "cycles-ct") &&
@@ -2452,7 +1207,7 @@ static int add_default_attributes(void)
2452 if (pmu_have_event("msr", "aperf") && 1207 if (pmu_have_event("msr", "aperf") &&
2453 pmu_have_event("msr", "smi")) { 1208 pmu_have_event("msr", "smi")) {
2454 if (!force_metric_only) 1209 if (!force_metric_only)
2455 metric_only = true; 1210 stat_config.metric_only = true;
2456 err = parse_events(evsel_list, smi_cost_attrs, &errinfo); 1211 err = parse_events(evsel_list, smi_cost_attrs, &errinfo);
2457 } else { 1212 } else {
2458 fprintf(stderr, "To measure SMI cost, it needs " 1213 fprintf(stderr, "To measure SMI cost, it needs "
@@ -2483,7 +1238,7 @@ static int add_default_attributes(void)
2483 } 1238 }
2484 1239
2485 if (!force_metric_only) 1240 if (!force_metric_only)
2486 metric_only = true; 1241 stat_config.metric_only = true;
2487 if (topdown_filter_events(topdown_attrs, &str, 1242 if (topdown_filter_events(topdown_attrs, &str,
2488 arch_topdown_check_group(&warn)) < 0) { 1243 arch_topdown_check_group(&warn)) < 0) {
2489 pr_err("Out of memory\n"); 1244 pr_err("Out of memory\n");
@@ -2580,7 +1335,7 @@ static int __cmd_record(int argc, const char **argv)
2580 if (output_name) 1335 if (output_name)
2581 data->file.path = output_name; 1336 data->file.path = output_name;
2582 1337
2583 if (run_count != 1 || forever) { 1338 if (stat_config.run_count != 1 || forever) {
2584 pr_err("Cannot use -r option with perf stat record.\n"); 1339 pr_err("Cannot use -r option with perf stat record.\n");
2585 return -1; 1340 return -1;
2586 } 1341 }
@@ -2599,9 +1354,8 @@ static int __cmd_record(int argc, const char **argv)
2599 return argc; 1354 return argc;
2600} 1355}
2601 1356
2602static int process_stat_round_event(struct perf_tool *tool __maybe_unused, 1357static int process_stat_round_event(struct perf_session *session,
2603 union perf_event *event, 1358 union perf_event *event)
2604 struct perf_session *session)
2605{ 1359{
2606 struct stat_round_event *stat_round = &event->stat_round; 1360 struct stat_round_event *stat_round = &event->stat_round;
2607 struct perf_evsel *counter; 1361 struct perf_evsel *counter;
@@ -2626,10 +1380,10 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2626} 1380}
2627 1381
2628static 1382static
2629int process_stat_config_event(struct perf_tool *tool, 1383int process_stat_config_event(struct perf_session *session,
2630 union perf_event *event, 1384 union perf_event *event)
2631 struct perf_session *session __maybe_unused)
2632{ 1385{
1386 struct perf_tool *tool = session->tool;
2633 struct perf_stat *st = container_of(tool, struct perf_stat, tool); 1387 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2634 1388
2635 perf_event__read_stat_config(&stat_config, &event->stat_config); 1389 perf_event__read_stat_config(&stat_config, &event->stat_config);
@@ -2669,10 +1423,10 @@ static int set_maps(struct perf_stat *st)
2669} 1423}
2670 1424
2671static 1425static
2672int process_thread_map_event(struct perf_tool *tool, 1426int process_thread_map_event(struct perf_session *session,
2673 union perf_event *event, 1427 union perf_event *event)
2674 struct perf_session *session __maybe_unused)
2675{ 1428{
1429 struct perf_tool *tool = session->tool;
2676 struct perf_stat *st = container_of(tool, struct perf_stat, tool); 1430 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2677 1431
2678 if (st->threads) { 1432 if (st->threads) {
@@ -2688,10 +1442,10 @@ int process_thread_map_event(struct perf_tool *tool,
2688} 1442}
2689 1443
2690static 1444static
2691int process_cpu_map_event(struct perf_tool *tool, 1445int process_cpu_map_event(struct perf_session *session,
2692 union perf_event *event, 1446 union perf_event *event)
2693 struct perf_session *session __maybe_unused)
2694{ 1447{
1448 struct perf_tool *tool = session->tool;
2695 struct perf_stat *st = container_of(tool, struct perf_stat, tool); 1449 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2696 struct cpu_map *cpus; 1450 struct cpu_map *cpus;
2697 1451
@@ -2853,12 +1607,12 @@ int cmd_stat(int argc, const char **argv)
2853 perf_stat__collect_metric_expr(evsel_list); 1607 perf_stat__collect_metric_expr(evsel_list);
2854 perf_stat__init_shadow_stats(); 1608 perf_stat__init_shadow_stats();
2855 1609
2856 if (csv_sep) { 1610 if (stat_config.csv_sep) {
2857 csv_output = true; 1611 stat_config.csv_output = true;
2858 if (!strcmp(csv_sep, "\\t")) 1612 if (!strcmp(stat_config.csv_sep, "\\t"))
2859 csv_sep = "\t"; 1613 stat_config.csv_sep = "\t";
2860 } else 1614 } else
2861 csv_sep = DEFAULT_SEPARATOR; 1615 stat_config.csv_sep = DEFAULT_SEPARATOR;
2862 1616
2863 if (argc && !strncmp(argv[0], "rec", 3)) { 1617 if (argc && !strncmp(argv[0], "rec", 3)) {
2864 argc = __cmd_record(argc, argv); 1618 argc = __cmd_record(argc, argv);
@@ -2883,17 +1637,17 @@ int cmd_stat(int argc, const char **argv)
2883 goto out; 1637 goto out;
2884 } 1638 }
2885 1639
2886 if (metric_only && stat_config.aggr_mode == AGGR_THREAD) { 1640 if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) {
2887 fprintf(stderr, "--metric-only is not supported with --per-thread\n"); 1641 fprintf(stderr, "--metric-only is not supported with --per-thread\n");
2888 goto out; 1642 goto out;
2889 } 1643 }
2890 1644
2891 if (metric_only && run_count > 1) { 1645 if (stat_config.metric_only && stat_config.run_count > 1) {
2892 fprintf(stderr, "--metric-only is not supported with -r\n"); 1646 fprintf(stderr, "--metric-only is not supported with -r\n");
2893 goto out; 1647 goto out;
2894 } 1648 }
2895 1649
2896 if (walltime_run_table && run_count <= 1) { 1650 if (stat_config.walltime_run_table && stat_config.run_count <= 1) {
2897 fprintf(stderr, "--table is only supported with -r\n"); 1651 fprintf(stderr, "--table is only supported with -r\n");
2898 parse_options_usage(stat_usage, stat_options, "r", 1); 1652 parse_options_usage(stat_usage, stat_options, "r", 1);
2899 parse_options_usage(NULL, stat_options, "table", 0); 1653 parse_options_usage(NULL, stat_options, "table", 0);
@@ -2931,7 +1685,7 @@ int cmd_stat(int argc, const char **argv)
2931 /* 1685 /*
2932 * let the spreadsheet do the pretty-printing 1686 * let the spreadsheet do the pretty-printing
2933 */ 1687 */
2934 if (csv_output) { 1688 if (stat_config.csv_output) {
2935 /* User explicitly passed -B? */ 1689 /* User explicitly passed -B? */
2936 if (big_num_opt == 1) { 1690 if (big_num_opt == 1) {
2937 fprintf(stderr, "-B option not supported with -x\n"); 1691 fprintf(stderr, "-B option not supported with -x\n");
@@ -2939,9 +1693,9 @@ int cmd_stat(int argc, const char **argv)
2939 parse_options_usage(NULL, stat_options, "x", 1); 1693 parse_options_usage(NULL, stat_options, "x", 1);
2940 goto out; 1694 goto out;
2941 } else /* Nope, so disable big number formatting */ 1695 } else /* Nope, so disable big number formatting */
2942 big_num = false; 1696 stat_config.big_num = false;
2943 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1697 } else if (big_num_opt == 0) /* User passed --no-big-num */
2944 big_num = false; 1698 stat_config.big_num = false;
2945 1699
2946 setup_system_wide(argc); 1700 setup_system_wide(argc);
2947 1701
@@ -2949,21 +1703,21 @@ int cmd_stat(int argc, const char **argv)
2949 * Display user/system times only for single 1703 * Display user/system times only for single
2950 * run and when there's specified tracee. 1704 * run and when there's specified tracee.
2951 */ 1705 */
2952 if ((run_count == 1) && target__none(&target)) 1706 if ((stat_config.run_count == 1) && target__none(&target))
2953 ru_display = true; 1707 stat_config.ru_display = true;
2954 1708
2955 if (run_count < 0) { 1709 if (stat_config.run_count < 0) {
2956 pr_err("Run count must be a positive number\n"); 1710 pr_err("Run count must be a positive number\n");
2957 parse_options_usage(stat_usage, stat_options, "r", 1); 1711 parse_options_usage(stat_usage, stat_options, "r", 1);
2958 goto out; 1712 goto out;
2959 } else if (run_count == 0) { 1713 } else if (stat_config.run_count == 0) {
2960 forever = true; 1714 forever = true;
2961 run_count = 1; 1715 stat_config.run_count = 1;
2962 } 1716 }
2963 1717
2964 if (walltime_run_table) { 1718 if (stat_config.walltime_run_table) {
2965 walltime_run = zalloc(run_count * sizeof(walltime_run[0])); 1719 stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0]));
2966 if (!walltime_run) { 1720 if (!stat_config.walltime_run) {
2967 pr_err("failed to setup -r option"); 1721 pr_err("failed to setup -r option");
2968 goto out; 1722 goto out;
2969 } 1723 }
@@ -3066,6 +1820,17 @@ int cmd_stat(int argc, const char **argv)
3066 goto out; 1820 goto out;
3067 1821
3068 /* 1822 /*
1823 * Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
1824 * while avoiding that older tools show confusing messages.
1825 *
1826 * However for pipe sessions we need to keep it zero,
1827 * because script's perf_evsel__check_attr is triggered
1828 * by attr->sample_type != 0, and we can't run it on
1829 * stat sessions.
1830 */
1831 stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe);
1832
1833 /*
3069 * We dont want to block the signals - that would cause 1834 * We dont want to block the signals - that would cause
3070 * child tasks to inherit that and Ctrl-C would not work. 1835 * child tasks to inherit that and Ctrl-C would not work.
3071 * What we want is for Ctrl-C to work in the exec()-ed 1836 * What we want is for Ctrl-C to work in the exec()-ed
@@ -3079,8 +1844,8 @@ int cmd_stat(int argc, const char **argv)
3079 signal(SIGABRT, skip_signal); 1844 signal(SIGABRT, skip_signal);
3080 1845
3081 status = 0; 1846 status = 0;
3082 for (run_idx = 0; forever || run_idx < run_count; run_idx++) { 1847 for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) {
3083 if (run_count != 1 && verbose > 0) 1848 if (stat_config.run_count != 1 && verbose > 0)
3084 fprintf(output, "[ perf stat: executing run #%d ... ]\n", 1849 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
3085 run_idx + 1); 1850 run_idx + 1);
3086 1851
@@ -3132,7 +1897,7 @@ int cmd_stat(int argc, const char **argv)
3132 perf_stat__exit_aggr_mode(); 1897 perf_stat__exit_aggr_mode();
3133 perf_evlist__free_stats(evsel_list); 1898 perf_evlist__free_stats(evsel_list);
3134out: 1899out:
3135 free(walltime_run); 1900 free(stat_config.walltime_run);
3136 1901
3137 if (smi_cost && smi_reset) 1902 if (smi_cost && smi_reset)
3138 sysfs__write_int(FREEZE_ON_SMI_PATH, 0); 1903 sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 22ab8e67c760..90289f31dd87 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -181,7 +181,7 @@ static int __tp_field__init_uint(struct tp_field *field, int size, int offset, b
181 return 0; 181 return 0;
182} 182}
183 183
184static int tp_field__init_uint(struct tp_field *field, struct format_field *format_field, bool needs_swap) 184static int tp_field__init_uint(struct tp_field *field, struct tep_format_field *format_field, bool needs_swap)
185{ 185{
186 return __tp_field__init_uint(field, format_field->size, format_field->offset, needs_swap); 186 return __tp_field__init_uint(field, format_field->size, format_field->offset, needs_swap);
187} 187}
@@ -198,7 +198,7 @@ static int __tp_field__init_ptr(struct tp_field *field, int offset)
198 return 0; 198 return 0;
199} 199}
200 200
201static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field) 201static int tp_field__init_ptr(struct tp_field *field, struct tep_format_field *format_field)
202{ 202{
203 return __tp_field__init_ptr(field, format_field->offset); 203 return __tp_field__init_ptr(field, format_field->offset);
204} 204}
@@ -214,7 +214,7 @@ static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
214 struct tp_field *field, 214 struct tp_field *field,
215 const char *name) 215 const char *name)
216{ 216{
217 struct format_field *format_field = perf_evsel__field(evsel, name); 217 struct tep_format_field *format_field = perf_evsel__field(evsel, name);
218 218
219 if (format_field == NULL) 219 if (format_field == NULL)
220 return -1; 220 return -1;
@@ -230,7 +230,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
230 struct tp_field *field, 230 struct tp_field *field,
231 const char *name) 231 const char *name)
232{ 232{
233 struct format_field *format_field = perf_evsel__field(evsel, name); 233 struct tep_format_field *format_field = perf_evsel__field(evsel, name);
234 234
235 if (format_field == NULL) 235 if (format_field == NULL)
236 return -1; 236 return -1;
@@ -288,6 +288,13 @@ static int perf_evsel__init_augmented_syscall_tp_args(struct perf_evsel *evsel)
288 return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64)); 288 return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64));
289} 289}
290 290
291static int perf_evsel__init_augmented_syscall_tp_ret(struct perf_evsel *evsel)
292{
293 struct syscall_tp *sc = evsel->priv;
294
295 return __tp_field__init_uint(&sc->ret, sizeof(u64), sc->id.offset + sizeof(u64), evsel->needs_swap);
296}
297
291static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler) 298static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler)
292{ 299{
293 evsel->priv = malloc(sizeof(struct syscall_tp)); 300 evsel->priv = malloc(sizeof(struct syscall_tp));
@@ -498,16 +505,6 @@ static const char *clockid[] = {
498}; 505};
499static DEFINE_STRARRAY(clockid); 506static DEFINE_STRARRAY(clockid);
500 507
501static const char *socket_families[] = {
502 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
503 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
504 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
505 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
506 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
507 "ALG", "NFC", "VSOCK",
508};
509static DEFINE_STRARRAY(socket_families);
510
511static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size, 508static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
512 struct syscall_arg *arg) 509 struct syscall_arg *arg)
513{ 510{
@@ -631,6 +628,8 @@ static struct syscall_fmt {
631} syscall_fmts[] = { 628} syscall_fmts[] = {
632 { .name = "access", 629 { .name = "access",
633 .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, 630 .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
631 { .name = "bind",
632 .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, },
634 { .name = "bpf", 633 { .name = "bpf",
635 .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, 634 .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
636 { .name = "brk", .hexret = true, 635 { .name = "brk", .hexret = true,
@@ -645,6 +644,8 @@ static struct syscall_fmt {
645 [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, }, 644 [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, },
646 { .name = "close", 645 { .name = "close",
647 .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, }, 646 .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
647 { .name = "connect",
648 .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, }, },
648 { .name = "epoll_ctl", 649 { .name = "epoll_ctl",
649 .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, }, 650 .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
650 { .name = "eventfd2", 651 { .name = "eventfd2",
@@ -801,7 +802,8 @@ static struct syscall_fmt {
801 { .name = "sendmsg", 802 { .name = "sendmsg",
802 .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, 803 .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
803 { .name = "sendto", 804 { .name = "sendto",
804 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, 805 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ },
806 [4] = { .scnprintf = SCA_SOCKADDR, /* addr */ }, }, },
805 { .name = "set_tid_address", .errpid = true, }, 807 { .name = "set_tid_address", .errpid = true, },
806 { .name = "setitimer", 808 { .name = "setitimer",
807 .arg = { [0] = STRARRAY(which, itimers), }, }, 809 .arg = { [0] = STRARRAY(which, itimers), }, },
@@ -830,6 +832,7 @@ static struct syscall_fmt {
830 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, 832 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
831 { .name = "tkill", 833 { .name = "tkill",
832 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, 834 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
835 { .name = "umount2", .alias = "umount", },
833 { .name = "uname", .alias = "newuname", }, 836 { .name = "uname", .alias = "newuname", },
834 { .name = "unlinkat", 837 { .name = "unlinkat",
835 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, 838 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
@@ -856,13 +859,15 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
856/* 859/*
857 * is_exit: is this "exit" or "exit_group"? 860 * is_exit: is this "exit" or "exit_group"?
858 * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter. 861 * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
862 * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
859 */ 863 */
860struct syscall { 864struct syscall {
861 struct event_format *tp_format; 865 struct tep_event_format *tp_format;
862 int nr_args; 866 int nr_args;
867 int args_size;
863 bool is_exit; 868 bool is_exit;
864 bool is_open; 869 bool is_open;
865 struct format_field *args; 870 struct tep_format_field *args;
866 const char *name; 871 const char *name;
867 struct syscall_fmt *fmt; 872 struct syscall_fmt *fmt;
868 struct syscall_arg_fmt *arg_fmt; 873 struct syscall_arg_fmt *arg_fmt;
@@ -1095,11 +1100,21 @@ static void thread__set_filename_pos(struct thread *thread, const char *bf,
1095 ttrace->filename.entry_str_pos = bf - ttrace->entry_str; 1100 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1096} 1101}
1097 1102
1103static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, char *bf, size_t size)
1104{
1105 struct augmented_arg *augmented_arg = arg->augmented.args;
1106
1107 return scnprintf(bf, size, "%.*s", augmented_arg->size, augmented_arg->value);
1108}
1109
1098static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, 1110static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1099 struct syscall_arg *arg) 1111 struct syscall_arg *arg)
1100{ 1112{
1101 unsigned long ptr = arg->val; 1113 unsigned long ptr = arg->val;
1102 1114
1115 if (arg->augmented.args)
1116 return syscall_arg__scnprintf_augmented_string(arg, bf, size);
1117
1103 if (!arg->trace->vfs_getname) 1118 if (!arg->trace->vfs_getname)
1104 return scnprintf(bf, size, "%#x", ptr); 1119 return scnprintf(bf, size, "%#x", ptr);
1105 1120
@@ -1142,11 +1157,9 @@ static void sig_handler(int sig)
1142 interrupted = sig == SIGINT; 1157 interrupted = sig == SIGINT;
1143} 1158}
1144 1159
1145static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, 1160static size_t trace__fprintf_comm_tid(struct trace *trace, struct thread *thread, FILE *fp)
1146 u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
1147{ 1161{
1148 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); 1162 size_t printed = 0;
1149 printed += fprintf_duration(duration, duration_calculated, fp);
1150 1163
1151 if (trace->multiple_threads) { 1164 if (trace->multiple_threads) {
1152 if (trace->show_comm) 1165 if (trace->show_comm)
@@ -1157,6 +1170,14 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
1157 return printed; 1170 return printed;
1158} 1171}
1159 1172
1173static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
1174 u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
1175{
1176 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
1177 printed += fprintf_duration(duration, duration_calculated, fp);
1178 return printed + trace__fprintf_comm_tid(trace, thread, fp);
1179}
1180
1160static int trace__process_event(struct trace *trace, struct machine *machine, 1181static int trace__process_event(struct trace *trace, struct machine *machine,
1161 union perf_event *event, struct perf_sample *sample) 1182 union perf_event *event, struct perf_sample *sample)
1162{ 1183{
@@ -1258,10 +1279,12 @@ static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args)
1258 1279
1259static int syscall__set_arg_fmts(struct syscall *sc) 1280static int syscall__set_arg_fmts(struct syscall *sc)
1260{ 1281{
1261 struct format_field *field; 1282 struct tep_format_field *field, *last_field = NULL;
1262 int idx = 0, len; 1283 int idx = 0, len;
1263 1284
1264 for (field = sc->args; field; field = field->next, ++idx) { 1285 for (field = sc->args; field; field = field->next, ++idx) {
1286 last_field = field;
1287
1265 if (sc->fmt && sc->fmt->arg[idx].scnprintf) 1288 if (sc->fmt && sc->fmt->arg[idx].scnprintf)
1266 continue; 1289 continue;
1267 1290
@@ -1270,7 +1293,7 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1270 strcmp(field->name, "path") == 0 || 1293 strcmp(field->name, "path") == 0 ||
1271 strcmp(field->name, "pathname") == 0)) 1294 strcmp(field->name, "pathname") == 0))
1272 sc->arg_fmt[idx].scnprintf = SCA_FILENAME; 1295 sc->arg_fmt[idx].scnprintf = SCA_FILENAME;
1273 else if (field->flags & FIELD_IS_POINTER) 1296 else if (field->flags & TEP_FIELD_IS_POINTER)
1274 sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex; 1297 sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex;
1275 else if (strcmp(field->type, "pid_t") == 0) 1298 else if (strcmp(field->type, "pid_t") == 0)
1276 sc->arg_fmt[idx].scnprintf = SCA_PID; 1299 sc->arg_fmt[idx].scnprintf = SCA_PID;
@@ -1292,6 +1315,9 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1292 } 1315 }
1293 } 1316 }
1294 1317
1318 if (last_field)
1319 sc->args_size = last_field->offset + last_field->size;
1320
1295 return 0; 1321 return 0;
1296} 1322}
1297 1323
@@ -1472,14 +1498,18 @@ static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
1472} 1498}
1473 1499
1474static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1500static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1475 unsigned char *args, struct trace *trace, 1501 unsigned char *args, void *augmented_args, int augmented_args_size,
1476 struct thread *thread) 1502 struct trace *trace, struct thread *thread)
1477{ 1503{
1478 size_t printed = 0; 1504 size_t printed = 0;
1479 unsigned long val; 1505 unsigned long val;
1480 u8 bit = 1; 1506 u8 bit = 1;
1481 struct syscall_arg arg = { 1507 struct syscall_arg arg = {
1482 .args = args, 1508 .args = args,
1509 .augmented = {
1510 .size = augmented_args_size,
1511 .args = augmented_args,
1512 },
1483 .idx = 0, 1513 .idx = 0,
1484 .mask = 0, 1514 .mask = 0,
1485 .trace = trace, 1515 .trace = trace,
@@ -1495,7 +1525,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1495 ttrace->ret_scnprintf = NULL; 1525 ttrace->ret_scnprintf = NULL;
1496 1526
1497 if (sc->args != NULL) { 1527 if (sc->args != NULL) {
1498 struct format_field *field; 1528 struct tep_format_field *field;
1499 1529
1500 for (field = sc->args; field; 1530 for (field = sc->args; field;
1501 field = field->next, ++arg.idx, bit <<= 1) { 1531 field = field->next, ++arg.idx, bit <<= 1) {
@@ -1654,6 +1684,17 @@ static int trace__fprintf_sample(struct trace *trace, struct perf_evsel *evsel,
1654 return printed; 1684 return printed;
1655} 1685}
1656 1686
1687static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sample, int *augmented_args_size)
1688{
1689 void *augmented_args = NULL;
1690
1691 *augmented_args_size = sample->raw_size - sc->args_size;
1692 if (*augmented_args_size > 0)
1693 augmented_args = sample->raw_data + sc->args_size;
1694
1695 return augmented_args;
1696}
1697
1657static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1698static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1658 union perf_event *event __maybe_unused, 1699 union perf_event *event __maybe_unused,
1659 struct perf_sample *sample) 1700 struct perf_sample *sample)
@@ -1663,6 +1704,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1663 size_t printed = 0; 1704 size_t printed = 0;
1664 struct thread *thread; 1705 struct thread *thread;
1665 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; 1706 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
1707 int augmented_args_size = 0;
1708 void *augmented_args = NULL;
1666 struct syscall *sc = trace__syscall_info(trace, evsel, id); 1709 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1667 struct thread_trace *ttrace; 1710 struct thread_trace *ttrace;
1668 1711
@@ -1686,13 +1729,24 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1686 1729
1687 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) 1730 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
1688 trace__printf_interrupted_entry(trace); 1731 trace__printf_interrupted_entry(trace);
1689 1732 /*
1733 * If this is raw_syscalls.sys_enter, then it always comes with the 6 possible
1734 * arguments, even if the syscall being handled, say "openat", uses only 4 arguments
1735 * this breaks syscall__augmented_args() check for augmented args, as we calculate
1736 * syscall->args_size using each syscalls:sys_enter_NAME tracefs format file,
1737 * so when handling, say the openat syscall, we end up getting 6 args for the
1738 * raw_syscalls:sys_enter event, when we expected just 4, we end up mistakenly
1739 * thinking that the extra 2 u64 args are the augmented filename, so just check
1740 * here and avoid using augmented syscalls when the evsel is the raw_syscalls one.
1741 */
1742 if (evsel != trace->syscalls.events.sys_enter)
1743 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size);
1690 ttrace->entry_time = sample->time; 1744 ttrace->entry_time = sample->time;
1691 msg = ttrace->entry_str; 1745 msg = ttrace->entry_str;
1692 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name); 1746 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
1693 1747
1694 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed, 1748 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
1695 args, trace, thread); 1749 args, augmented_args, augmented_args_size, trace, thread);
1696 1750
1697 if (sc->is_exit) { 1751 if (sc->is_exit) {
1698 if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { 1752 if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) {
@@ -1723,7 +1777,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse
1723 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; 1777 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
1724 struct syscall *sc = trace__syscall_info(trace, evsel, id); 1778 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1725 char msg[1024]; 1779 char msg[1024];
1726 void *args; 1780 void *args, *augmented_args = NULL;
1781 int augmented_args_size;
1727 1782
1728 if (sc == NULL) 1783 if (sc == NULL)
1729 return -1; 1784 return -1;
@@ -1738,7 +1793,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse
1738 goto out_put; 1793 goto out_put;
1739 1794
1740 args = perf_evsel__sc_tp_ptr(evsel, args, sample); 1795 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
1741 syscall__scnprintf_args(sc, msg, sizeof(msg), args, trace, thread); 1796 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size);
1797 syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread);
1742 fprintf(trace->output, "%s", msg); 1798 fprintf(trace->output, "%s", msg);
1743 err = 0; 1799 err = 0;
1744out_put: 1800out_put:
@@ -2022,6 +2078,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2022 union perf_event *event __maybe_unused, 2078 union perf_event *event __maybe_unused,
2023 struct perf_sample *sample) 2079 struct perf_sample *sample)
2024{ 2080{
2081 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2025 int callchain_ret = 0; 2082 int callchain_ret = 0;
2026 2083
2027 if (sample->callchain) { 2084 if (sample->callchain) {
@@ -2039,13 +2096,31 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2039 if (trace->trace_syscalls) 2096 if (trace->trace_syscalls)
2040 fprintf(trace->output, "( ): "); 2097 fprintf(trace->output, "( ): ");
2041 2098
2099 if (thread)
2100 trace__fprintf_comm_tid(trace, thread, trace->output);
2101
2102 if (evsel == trace->syscalls.events.augmented) {
2103 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
2104 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2105
2106 if (sc) {
2107 fprintf(trace->output, "%s(", sc->name);
2108 trace__fprintf_sys_enter(trace, evsel, sample);
2109 fputc(')', trace->output);
2110 goto newline;
2111 }
2112
2113 /*
2114 * XXX: Not having the associated syscall info or not finding/adding
2115 * the thread should never happen, but if it does...
2116 * fall thru and print it as a bpf_output event.
2117 */
2118 }
2119
2042 fprintf(trace->output, "%s:", evsel->name); 2120 fprintf(trace->output, "%s:", evsel->name);
2043 2121
2044 if (perf_evsel__is_bpf_output(evsel)) { 2122 if (perf_evsel__is_bpf_output(evsel)) {
2045 if (evsel == trace->syscalls.events.augmented) 2123 bpf_output__fprintf(trace, sample);
2046 trace__fprintf_sys_enter(trace, evsel, sample);
2047 else
2048 bpf_output__fprintf(trace, sample);
2049 } else if (evsel->tp_format) { 2124 } else if (evsel->tp_format) {
2050 if (strncmp(evsel->tp_format->name, "sys_enter_", 10) || 2125 if (strncmp(evsel->tp_format->name, "sys_enter_", 10) ||
2051 trace__fprintf_sys_enter(trace, evsel, sample)) { 2126 trace__fprintf_sys_enter(trace, evsel, sample)) {
@@ -2055,12 +2130,14 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2055 } 2130 }
2056 } 2131 }
2057 2132
2133newline:
2058 fprintf(trace->output, "\n"); 2134 fprintf(trace->output, "\n");
2059 2135
2060 if (callchain_ret > 0) 2136 if (callchain_ret > 0)
2061 trace__fprintf_callchain(trace, sample); 2137 trace__fprintf_callchain(trace, sample);
2062 else if (callchain_ret < 0) 2138 else if (callchain_ret < 0)
2063 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); 2139 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2140 thread__put(thread);
2064out: 2141out:
2065 return 0; 2142 return 0;
2066} 2143}
@@ -3276,12 +3353,8 @@ int cmd_trace(int argc, const char **argv)
3276 goto out; 3353 goto out;
3277 } 3354 }
3278 3355
3279 if (evsel) { 3356 if (evsel)
3280 if (perf_evsel__init_augmented_syscall_tp(evsel) ||
3281 perf_evsel__init_augmented_syscall_tp_args(evsel))
3282 goto out;
3283 trace.syscalls.events.augmented = evsel; 3357 trace.syscalls.events.augmented = evsel;
3284 }
3285 3358
3286 err = bpf__setup_stdout(trace.evlist); 3359 err = bpf__setup_stdout(trace.evlist);
3287 if (err) { 3360 if (err) {
@@ -3326,6 +3399,34 @@ int cmd_trace(int argc, const char **argv)
3326 } 3399 }
3327 } 3400 }
3328 3401
3402 /*
3403 * If we are augmenting syscalls, then combine what we put in the
3404 * __augmented_syscalls__ BPF map with what is in the
3405 * syscalls:sys_exit_FOO tracepoints, i.e. just like we do without BPF,
3406 * combining raw_syscalls:sys_enter with raw_syscalls:sys_exit.
3407 *
3408 * We'll switch to look at two BPF maps, one for sys_enter and the
3409 * other for sys_exit when we start augmenting the sys_exit paths with
3410 * buffers that are being copied from kernel to userspace, think 'read'
3411 * syscall.
3412 */
3413 if (trace.syscalls.events.augmented) {
3414 evsel = trace.syscalls.events.augmented;
3415
3416 if (perf_evsel__init_augmented_syscall_tp(evsel) ||
3417 perf_evsel__init_augmented_syscall_tp_args(evsel))
3418 goto out;
3419 evsel->handler = trace__sys_enter;
3420
3421 evlist__for_each_entry(trace.evlist, evsel) {
3422 if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) {
3423 perf_evsel__init_augmented_syscall_tp(evsel);
3424 perf_evsel__init_augmented_syscall_tp_ret(evsel);
3425 evsel->handler = trace__sys_exit;
3426 }
3427 }
3428 }
3429
3329 if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) 3430 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3330 return trace__record(&trace, argc-1, &argv[1]); 3431 return trace__record(&trace, argc-1, &argv[1]);
3331 3432
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 466540ee8ea7..c72cc73a6b09 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -14,6 +14,7 @@ include/uapi/linux/sched.h
14include/uapi/linux/stat.h 14include/uapi/linux/stat.h
15include/uapi/linux/vhost.h 15include/uapi/linux/vhost.h
16include/uapi/sound/asound.h 16include/uapi/sound/asound.h
17include/linux/bits.h
17include/linux/hash.h 18include/linux/hash.h
18include/uapi/linux/hw_breakpoint.h 19include/uapi/linux/hw_breakpoint.h
19arch/x86/include/asm/disabled-features.h 20arch/x86/include/asm/disabled-features.h
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 2d0caf20ff3a..bc6c585f74fc 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -30,3 +30,4 @@ perf-test mainporcelain common
30perf-timechart mainporcelain common 30perf-timechart mainporcelain common
31perf-top mainporcelain common 31perf-top mainporcelain common
32perf-trace mainporcelain audit 32perf-trace mainporcelain audit
33perf-version mainporcelain common
diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c
index 69a31386d8cd..2ae44813ef2d 100644
--- a/tools/perf/examples/bpf/augmented_syscalls.c
+++ b/tools/perf/examples/bpf/augmented_syscalls.c
@@ -1,6 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2/* 2/*
3 * Augment the openat syscall with the contents of the filename pointer argument. 3 * Augment syscalls with the contents of the pointer arguments.
4 * 4 *
5 * Test it with: 5 * Test it with:
6 * 6 *
@@ -10,15 +10,14 @@
10 * the last one should be the one for '/etc/passwd'. 10 * the last one should be the one for '/etc/passwd'.
11 * 11 *
12 * This matches what is marshalled into the raw_syscall:sys_enter payload 12 * This matches what is marshalled into the raw_syscall:sys_enter payload
13 * expected by the 'perf trace' beautifiers, and can be used by them unmodified, 13 * expected by the 'perf trace' beautifiers, and can be used by them, that will
14 * which will be done as that feature is implemented in the next csets, for now 14 * check if perf_sample->raw_data is more than what is expected for each
15 * it will appear in a dump done by the default tracepoint handler in 'perf trace', 15 * syscalls:sys_{enter,exit}_SYSCALL tracepoint, uing the extra data as the
16 * that uses bpf_output__fprintf() to just dump those contents, as done with 16 * contents of pointer arguments.
17 * the bpf-output event associated with the __bpf_output__ map declared in
18 * tools/perf/include/bpf/stdio.h.
19 */ 17 */
20 18
21#include <stdio.h> 19#include <stdio.h>
20#include <linux/socket.h>
22 21
23struct bpf_map SEC("maps") __augmented_syscalls__ = { 22struct bpf_map SEC("maps") __augmented_syscalls__ = {
24 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, 23 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
@@ -27,6 +26,44 @@ struct bpf_map SEC("maps") __augmented_syscalls__ = {
27 .max_entries = __NR_CPUS__, 26 .max_entries = __NR_CPUS__,
28}; 27};
29 28
29struct syscall_exit_args {
30 unsigned long long common_tp_fields;
31 long syscall_nr;
32 long ret;
33};
34
35struct augmented_filename {
36 unsigned int size;
37 int reserved;
38 char value[256];
39};
40
41#define augmented_filename_syscall(syscall) \
42struct augmented_enter_##syscall##_args { \
43 struct syscall_enter_##syscall##_args args; \
44 struct augmented_filename filename; \
45}; \
46int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
47{ \
48 struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \
49 unsigned int len = sizeof(augmented_args); \
50 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
51 augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \
52 sizeof(augmented_args.filename.value), \
53 args->filename_ptr); \
54 if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) { \
55 len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size; \
56 len &= sizeof(augmented_args.filename.value) - 1; \
57 } \
58 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
59 &augmented_args, len); \
60 return 0; \
61} \
62int syscall_exit(syscall)(struct syscall_exit_args *args) \
63{ \
64 return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \
65}
66
30struct syscall_enter_openat_args { 67struct syscall_enter_openat_args {
31 unsigned long long common_tp_fields; 68 unsigned long long common_tp_fields;
32 long syscall_nr; 69 long syscall_nr;
@@ -36,20 +73,101 @@ struct syscall_enter_openat_args {
36 long mode; 73 long mode;
37}; 74};
38 75
39struct augmented_enter_openat_args { 76augmented_filename_syscall(openat);
40 struct syscall_enter_openat_args args; 77
41 char filename[64]; 78struct syscall_enter_open_args {
79 unsigned long long common_tp_fields;
80 long syscall_nr;
81 char *filename_ptr;
82 long flags;
83 long mode;
84};
85
86augmented_filename_syscall(open);
87
88struct syscall_enter_inotify_add_watch_args {
89 unsigned long long common_tp_fields;
90 long syscall_nr;
91 long fd;
92 char *filename_ptr;
93 long mask;
94};
95
96augmented_filename_syscall(inotify_add_watch);
97
98struct statbuf;
99
100struct syscall_enter_newstat_args {
101 unsigned long long common_tp_fields;
102 long syscall_nr;
103 char *filename_ptr;
104 struct stat *statbuf;
42}; 105};
43 106
44int syscall_enter(openat)(struct syscall_enter_openat_args *args) 107augmented_filename_syscall(newstat);
45{ 108
46 struct augmented_enter_openat_args augmented_args; 109#ifndef _K_SS_MAXSIZE
110#define _K_SS_MAXSIZE 128
111#endif
47 112
48 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); 113#define augmented_sockaddr_syscall(syscall) \
49 probe_read_str(&augmented_args.filename, sizeof(augmented_args.filename), args->filename_ptr); 114struct augmented_enter_##syscall##_args { \
50 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, 115 struct syscall_enter_##syscall##_args args; \
51 &augmented_args, sizeof(augmented_args)); 116 struct sockaddr_storage addr; \
52 return 1; 117}; \
118int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
119{ \
120 struct augmented_enter_##syscall##_args augmented_args; \
121 unsigned long addrlen = sizeof(augmented_args.addr); \
122 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
123/* FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK */ \
124/* if (addrlen > augmented_args.args.addrlen) */ \
125/* addrlen = augmented_args.args.addrlen; */ \
126/* */ \
127 probe_read(&augmented_args.addr, addrlen, args->addr_ptr); \
128 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
129 &augmented_args, \
130 sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen); \
131 return 0; \
132} \
133int syscall_exit(syscall)(struct syscall_exit_args *args) \
134{ \
135 return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \
53} 136}
54 137
138struct sockaddr;
139
140struct syscall_enter_bind_args {
141 unsigned long long common_tp_fields;
142 long syscall_nr;
143 long fd;
144 struct sockaddr *addr_ptr;
145 unsigned long addrlen;
146};
147
148augmented_sockaddr_syscall(bind);
149
150struct syscall_enter_connect_args {
151 unsigned long long common_tp_fields;
152 long syscall_nr;
153 long fd;
154 struct sockaddr *addr_ptr;
155 unsigned long addrlen;
156};
157
158augmented_sockaddr_syscall(connect);
159
160struct syscall_enter_sendto_args {
161 unsigned long long common_tp_fields;
162 long syscall_nr;
163 long fd;
164 void *buff;
165 long len;
166 unsigned long flags;
167 struct sockaddr *addr_ptr;
168 long addr_len;
169};
170
171augmented_sockaddr_syscall(sendto);
172
55license(GPL); 173license(GPL);
diff --git a/tools/perf/examples/bpf/etcsnoop.c b/tools/perf/examples/bpf/etcsnoop.c
new file mode 100644
index 000000000000..b59e8812ee8c
--- /dev/null
+++ b/tools/perf/examples/bpf/etcsnoop.c
@@ -0,0 +1,80 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Augment the filename syscalls with the contents of the filename pointer argument
4 * filtering only those that do not start with /etc/.
5 *
6 * Test it with:
7 *
8 * perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null
9 *
10 * It'll catch some openat syscalls related to the dynamic linked and
11 * the last one should be the one for '/etc/passwd'.
12 *
13 * This matches what is marshalled into the raw_syscall:sys_enter payload
14 * expected by the 'perf trace' beautifiers, and can be used by them unmodified,
15 * which will be done as that feature is implemented in the next csets, for now
16 * it will appear in a dump done by the default tracepoint handler in 'perf trace',
17 * that uses bpf_output__fprintf() to just dump those contents, as done with
18 * the bpf-output event associated with the __bpf_output__ map declared in
19 * tools/perf/include/bpf/stdio.h.
20 */
21
22#include <stdio.h>
23
24struct bpf_map SEC("maps") __augmented_syscalls__ = {
25 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
26 .key_size = sizeof(int),
27 .value_size = sizeof(u32),
28 .max_entries = __NR_CPUS__,
29};
30
31struct augmented_filename {
32 int size;
33 int reserved;
34 char value[64];
35};
36
37#define augmented_filename_syscall_enter(syscall) \
38struct augmented_enter_##syscall##_args { \
39 struct syscall_enter_##syscall##_args args; \
40 struct augmented_filename filename; \
41}; \
42int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
43{ \
44 char etc[6] = "/etc/"; \
45 struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \
46 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
47 augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \
48 sizeof(augmented_args.filename.value), \
49 args->filename_ptr); \
50 if (__builtin_memcmp(augmented_args.filename.value, etc, 4) != 0) \
51 return 0; \
52 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
53 &augmented_args, \
54 (sizeof(augmented_args) - sizeof(augmented_args.filename.value) + \
55 augmented_args.filename.size)); \
56 return 0; \
57}
58
59struct syscall_enter_openat_args {
60 unsigned long long common_tp_fields;
61 long syscall_nr;
62 long dfd;
63 char *filename_ptr;
64 long flags;
65 long mode;
66};
67
68augmented_filename_syscall_enter(openat);
69
70struct syscall_enter_open_args {
71 unsigned long long common_tp_fields;
72 long syscall_nr;
73 char *filename_ptr;
74 long flags;
75 long mode;
76};
77
78augmented_filename_syscall_enter(open);
79
80license(GPL);
diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h
index 47897d65e799..52b6d87fe822 100644
--- a/tools/perf/include/bpf/bpf.h
+++ b/tools/perf/include/bpf/bpf.h
@@ -26,6 +26,9 @@ struct bpf_map {
26#define syscall_enter(name) \ 26#define syscall_enter(name) \
27 SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name 27 SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name
28 28
29#define syscall_exit(name) \
30 SEC("syscalls:sys_exit_" #name) syscall_exit_ ## name
31
29#define license(name) \ 32#define license(name) \
30char _license[] SEC("license") = #name; \ 33char _license[] SEC("license") = #name; \
31int _version SEC("version") = LINUX_VERSION_CODE; 34int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/include/bpf/linux/socket.h b/tools/perf/include/bpf/linux/socket.h
new file mode 100644
index 000000000000..7f844568dab8
--- /dev/null
+++ b/tools/perf/include/bpf/linux/socket.h
@@ -0,0 +1,24 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef _UAPI_LINUX_SOCKET_H
3#define _UAPI_LINUX_SOCKET_H
4
5/*
6 * Desired design of maximum size and alignment (see RFC2553)
7 */
8#define _K_SS_MAXSIZE 128 /* Implementation specific max size */
9#define _K_SS_ALIGNSIZE (__alignof__ (struct sockaddr *))
10 /* Implementation specific desired alignment */
11
12typedef unsigned short __kernel_sa_family_t;
13
14struct __kernel_sockaddr_storage {
15 __kernel_sa_family_t ss_family; /* address family */
16 /* Following field(s) are implementation specific */
17 char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
18 /* space to achieve desired size, */
19 /* _SS_MAXSIZE value minus size of ss_family */
20} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */
21
22#define sockaddr_storage __kernel_sockaddr_storage
23
24#endif /* _UAPI_LINUX_SOCKET_H */
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json
new file mode 100644
index 000000000000..abc98b018446
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json
@@ -0,0 +1,23 @@
1[
2 {
3 "ArchStdEvent": "BR_IMMED_SPEC",
4 },
5 {
6 "ArchStdEvent": "BR_RETURN_SPEC",
7 },
8 {
9 "ArchStdEvent": "BR_INDIRECT_SPEC",
10 },
11 {
12 "PublicDescription": "Mispredicted or not predicted branch speculatively executed",
13 "EventCode": "0x10",
14 "EventName": "BR_MIS_PRED",
15 "BriefDescription": "Branch mispredicted"
16 },
17 {
18 "PublicDescription": "Predictable branch speculatively executed",
19 "EventCode": "0x12",
20 "EventName": "BR_PRED",
21 "BriefDescription": "Predictable branch"
22 },
23]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json
new file mode 100644
index 000000000000..687b2629e1d1
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json
@@ -0,0 +1,26 @@
1[
2 {
3 "ArchStdEvent": "BUS_ACCESS_RD",
4 },
5 {
6 "ArchStdEvent": "BUS_ACCESS_WR",
7 },
8 {
9 "ArchStdEvent": "BUS_ACCESS_SHARED",
10 },
11 {
12 "ArchStdEvent": "BUS_ACCESS_NOT_SHARED",
13 },
14 {
15 "ArchStdEvent": "BUS_ACCESS_NORMAL",
16 },
17 {
18 "ArchStdEvent": "BUS_ACCESS_PERIPH",
19 },
20 {
21 "PublicDescription": "Bus access",
22 "EventCode": "0x19",
23 "EventName": "BUS_ACCESS",
24 "BriefDescription": "Bus access"
25 },
26]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json
new file mode 100644
index 000000000000..df9201434cb6
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json
@@ -0,0 +1,191 @@
1[
2 {
3 "ArchStdEvent": "L1D_CACHE_RD",
4 },
5 {
6 "ArchStdEvent": "L1D_CACHE_WR",
7 },
8 {
9 "ArchStdEvent": "L1D_CACHE_REFILL_RD",
10 },
11 {
12 "ArchStdEvent": "L1D_CACHE_INVAL",
13 },
14 {
15 "ArchStdEvent": "L1D_TLB_REFILL_RD",
16 },
17 {
18 "ArchStdEvent": "L1D_TLB_REFILL_WR",
19 },
20 {
21 "ArchStdEvent": "L2D_CACHE_RD",
22 },
23 {
24 "ArchStdEvent": "L2D_CACHE_WR",
25 },
26 {
27 "ArchStdEvent": "L2D_CACHE_REFILL_RD",
28 },
29 {
30 "ArchStdEvent": "L2D_CACHE_REFILL_WR",
31 },
32 {
33 "ArchStdEvent": "L2D_CACHE_WB_VICTIM",
34 },
35 {
36 "ArchStdEvent": "L2D_CACHE_WB_CLEAN",
37 },
38 {
39 "ArchStdEvent": "L2D_CACHE_INVAL",
40 },
41 {
42 "PublicDescription": "Level 1 instruction cache refill",
43 "EventCode": "0x01",
44 "EventName": "L1I_CACHE_REFILL",
45 "BriefDescription": "L1I cache refill"
46 },
47 {
48 "PublicDescription": "Level 1 instruction TLB refill",
49 "EventCode": "0x02",
50 "EventName": "L1I_TLB_REFILL",
51 "BriefDescription": "L1I TLB refill"
52 },
53 {
54 "PublicDescription": "Level 1 data cache refill",
55 "EventCode": "0x03",
56 "EventName": "L1D_CACHE_REFILL",
57 "BriefDescription": "L1D cache refill"
58 },
59 {
60 "PublicDescription": "Level 1 data cache access",
61 "EventCode": "0x04",
62 "EventName": "L1D_CACHE_ACCESS",
63 "BriefDescription": "L1D cache access"
64 },
65 {
66 "PublicDescription": "Level 1 data TLB refill",
67 "EventCode": "0x05",
68 "EventName": "L1D_TLB_REFILL",
69 "BriefDescription": "L1D TLB refill"
70 },
71 {
72 "PublicDescription": "Level 1 instruction cache access",
73 "EventCode": "0x14",
74 "EventName": "L1I_CACHE_ACCESS",
75 "BriefDescription": "L1I cache access"
76 },
77 {
78 "PublicDescription": "Level 2 data cache access",
79 "EventCode": "0x16",
80 "EventName": "L2D_CACHE_ACCESS",
81 "BriefDescription": "L2D cache access"
82 },
83 {
84 "PublicDescription": "Level 2 data refill",
85 "EventCode": "0x17",
86 "EventName": "L2D_CACHE_REFILL",
87 "BriefDescription": "L2D cache refill"
88 },
89 {
90 "PublicDescription": "Level 2 data cache, Write-Back",
91 "EventCode": "0x18",
92 "EventName": "L2D_CACHE_WB",
93 "BriefDescription": "L2D cache Write-Back"
94 },
95 {
96 "PublicDescription": "Level 1 data TLB access. This event counts any load or store operation which accesses the data L1 TLB",
97 "EventCode": "0x25",
98 "EventName": "L1D_TLB_ACCESS",
99 "BriefDescription": "L1D TLB access"
100 },
101 {
102 "PublicDescription": "Level 1 instruction TLB access. This event counts any instruction fetch which accesses the instruction L1 TLB",
103 "EventCode": "0x26",
104 "EventName": "L1I_TLB_ACCESS",
105 "BriefDescription": "L1I TLB access"
106 },
107 {
108 "PublicDescription": "Level 2 access to data TLB that caused a page table walk. This event counts on any data access which causes L2D_TLB_REFILL to count",
109 "EventCode": "0x34",
110 "EventName": "L2D_TLB_ACCESS",
111 "BriefDescription": "L2D TLB access"
112 },
113 {
114 "PublicDescription": "Level 2 access to instruciton TLB that caused a page table walk. This event counts on any instruciton access which causes L2I_TLB_REFILL to count",
115 "EventCode": "0x35",
116 "EventName": "L2I_TLB_ACCESS",
117 "BriefDescription": "L2D TLB access"
118 },
119 {
120 "PublicDescription": "Branch target buffer misprediction",
121 "EventCode": "0x102",
122 "EventName": "BTB_MIS_PRED",
123 "BriefDescription": "BTB misprediction"
124 },
125 {
126 "PublicDescription": "ITB miss",
127 "EventCode": "0x103",
128 "EventName": "ITB_MISS",
129 "BriefDescription": "ITB miss"
130 },
131 {
132 "PublicDescription": "DTB miss",
133 "EventCode": "0x104",
134 "EventName": "DTB_MISS",
135 "BriefDescription": "DTB miss"
136 },
137 {
138 "PublicDescription": "Level 1 data cache late miss",
139 "EventCode": "0x105",
140 "EventName": "L1D_CACHE_LATE_MISS",
141 "BriefDescription": "L1D cache late miss"
142 },
143 {
144 "PublicDescription": "Level 1 data cache prefetch request",
145 "EventCode": "0x106",
146 "EventName": "L1D_CACHE_PREFETCH",
147 "BriefDescription": "L1D cache prefetch"
148 },
149 {
150 "PublicDescription": "Level 2 data cache prefetch request",
151 "EventCode": "0x107",
152 "EventName": "L2D_CACHE_PREFETCH",
153 "BriefDescription": "L2D cache prefetch"
154 },
155 {
156 "PublicDescription": "Level 1 stage 2 TLB refill",
157 "EventCode": "0x111",
158 "EventName": "L1_STAGE2_TLB_REFILL",
159 "BriefDescription": "L1 stage 2 TLB refill"
160 },
161 {
162 "PublicDescription": "Page walk cache level-0 stage-1 hit",
163 "EventCode": "0x112",
164 "EventName": "PAGE_WALK_L0_STAGE1_HIT",
165 "BriefDescription": "Page walk, L0 stage-1 hit"
166 },
167 {
168 "PublicDescription": "Page walk cache level-1 stage-1 hit",
169 "EventCode": "0x113",
170 "EventName": "PAGE_WALK_L1_STAGE1_HIT",
171 "BriefDescription": "Page walk, L1 stage-1 hit"
172 },
173 {
174 "PublicDescription": "Page walk cache level-2 stage-1 hit",
175 "EventCode": "0x114",
176 "EventName": "PAGE_WALK_L2_STAGE1_HIT",
177 "BriefDescription": "Page walk, L2 stage-1 hit"
178 },
179 {
180 "PublicDescription": "Page walk cache level-1 stage-2 hit",
181 "EventCode": "0x115",
182 "EventName": "PAGE_WALK_L1_STAGE2_HIT",
183 "BriefDescription": "Page walk, L1 stage-2 hit"
184 },
185 {
186 "PublicDescription": "Page walk cache level-2 stage-2 hit",
187 "EventCode": "0x116",
188 "EventName": "PAGE_WALK_L2_STAGE2_HIT",
189 "BriefDescription": "Page walk, L2 stage-2 hit"
190 },
191]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json
new file mode 100644
index 000000000000..38cd1f1a70dc
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json
@@ -0,0 +1,20 @@
1[
2 {
3 "PublicDescription": "The number of core clock cycles",
4 "EventCode": "0x11",
5 "EventName": "CPU_CYCLES",
6 "BriefDescription": "Clock cycles"
7 },
8 {
9 "PublicDescription": "FSU clocking gated off cycle",
10 "EventCode": "0x101",
11 "EventName": "FSU_CLOCK_OFF_CYCLES",
12 "BriefDescription": "FSU clocking gated off cycle"
13 },
14 {
15 "PublicDescription": "Wait state cycle",
16 "EventCode": "0x110",
17 "EventName": "Wait_CYCLES",
18 "BriefDescription": "Wait state cycle"
19 },
20]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json
deleted file mode 100644
index bc03c06c3918..000000000000
--- a/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json
+++ /dev/null
@@ -1,32 +0,0 @@
1[
2 {
3 "ArchStdEvent": "L1D_CACHE_RD",
4 },
5 {
6 "ArchStdEvent": "L1D_CACHE_WR",
7 },
8 {
9 "ArchStdEvent": "L1D_CACHE_REFILL_RD",
10 },
11 {
12 "ArchStdEvent": "L1D_CACHE_REFILL_WR",
13 },
14 {
15 "ArchStdEvent": "L1D_TLB_REFILL_RD",
16 },
17 {
18 "ArchStdEvent": "L1D_TLB_REFILL_WR",
19 },
20 {
21 "ArchStdEvent": "L1D_TLB_RD",
22 },
23 {
24 "ArchStdEvent": "L1D_TLB_WR",
25 },
26 {
27 "ArchStdEvent": "BUS_ACCESS_RD",
28 },
29 {
30 "ArchStdEvent": "BUS_ACCESS_WR",
31 }
32]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json
new file mode 100644
index 000000000000..3720dc28a15f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json
@@ -0,0 +1,50 @@
1[
2 {
3 "ArchStdEvent": "EXC_UNDEF",
4 },
5 {
6 "ArchStdEvent": "EXC_SVC",
7 },
8 {
9 "ArchStdEvent": "EXC_PABORT",
10 },
11 {
12 "ArchStdEvent": "EXC_DABORT",
13 },
14 {
15 "ArchStdEvent": "EXC_IRQ",
16 },
17 {
18 "ArchStdEvent": "EXC_FIQ",
19 },
20 {
21 "ArchStdEvent": "EXC_HVC",
22 },
23 {
24 "ArchStdEvent": "EXC_TRAP_PABORT",
25 },
26 {
27 "ArchStdEvent": "EXC_TRAP_DABORT",
28 },
29 {
30 "ArchStdEvent": "EXC_TRAP_OTHER",
31 },
32 {
33 "ArchStdEvent": "EXC_TRAP_IRQ",
34 },
35 {
36 "ArchStdEvent": "EXC_TRAP_FIQ",
37 },
38 {
39 "PublicDescription": "Exception taken",
40 "EventCode": "0x09",
41 "EventName": "EXC_TAKEN",
42 "BriefDescription": "Exception taken"
43 },
44 {
45 "PublicDescription": "Instruction architecturally executed, condition check pass, exception return",
46 "EventCode": "0x0a",
47 "EventName": "EXC_RETURN",
48 "BriefDescription": "Exception return"
49 },
50]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json
new file mode 100644
index 000000000000..82cf753e6472
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json
@@ -0,0 +1,89 @@
1[
2 {
3 "ArchStdEvent": "LD_SPEC",
4 },
5 {
6 "ArchStdEvent": "ST_SPEC",
7 },
8 {
9 "ArchStdEvent": "LDST_SPEC",
10 },
11 {
12 "ArchStdEvent": "DP_SPEC",
13 },
14 {
15 "ArchStdEvent": "ASE_SPEC",
16 },
17 {
18 "ArchStdEvent": "VFP_SPEC",
19 },
20 {
21 "ArchStdEvent": "PC_WRITE_SPEC",
22 },
23 {
24 "ArchStdEvent": "CRYPTO_SPEC",
25 },
26 {
27 "ArchStdEvent": "ISB_SPEC",
28 },
29 {
30 "ArchStdEvent": "DSB_SPEC",
31 },
32 {
33 "ArchStdEvent": "DMB_SPEC",
34 },
35 {
36 "ArchStdEvent": "RC_LD_SPEC",
37 },
38 {
39 "ArchStdEvent": "RC_ST_SPEC",
40 },
41 {
42 "PublicDescription": "Instruction architecturally executed, software increment",
43 "EventCode": "0x00",
44 "EventName": "SW_INCR",
45 "BriefDescription": "Software increment"
46 },
47 {
48 "PublicDescription": "Instruction architecturally executed",
49 "EventCode": "0x08",
50 "EventName": "INST_RETIRED",
51 "BriefDescription": "Instruction retired"
52 },
53 {
54 "PublicDescription": "Instruction architecturally executed, condition code check pass, write to CONTEXTIDR",
55 "EventCode": "0x0b",
56 "EventName": "CID_WRITE_RETIRED",
57 "BriefDescription": "Write to CONTEXTIDR"
58 },
59 {
60 "PublicDescription": "Operation speculatively executed",
61 "EventCode": "0x1b",
62 "EventName": "INST_SPEC",
63 "BriefDescription": "Speculatively executed"
64 },
65 {
66 "PublicDescription": "Instruction architecturally executed (condition check pass), write to TTBR",
67 "EventCode": "0x1c",
68 "EventName": "TTBR_WRITE_RETIRED",
69 "BriefDescription": "Instruction executed, TTBR write"
70 },
71 {
72 "PublicDescription": "Instruction architecturally executed, branch. This event counts all branches, taken or not. This excludes exception entries, debug entries and CCFAIL branches",
73 "EventCode": "0x21",
74 "EventName": "BR_RETIRED",
75 "BriefDescription": "Branch retired"
76 },
77 {
78 "PublicDescription": "Instruction architecturally executed, mispredicted branch. This event counts any branch counted by BR_RETIRED which is not correctly predicted and causes a pipeline flush",
79 "EventCode": "0x22",
80 "EventName": "BR_MISPRED_RETIRED",
81 "BriefDescription": "Mispredicted branch retired"
82 },
83 {
84 "PublicDescription": "Operation speculatively executed, NOP",
85 "EventCode": "0x100",
86 "EventName": "NOP_SPEC",
87 "BriefDescription": "Speculatively executed, NOP"
88 },
89]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json
new file mode 100644
index 000000000000..2aecc5c2347d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json
@@ -0,0 +1,14 @@
1[
2 {
3 "ArchStdEvent": "LDREX_SPEC",
4 },
5 {
6 "ArchStdEvent": "STREX_PASS_SPEC",
7 },
8 {
9 "ArchStdEvent": "STREX_FAIL_SPEC",
10 },
11 {
12 "ArchStdEvent": "STREX_SPEC",
13 },
14]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json
new file mode 100644
index 000000000000..08508697b318
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json
@@ -0,0 +1,29 @@
1[
2 {
3 "ArchStdEvent": "MEM_ACCESS_RD",
4 },
5 {
6 "ArchStdEvent": "MEM_ACCESS_WR",
7 },
8 {
9 "ArchStdEvent": "UNALIGNED_LD_SPEC",
10 },
11 {
12 "ArchStdEvent": "UNALIGNED_ST_SPEC",
13 },
14 {
15 "ArchStdEvent": "UNALIGNED_LDST_SPEC",
16 },
17 {
18 "PublicDescription": "Data memory access",
19 "EventCode": "0x13",
20 "EventName": "MEM_ACCESS",
21 "BriefDescription": "Memory access"
22 },
23 {
24 "PublicDescription": "Local memory error. This event counts any correctable or uncorrectable memory error (ECC or parity) in the protected core RAMs",
25 "EventCode": "0x1a",
26 "EventName": "MEM_ERROR",
27 "BriefDescription": "Memory error"
28 },
29]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json
new file mode 100644
index 000000000000..e2087de586bf
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json
@@ -0,0 +1,50 @@
1[
2 {
3 "PublicDescription": "Decode starved for instruction cycle",
4 "EventCode": "0x108",
5 "EventName": "DECODE_STALL",
6 "BriefDescription": "Decode starved"
7 },
8 {
9 "PublicDescription": "Op dispatch stalled cycle",
10 "EventCode": "0x109",
11 "EventName": "DISPATCH_STALL",
12 "BriefDescription": "Dispatch stalled"
13 },
14 {
15 "PublicDescription": "IXA Op non-issue",
16 "EventCode": "0x10a",
17 "EventName": "IXA_STALL",
18 "BriefDescription": "IXA stalled"
19 },
20 {
21 "PublicDescription": "IXB Op non-issue",
22 "EventCode": "0x10b",
23 "EventName": "IXB_STALL",
24 "BriefDescription": "IXB stalled"
25 },
26 {
27 "PublicDescription": "BX Op non-issue",
28 "EventCode": "0x10c",
29 "EventName": "BX_STALL",
30 "BriefDescription": "BX stalled"
31 },
32 {
33 "PublicDescription": "LX Op non-issue",
34 "EventCode": "0x10d",
35 "EventName": "LX_STALL",
36 "BriefDescription": "LX stalled"
37 },
38 {
39 "PublicDescription": "SX Op non-issue",
40 "EventCode": "0x10e",
41 "EventName": "SX_STALL",
42 "BriefDescription": "SX stalled"
43 },
44 {
45 "PublicDescription": "FX Op non-issue",
46 "EventCode": "0x10f",
47 "EventName": "FX_STALL",
48 "BriefDescription": "FX stalled"
49 },
50]
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
index d40498f2cb1e..635c09fda1d9 100644
--- a/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
@@ -188,7 +188,7 @@
188 "Counter": "0,1,2,3", 188 "Counter": "0,1,2,3",
189 "EventCode": "0xb", 189 "EventCode": "0xb",
190 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES", 190 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
191 "Filter": "filter_band0=1200", 191 "Filter": "filter_band0=12",
192 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 192 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
193 "MetricName": "freq_ge_1200mhz_cycles %", 193 "MetricName": "freq_ge_1200mhz_cycles %",
194 "PerPkg": "1", 194 "PerPkg": "1",
@@ -199,7 +199,7 @@
199 "Counter": "0,1,2,3", 199 "Counter": "0,1,2,3",
200 "EventCode": "0xc", 200 "EventCode": "0xc",
201 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES", 201 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
202 "Filter": "filter_band1=2000", 202 "Filter": "filter_band1=20",
203 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 203 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
204 "MetricName": "freq_ge_2000mhz_cycles %", 204 "MetricName": "freq_ge_2000mhz_cycles %",
205 "PerPkg": "1", 205 "PerPkg": "1",
@@ -210,7 +210,7 @@
210 "Counter": "0,1,2,3", 210 "Counter": "0,1,2,3",
211 "EventCode": "0xd", 211 "EventCode": "0xd",
212 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES", 212 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
213 "Filter": "filter_band2=3000", 213 "Filter": "filter_band2=30",
214 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 214 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
215 "MetricName": "freq_ge_3000mhz_cycles %", 215 "MetricName": "freq_ge_3000mhz_cycles %",
216 "PerPkg": "1", 216 "PerPkg": "1",
@@ -221,7 +221,7 @@
221 "Counter": "0,1,2,3", 221 "Counter": "0,1,2,3",
222 "EventCode": "0xe", 222 "EventCode": "0xe",
223 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES", 223 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
224 "Filter": "filter_band3=4000", 224 "Filter": "filter_band3=40",
225 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 225 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
226 "MetricName": "freq_ge_4000mhz_cycles %", 226 "MetricName": "freq_ge_4000mhz_cycles %",
227 "PerPkg": "1", 227 "PerPkg": "1",
@@ -232,7 +232,7 @@
232 "Counter": "0,1,2,3", 232 "Counter": "0,1,2,3",
233 "EventCode": "0xb", 233 "EventCode": "0xb",
234 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS", 234 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
235 "Filter": "edge=1,filter_band0=1200", 235 "Filter": "edge=1,filter_band0=12",
236 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 236 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
237 "MetricName": "freq_ge_1200mhz_cycles %", 237 "MetricName": "freq_ge_1200mhz_cycles %",
238 "PerPkg": "1", 238 "PerPkg": "1",
@@ -243,7 +243,7 @@
243 "Counter": "0,1,2,3", 243 "Counter": "0,1,2,3",
244 "EventCode": "0xc", 244 "EventCode": "0xc",
245 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS", 245 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
246 "Filter": "edge=1,filter_band1=2000", 246 "Filter": "edge=1,filter_band1=20",
247 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 247 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
248 "MetricName": "freq_ge_2000mhz_cycles %", 248 "MetricName": "freq_ge_2000mhz_cycles %",
249 "PerPkg": "1", 249 "PerPkg": "1",
@@ -254,7 +254,7 @@
254 "Counter": "0,1,2,3", 254 "Counter": "0,1,2,3",
255 "EventCode": "0xd", 255 "EventCode": "0xd",
256 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS", 256 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
257 "Filter": "edge=1,filter_band2=4000", 257 "Filter": "edge=1,filter_band2=30",
258 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 258 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
259 "MetricName": "freq_ge_3000mhz_cycles %", 259 "MetricName": "freq_ge_3000mhz_cycles %",
260 "PerPkg": "1", 260 "PerPkg": "1",
@@ -265,7 +265,7 @@
265 "Counter": "0,1,2,3", 265 "Counter": "0,1,2,3",
266 "EventCode": "0xe", 266 "EventCode": "0xe",
267 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS", 267 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
268 "Filter": "edge=1,filter_band3=4000", 268 "Filter": "edge=1,filter_band3=40",
269 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 269 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
270 "MetricName": "freq_ge_4000mhz_cycles %", 270 "MetricName": "freq_ge_4000mhz_cycles %",
271 "PerPkg": "1", 271 "PerPkg": "1",
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
index 16034bfd06dd..8755693d86c6 100644
--- a/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
@@ -187,7 +187,7 @@
187 "Counter": "0,1,2,3", 187 "Counter": "0,1,2,3",
188 "EventCode": "0xb", 188 "EventCode": "0xb",
189 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES", 189 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
190 "Filter": "filter_band0=1200", 190 "Filter": "filter_band0=12",
191 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 191 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
192 "MetricName": "freq_ge_1200mhz_cycles %", 192 "MetricName": "freq_ge_1200mhz_cycles %",
193 "PerPkg": "1", 193 "PerPkg": "1",
@@ -198,7 +198,7 @@
198 "Counter": "0,1,2,3", 198 "Counter": "0,1,2,3",
199 "EventCode": "0xc", 199 "EventCode": "0xc",
200 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES", 200 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
201 "Filter": "filter_band1=2000", 201 "Filter": "filter_band1=20",
202 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 202 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
203 "MetricName": "freq_ge_2000mhz_cycles %", 203 "MetricName": "freq_ge_2000mhz_cycles %",
204 "PerPkg": "1", 204 "PerPkg": "1",
@@ -209,7 +209,7 @@
209 "Counter": "0,1,2,3", 209 "Counter": "0,1,2,3",
210 "EventCode": "0xd", 210 "EventCode": "0xd",
211 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES", 211 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
212 "Filter": "filter_band2=3000", 212 "Filter": "filter_band2=30",
213 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 213 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
214 "MetricName": "freq_ge_3000mhz_cycles %", 214 "MetricName": "freq_ge_3000mhz_cycles %",
215 "PerPkg": "1", 215 "PerPkg": "1",
@@ -220,7 +220,7 @@
220 "Counter": "0,1,2,3", 220 "Counter": "0,1,2,3",
221 "EventCode": "0xe", 221 "EventCode": "0xe",
222 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES", 222 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
223 "Filter": "filter_band3=4000", 223 "Filter": "filter_band3=40",
224 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 224 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
225 "MetricName": "freq_ge_4000mhz_cycles %", 225 "MetricName": "freq_ge_4000mhz_cycles %",
226 "PerPkg": "1", 226 "PerPkg": "1",
@@ -231,7 +231,7 @@
231 "Counter": "0,1,2,3", 231 "Counter": "0,1,2,3",
232 "EventCode": "0xb", 232 "EventCode": "0xb",
233 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS", 233 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
234 "Filter": "edge=1,filter_band0=1200", 234 "Filter": "edge=1,filter_band0=12",
235 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 235 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
236 "MetricName": "freq_ge_1200mhz_cycles %", 236 "MetricName": "freq_ge_1200mhz_cycles %",
237 "PerPkg": "1", 237 "PerPkg": "1",
@@ -242,7 +242,7 @@
242 "Counter": "0,1,2,3", 242 "Counter": "0,1,2,3",
243 "EventCode": "0xc", 243 "EventCode": "0xc",
244 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS", 244 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
245 "Filter": "edge=1,filter_band1=2000", 245 "Filter": "edge=1,filter_band1=20",
246 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 246 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
247 "MetricName": "freq_ge_2000mhz_cycles %", 247 "MetricName": "freq_ge_2000mhz_cycles %",
248 "PerPkg": "1", 248 "PerPkg": "1",
@@ -253,7 +253,7 @@
253 "Counter": "0,1,2,3", 253 "Counter": "0,1,2,3",
254 "EventCode": "0xd", 254 "EventCode": "0xd",
255 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS", 255 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
256 "Filter": "edge=1,filter_band2=4000", 256 "Filter": "edge=1,filter_band2=30",
257 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 257 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
258 "MetricName": "freq_ge_3000mhz_cycles %", 258 "MetricName": "freq_ge_3000mhz_cycles %",
259 "PerPkg": "1", 259 "PerPkg": "1",
@@ -264,7 +264,7 @@
264 "Counter": "0,1,2,3", 264 "Counter": "0,1,2,3",
265 "EventCode": "0xe", 265 "EventCode": "0xe",
266 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS", 266 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
267 "Filter": "edge=1,filter_band3=4000", 267 "Filter": "edge=1,filter_band3=40",
268 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 268 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
269 "MetricName": "freq_ge_4000mhz_cycles %", 269 "MetricName": "freq_ge_4000mhz_cycles %",
270 "PerPkg": "1", 270 "PerPkg": "1",
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index efcaf6cac2eb..e46f51b17513 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -204,14 +204,23 @@ from ctypes import *
204libpq = CDLL("libpq.so.5") 204libpq = CDLL("libpq.so.5")
205PQconnectdb = libpq.PQconnectdb 205PQconnectdb = libpq.PQconnectdb
206PQconnectdb.restype = c_void_p 206PQconnectdb.restype = c_void_p
207PQconnectdb.argtypes = [ c_char_p ]
207PQfinish = libpq.PQfinish 208PQfinish = libpq.PQfinish
209PQfinish.argtypes = [ c_void_p ]
208PQstatus = libpq.PQstatus 210PQstatus = libpq.PQstatus
211PQstatus.restype = c_int
212PQstatus.argtypes = [ c_void_p ]
209PQexec = libpq.PQexec 213PQexec = libpq.PQexec
210PQexec.restype = c_void_p 214PQexec.restype = c_void_p
215PQexec.argtypes = [ c_void_p, c_char_p ]
211PQresultStatus = libpq.PQresultStatus 216PQresultStatus = libpq.PQresultStatus
217PQresultStatus.restype = c_int
218PQresultStatus.argtypes = [ c_void_p ]
212PQputCopyData = libpq.PQputCopyData 219PQputCopyData = libpq.PQputCopyData
220PQputCopyData.restype = c_int
213PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ] 221PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ]
214PQputCopyEnd = libpq.PQputCopyEnd 222PQputCopyEnd = libpq.PQputCopyEnd
223PQputCopyEnd.restype = c_int
215PQputCopyEnd.argtypes = [ c_void_p, c_void_p ] 224PQputCopyEnd.argtypes = [ c_void_p, c_void_p ]
216 225
217sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 226sys.path.append(os.environ['PERF_EXEC_PATH'] + \
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py
index f827bf77e9d2..e4bb82c8aba9 100644
--- a/tools/perf/scripts/python/export-to-sqlite.py
+++ b/tools/perf/scripts/python/export-to-sqlite.py
@@ -440,7 +440,11 @@ def branch_type_table(*x):
440 440
441def sample_table(*x): 441def sample_table(*x):
442 if branches: 442 if branches:
443 bind_exec(sample_query, 18, x) 443 for xx in x[0:15]:
444 sample_query.addBindValue(str(xx))
445 for xx in x[19:22]:
446 sample_query.addBindValue(str(xx))
447 do_query_(sample_query)
444 else: 448 else:
445 bind_exec(sample_query, 22, x) 449 bind_exec(sample_query, 22, x)
446 450
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 6c108fa79ae3..0b2b8305c965 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -21,6 +21,7 @@ perf-y += python-use.o
21perf-y += bp_signal.o 21perf-y += bp_signal.o
22perf-y += bp_signal_overflow.o 22perf-y += bp_signal_overflow.o
23perf-y += bp_account.o 23perf-y += bp_account.o
24perf-y += wp.o
24perf-y += task-exit.o 25perf-y += task-exit.o
25perf-y += sw-clock.o 26perf-y += sw-clock.o
26perf-y += mmap-thread-lookup.o 27perf-y += mmap-thread-lookup.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d7a5e1b9aa6f..12c09e0ece71 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -121,6 +121,16 @@ static struct test generic_tests[] = {
121 .is_supported = test__bp_signal_is_supported, 121 .is_supported = test__bp_signal_is_supported,
122 }, 122 },
123 { 123 {
124 .desc = "Watchpoint",
125 .func = test__wp,
126 .is_supported = test__wp_is_supported,
127 .subtest = {
128 .skip_if_fail = false,
129 .get_nr = test__wp_subtest_get_nr,
130 .get_desc = test__wp_subtest_get_desc,
131 },
132 },
133 {
124 .desc = "Number of exit events of a simple workload", 134 .desc = "Number of exit events of a simple workload",
125 .func = test__task_exit, 135 .func = test__task_exit,
126 }, 136 },
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 699561fa512c..5f8501c68da4 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -8,7 +8,7 @@
8static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, 8static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
9 int size, bool should_be_signed) 9 int size, bool should_be_signed)
10{ 10{
11 struct format_field *field = perf_evsel__field(evsel, name); 11 struct tep_format_field *field = perf_evsel__field(evsel, name);
12 int is_signed; 12 int is_signed;
13 int ret = 0; 13 int ret = 0;
14 14
@@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
17 return -1; 17 return -1;
18 } 18 }
19 19
20 is_signed = !!(field->flags | FIELD_IS_SIGNED); 20 is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED);
21 if (should_be_signed && !is_signed) { 21 if (should_be_signed && !is_signed) {
22 pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", 22 pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
23 evsel->name, name, is_signed, should_be_signed); 23 evsel->name, name, is_signed, should_be_signed);
diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index 3013ac8f83d0..cab7b0aea6ea 100755
--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -48,7 +48,7 @@ trace_libc_inet_pton_backtrace() {
48 *) 48 *)
49 eventattr='max-stack=3' 49 eventattr='max-stack=3'
50 echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected 50 echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected
51 echo ".*\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected 51 echo ".*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$" >> $expected
52 ;; 52 ;;
53 esac 53 esac
54 54
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index a9760e790563..b82f55fcc294 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -59,6 +59,9 @@ int test__python_use(struct test *test, int subtest);
59int test__bp_signal(struct test *test, int subtest); 59int test__bp_signal(struct test *test, int subtest);
60int test__bp_signal_overflow(struct test *test, int subtest); 60int test__bp_signal_overflow(struct test *test, int subtest);
61int test__bp_accounting(struct test *test, int subtest); 61int test__bp_accounting(struct test *test, int subtest);
62int test__wp(struct test *test, int subtest);
63const char *test__wp_subtest_get_desc(int subtest);
64int test__wp_subtest_get_nr(void);
62int test__task_exit(struct test *test, int subtest); 65int test__task_exit(struct test *test, int subtest);
63int test__mem(struct test *test, int subtest); 66int test__mem(struct test *test, int subtest);
64int test__sw_clock_freq(struct test *test, int subtest); 67int test__sw_clock_freq(struct test *test, int subtest);
@@ -106,6 +109,7 @@ int test__unit_number__scnprint(struct test *test, int subtest);
106int test__mem2node(struct test *t, int subtest); 109int test__mem2node(struct test *t, int subtest);
107 110
108bool test__bp_signal_is_supported(void); 111bool test__bp_signal_is_supported(void);
112bool test__wp_is_supported(void);
109 113
110#if defined(__arm__) || defined(__aarch64__) 114#if defined(__arm__) || defined(__aarch64__)
111#ifdef HAVE_DWARF_UNWIND_SUPPORT 115#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/wp.c b/tools/perf/tests/wp.c
new file mode 100644
index 000000000000..f89e6806557b
--- /dev/null
+++ b/tools/perf/tests/wp.c
@@ -0,0 +1,241 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <stdlib.h>
3#include <sys/ioctl.h>
4#include <linux/hw_breakpoint.h>
5#include "tests.h"
6#include "debug.h"
7#include "cloexec.h"
8
9#define WP_TEST_ASSERT_VAL(fd, text, val) \
10do { \
11 long long count; \
12 wp_read(fd, &count, sizeof(long long)); \
13 TEST_ASSERT_VAL(text, count == val); \
14} while (0)
15
16volatile u64 data1;
17volatile u8 data2[3];
18
19static int wp_read(int fd, long long *count, int size)
20{
21 int ret = read(fd, count, size);
22
23 if (ret != size) {
24 pr_debug("failed to read: %d\n", ret);
25 return -1;
26 }
27 return 0;
28}
29
30static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type,
31 void *wp_addr, unsigned long wp_len)
32{
33 memset(attr, 0, sizeof(struct perf_event_attr));
34 attr->type = PERF_TYPE_BREAKPOINT;
35 attr->size = sizeof(struct perf_event_attr);
36 attr->config = 0;
37 attr->bp_type = wp_type;
38 attr->bp_addr = (unsigned long)wp_addr;
39 attr->bp_len = wp_len;
40 attr->sample_period = 1;
41 attr->sample_type = PERF_SAMPLE_IP;
42 attr->exclude_kernel = 1;
43 attr->exclude_hv = 1;
44}
45
46static int __event(int wp_type, void *wp_addr, unsigned long wp_len)
47{
48 int fd;
49 struct perf_event_attr attr;
50
51 get__perf_event_attr(&attr, wp_type, wp_addr, wp_len);
52 fd = sys_perf_event_open(&attr, 0, -1, -1,
53 perf_event_open_cloexec_flag());
54 if (fd < 0)
55 pr_debug("failed opening event %x\n", attr.bp_type);
56
57 return fd;
58}
59
60static int wp_ro_test(void)
61{
62 int fd;
63 unsigned long tmp, tmp1 = rand();
64
65 fd = __event(HW_BREAKPOINT_R, (void *)&data1, sizeof(data1));
66 if (fd < 0)
67 return -1;
68
69 tmp = data1;
70 WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
71
72 data1 = tmp1 + tmp;
73 WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
74
75 close(fd);
76 return 0;
77}
78
79static int wp_wo_test(void)
80{
81 int fd;
82 unsigned long tmp, tmp1 = rand();
83
84 fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
85 if (fd < 0)
86 return -1;
87
88 tmp = data1;
89 WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 0);
90
91 data1 = tmp1 + tmp;
92 WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 1);
93
94 close(fd);
95 return 0;
96}
97
98static int wp_rw_test(void)
99{
100 int fd;
101 unsigned long tmp, tmp1 = rand();
102
103 fd = __event(HW_BREAKPOINT_R | HW_BREAKPOINT_W, (void *)&data1,
104 sizeof(data1));
105 if (fd < 0)
106 return -1;
107
108 tmp = data1;
109 WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 1);
110
111 data1 = tmp1 + tmp;
112 WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 2);
113
114 close(fd);
115 return 0;
116}
117
118static int wp_modify_test(void)
119{
120 int fd, ret;
121 unsigned long tmp = rand();
122 struct perf_event_attr new_attr;
123
124 fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
125 if (fd < 0)
126 return -1;
127
128 data1 = tmp;
129 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
130
131 /* Modify watchpoint with disabled = 1 */
132 get__perf_event_attr(&new_attr, HW_BREAKPOINT_W, (void *)&data2[0],
133 sizeof(u8) * 2);
134 new_attr.disabled = 1;
135 ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr);
136 if (ret < 0) {
137 pr_debug("ioctl(PERF_EVENT_IOC_MODIFY_ATTRIBUTES) failed\n");
138 close(fd);
139 return ret;
140 }
141
142 data2[1] = tmp; /* Not Counted */
143 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
144
145 /* Enable the event */
146 ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
147 if (ret < 0) {
148 pr_debug("Failed to enable event\n");
149 close(fd);
150 return ret;
151 }
152
153 data2[1] = tmp; /* Counted */
154 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
155
156 data2[2] = tmp; /* Not Counted */
157 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
158
159 close(fd);
160 return 0;
161}
162
163static bool wp_ro_supported(void)
164{
165#if defined (__x86_64__) || defined (__i386__)
166 return false;
167#else
168 return true;
169#endif
170}
171
172static void wp_ro_skip_msg(void)
173{
174#if defined (__x86_64__) || defined (__i386__)
175 pr_debug("Hardware does not support read only watchpoints.\n");
176#endif
177}
178
179static struct {
180 const char *desc;
181 int (*target_func)(void);
182 bool (*is_supported)(void);
183 void (*skip_msg)(void);
184} wp_testcase_table[] = {
185 {
186 .desc = "Read Only Watchpoint",
187 .target_func = &wp_ro_test,
188 .is_supported = &wp_ro_supported,
189 .skip_msg = &wp_ro_skip_msg,
190 },
191 {
192 .desc = "Write Only Watchpoint",
193 .target_func = &wp_wo_test,
194 },
195 {
196 .desc = "Read / Write Watchpoint",
197 .target_func = &wp_rw_test,
198 },
199 {
200 .desc = "Modify Watchpoint",
201 .target_func = &wp_modify_test,
202 },
203};
204
205int test__wp_subtest_get_nr(void)
206{
207 return (int)ARRAY_SIZE(wp_testcase_table);
208}
209
210const char *test__wp_subtest_get_desc(int i)
211{
212 if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table))
213 return NULL;
214 return wp_testcase_table[i].desc;
215}
216
217int test__wp(struct test *test __maybe_unused, int i)
218{
219 if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table))
220 return TEST_FAIL;
221
222 if (wp_testcase_table[i].is_supported &&
223 !wp_testcase_table[i].is_supported()) {
224 wp_testcase_table[i].skip_msg();
225 return TEST_SKIP;
226 }
227
228 return !wp_testcase_table[i].target_func() ? TEST_OK : TEST_FAIL;
229}
230
231/* The s390 so far does not have support for
232 * instruction breakpoint using the perf_event_open() system call.
233 */
234bool test__wp_is_supported(void)
235{
236#if defined(__s390x__)
237 return false;
238#else
239 return true;
240#endif
241}
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index f528ba35e140..c3b0afd67760 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -7,5 +7,6 @@ endif
7libperf-y += kcmp.o 7libperf-y += kcmp.o
8libperf-y += pkey_alloc.o 8libperf-y += pkey_alloc.o
9libperf-y += prctl.o 9libperf-y += prctl.o
10libperf-y += sockaddr.o
10libperf-y += socket.o 11libperf-y += socket.o
11libperf-y += statx.o 12libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 9615af5d412b..2570152d3909 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -30,9 +30,36 @@ struct thread;
30 30
31size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size); 31size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size);
32 32
33extern struct strarray strarray__socket_families;
34
35/**
36 * augmented_arg: extra payload for syscall pointer arguments
37
38 * If perf_sample->raw_size is more than what a syscall sys_enter_FOO puts,
39 * then its the arguments contents, so that we can show more than just a
40 * pointer. This will be done initially with eBPF, the start of that is at the
41 * tools/perf/examples/bpf/augmented_syscalls.c example for the openat, but
42 * will eventually be done automagically caching the running kernel tracefs
43 * events data into an eBPF C script, that then gets compiled and its .o file
44 * cached for subsequent use. For char pointers like the ones for 'open' like
45 * syscalls its easy, for the rest we should use DWARF or better, BTF, much
46 * more compact.
47 *
48 * @size: 8 if all we need is an integer, otherwise all of the augmented arg.
49 * @int_arg: will be used for integer like pointer contents, like 'accept's 'upeer_addrlen'
50 * @value: u64 aligned, for structs, pathnames
51 */
52struct augmented_arg {
53 int size;
54 int int_arg;
55 u64 value[];
56};
57
33/** 58/**
34 * @val: value of syscall argument being formatted 59 * @val: value of syscall argument being formatted
35 * @args: All the args, use syscall_args__val(arg, nth) to access one 60 * @args: All the args, use syscall_args__val(arg, nth) to access one
61 * @augmented_args: Extra data that can be collected, for instance, with eBPF for expanding the pathname for open, etc
62 * @augmented_args_size: augmented_args total payload size
36 * @thread: tid state (maps, pid, tid, etc) 63 * @thread: tid state (maps, pid, tid, etc)
37 * @trace: 'perf trace' internals: all threads, etc 64 * @trace: 'perf trace' internals: all threads, etc
38 * @parm: private area, may be an strarray, for instance 65 * @parm: private area, may be an strarray, for instance
@@ -43,6 +70,10 @@ size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_
43struct syscall_arg { 70struct syscall_arg {
44 unsigned long val; 71 unsigned long val;
45 unsigned char *args; 72 unsigned char *args;
73 struct {
74 struct augmented_arg *args;
75 int size;
76 } augmented;
46 struct thread *thread; 77 struct thread *thread;
47 struct trace *trace; 78 struct trace *trace;
48 void *parm; 79 void *parm;
@@ -106,6 +137,9 @@ size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_a
106size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg); 137size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg);
107#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3 138#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3
108 139
140size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg);
141#define SCA_SOCKADDR syscall_arg__scnprintf_sockaddr
142
109size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg); 143size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg);
110#define SCA_SK_PROTO syscall_arg__scnprintf_socket_protocol 144#define SCA_SK_PROTO syscall_arg__scnprintf_socket_protocol
111 145
diff --git a/tools/perf/trace/beauty/sockaddr.c b/tools/perf/trace/beauty/sockaddr.c
new file mode 100644
index 000000000000..71a79f72d9d9
--- /dev/null
+++ b/tools/perf/trace/beauty/sockaddr.c
@@ -0,0 +1,76 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3
4#include "trace/beauty/beauty.h"
5#include <sys/socket.h>
6#include <sys/types.h>
7#include <sys/un.h>
8#include <arpa/inet.h>
9
10static const char *socket_families[] = {
11 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
12 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
13 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
14 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
15 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
16 "ALG", "NFC", "VSOCK",
17};
18DEFINE_STRARRAY(socket_families);
19
20static size_t af_inet__scnprintf(struct sockaddr *sa, char *bf, size_t size)
21{
22 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
23 char tmp[16];
24 return scnprintf(bf, size, ", port: %d, addr: %s", ntohs(sin->sin_port),
25 inet_ntop(sin->sin_family, &sin->sin_addr, tmp, sizeof(tmp)));
26}
27
28static size_t af_inet6__scnprintf(struct sockaddr *sa, char *bf, size_t size)
29{
30 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
31 u32 flowinfo = ntohl(sin6->sin6_flowinfo);
32 char tmp[512];
33 size_t printed = scnprintf(bf, size, ", port: %d, addr: %s", ntohs(sin6->sin6_port),
34 inet_ntop(sin6->sin6_family, &sin6->sin6_addr, tmp, sizeof(tmp)));
35 if (flowinfo != 0)
36 printed += scnprintf(bf + printed, size - printed, ", flowinfo: %lu", flowinfo);
37 if (sin6->sin6_scope_id != 0)
38 printed += scnprintf(bf + printed, size - printed, ", scope_id: %lu", sin6->sin6_scope_id);
39
40 return printed;
41}
42
43static size_t af_local__scnprintf(struct sockaddr *sa, char *bf, size_t size)
44{
45 struct sockaddr_un *sun = (struct sockaddr_un *)sa;
46 return scnprintf(bf, size, ", path: %s", sun->sun_path);
47}
48
49static size_t (*af_scnprintfs[])(struct sockaddr *sa, char *bf, size_t size) = {
50 [AF_LOCAL] = af_local__scnprintf,
51 [AF_INET] = af_inet__scnprintf,
52 [AF_INET6] = af_inet6__scnprintf,
53};
54
55static size_t syscall_arg__scnprintf_augmented_sockaddr(struct syscall_arg *arg, char *bf, size_t size)
56{
57 struct sockaddr *sa = (struct sockaddr *)arg->augmented.args;
58 char family[32];
59 size_t printed;
60
61 strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", sa->sa_family);
62 printed = scnprintf(bf, size, "{ .family: %s", family);
63
64 if (sa->sa_family < ARRAY_SIZE(af_scnprintfs) && af_scnprintfs[sa->sa_family])
65 printed += af_scnprintfs[sa->sa_family](sa, bf + printed, size - printed);
66
67 return printed + scnprintf(bf + printed, size - printed, " }");
68}
69
70size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg)
71{
72 if (arg->augmented.args)
73 return syscall_arg__scnprintf_augmented_sockaddr(arg, bf, size);
74
75 return scnprintf(bf, size, "%#x", arg->val);
76}
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 7efe15b9618d..ecd9f9ceda77 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -73,6 +73,7 @@ libperf-y += vdso.o
73libperf-y += counts.o 73libperf-y += counts.o
74libperf-y += stat.o 74libperf-y += stat.o
75libperf-y += stat-shadow.o 75libperf-y += stat-shadow.o
76libperf-y += stat-display.o
76libperf-y += record.o 77libperf-y += record.o
77libperf-y += srcline.o 78libperf-y += srcline.o
78libperf-y += data.o 79libperf-y += data.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 20061cf42288..28cd6a17491b 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -246,8 +246,14 @@ find_target:
246 246
247indirect_call: 247indirect_call:
248 tok = strchr(endptr, '*'); 248 tok = strchr(endptr, '*');
249 if (tok != NULL) 249 if (tok != NULL) {
250 ops->target.addr = strtoull(tok + 1, NULL, 16); 250 endptr++;
251
252 /* Indirect call can use a non-rip register and offset: callq *0x8(%rbx).
253 * Do not parse such instruction. */
254 if (strstr(endptr, "(%r") == NULL)
255 ops->target.addr = strtoull(endptr, NULL, 16);
256 }
251 goto find_target; 257 goto find_target;
252} 258}
253 259
@@ -276,7 +282,19 @@ bool ins__is_call(const struct ins *ins)
276 return ins->ops == &call_ops || ins->ops == &s390_call_ops; 282 return ins->ops == &call_ops || ins->ops == &s390_call_ops;
277} 283}
278 284
279static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms) 285/*
286 * Prevents from matching commas in the comment section, e.g.:
287 * ffff200008446e70: b.cs ffff2000084470f4 <generic_exec_single+0x314> // b.hs, b.nlast
288 */
289static inline const char *validate_comma(const char *c, struct ins_operands *ops)
290{
291 if (ops->raw_comment && c > ops->raw_comment)
292 return NULL;
293
294 return c;
295}
296
297static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
280{ 298{
281 struct map *map = ms->map; 299 struct map *map = ms->map;
282 struct symbol *sym = ms->sym; 300 struct symbol *sym = ms->sym;
@@ -285,6 +303,10 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
285 }; 303 };
286 const char *c = strchr(ops->raw, ','); 304 const char *c = strchr(ops->raw, ',');
287 u64 start, end; 305 u64 start, end;
306
307 ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char);
308 c = validate_comma(c, ops);
309
288 /* 310 /*
289 * Examples of lines to parse for the _cpp_lex_token@@Base 311 * Examples of lines to parse for the _cpp_lex_token@@Base
290 * function: 312 * function:
@@ -304,6 +326,7 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
304 ops->target.addr = strtoull(c, NULL, 16); 326 ops->target.addr = strtoull(c, NULL, 16);
305 if (!ops->target.addr) { 327 if (!ops->target.addr) {
306 c = strchr(c, ','); 328 c = strchr(c, ',');
329 c = validate_comma(c, ops);
307 if (c++ != NULL) 330 if (c++ != NULL)
308 ops->target.addr = strtoull(c, NULL, 16); 331 ops->target.addr = strtoull(c, NULL, 16);
309 } 332 }
@@ -361,9 +384,12 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
361 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name); 384 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
362 385
363 c = strchr(ops->raw, ','); 386 c = strchr(ops->raw, ',');
387 c = validate_comma(c, ops);
388
364 if (c != NULL) { 389 if (c != NULL) {
365 const char *c2 = strchr(c + 1, ','); 390 const char *c2 = strchr(c + 1, ',');
366 391
392 c2 = validate_comma(c2, ops);
367 /* check for 3-op insn */ 393 /* check for 3-op insn */
368 if (c2 != NULL) 394 if (c2 != NULL)
369 c = c2; 395 c = c2;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 005a5fe8a8c6..5399ba2321bb 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -22,6 +22,7 @@ struct ins {
22 22
23struct ins_operands { 23struct ins_operands {
24 char *raw; 24 char *raw;
25 char *raw_comment;
25 struct { 26 struct {
26 char *raw; 27 char *raw;
27 char *name; 28 char *name;
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index db1511359c5e..c4617bcfd521 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -906,9 +906,8 @@ out_free:
906 return err; 906 return err;
907} 907}
908 908
909int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused, 909int perf_event__process_auxtrace_info(struct perf_session *session,
910 union perf_event *event, 910 union perf_event *event)
911 struct perf_session *session)
912{ 911{
913 enum auxtrace_type type = event->auxtrace_info.type; 912 enum auxtrace_type type = event->auxtrace_info.type;
914 913
@@ -932,9 +931,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
932 } 931 }
933} 932}
934 933
935s64 perf_event__process_auxtrace(struct perf_tool *tool, 934s64 perf_event__process_auxtrace(struct perf_session *session,
936 union perf_event *event, 935 union perf_event *event)
937 struct perf_session *session)
938{ 936{
939 s64 err; 937 s64 err;
940 938
@@ -950,7 +948,7 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool,
950 if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE) 948 if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE)
951 return -EINVAL; 949 return -EINVAL;
952 950
953 err = session->auxtrace->process_auxtrace_event(session, event, tool); 951 err = session->auxtrace->process_auxtrace_event(session, event, session->tool);
954 if (err < 0) 952 if (err < 0)
955 return err; 953 return err;
956 954
@@ -1185,9 +1183,8 @@ void events_stats__auxtrace_error_warn(const struct events_stats *stats)
1185 } 1183 }
1186} 1184}
1187 1185
1188int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused, 1186int perf_event__process_auxtrace_error(struct perf_session *session,
1189 union perf_event *event, 1187 union perf_event *event)
1190 struct perf_session *session)
1191{ 1188{
1192 if (auxtrace__dont_decode(session)) 1189 if (auxtrace__dont_decode(session))
1193 return 0; 1190 return 0;
@@ -1196,11 +1193,12 @@ int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
1196 return 0; 1193 return 0;
1197} 1194}
1198 1195
1199static int __auxtrace_mmap__read(struct auxtrace_mmap *mm, 1196static int __auxtrace_mmap__read(struct perf_mmap *map,
1200 struct auxtrace_record *itr, 1197 struct auxtrace_record *itr,
1201 struct perf_tool *tool, process_auxtrace_t fn, 1198 struct perf_tool *tool, process_auxtrace_t fn,
1202 bool snapshot, size_t snapshot_size) 1199 bool snapshot, size_t snapshot_size)
1203{ 1200{
1201 struct auxtrace_mmap *mm = &map->auxtrace_mmap;
1204 u64 head, old = mm->prev, offset, ref; 1202 u64 head, old = mm->prev, offset, ref;
1205 unsigned char *data = mm->base; 1203 unsigned char *data = mm->base;
1206 size_t size, head_off, old_off, len1, len2, padding; 1204 size_t size, head_off, old_off, len1, len2, padding;
@@ -1287,7 +1285,7 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
1287 ev.auxtrace.tid = mm->tid; 1285 ev.auxtrace.tid = mm->tid;
1288 ev.auxtrace.cpu = mm->cpu; 1286 ev.auxtrace.cpu = mm->cpu;
1289 1287
1290 if (fn(tool, &ev, data1, len1, data2, len2)) 1288 if (fn(tool, map, &ev, data1, len1, data2, len2))
1291 return -1; 1289 return -1;
1292 1290
1293 mm->prev = head; 1291 mm->prev = head;
@@ -1306,18 +1304,18 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
1306 return 1; 1304 return 1;
1307} 1305}
1308 1306
1309int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 1307int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr,
1310 struct perf_tool *tool, process_auxtrace_t fn) 1308 struct perf_tool *tool, process_auxtrace_t fn)
1311{ 1309{
1312 return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0); 1310 return __auxtrace_mmap__read(map, itr, tool, fn, false, 0);
1313} 1311}
1314 1312
1315int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm, 1313int auxtrace_mmap__read_snapshot(struct perf_mmap *map,
1316 struct auxtrace_record *itr, 1314 struct auxtrace_record *itr,
1317 struct perf_tool *tool, process_auxtrace_t fn, 1315 struct perf_tool *tool, process_auxtrace_t fn,
1318 size_t snapshot_size) 1316 size_t snapshot_size)
1319{ 1317{
1320 return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size); 1318 return __auxtrace_mmap__read(map, itr, tool, fn, true, snapshot_size);
1321} 1319}
1322 1320
1323/** 1321/**
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 71fc3bd74299..d88f6e9eb461 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -23,6 +23,7 @@
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/perf_event.h> 24#include <linux/perf_event.h>
25#include <linux/types.h> 25#include <linux/types.h>
26#include <asm/bitsperlong.h>
26 27
27#include "../perf.h" 28#include "../perf.h"
28#include "event.h" 29#include "event.h"
@@ -33,6 +34,7 @@ union perf_event;
33struct perf_session; 34struct perf_session;
34struct perf_evlist; 35struct perf_evlist;
35struct perf_tool; 36struct perf_tool;
37struct perf_mmap;
36struct option; 38struct option;
37struct record_opts; 39struct record_opts;
38struct auxtrace_info_event; 40struct auxtrace_info_event;
@@ -434,13 +436,14 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
434 bool per_cpu); 436 bool per_cpu);
435 437
436typedef int (*process_auxtrace_t)(struct perf_tool *tool, 438typedef int (*process_auxtrace_t)(struct perf_tool *tool,
439 struct perf_mmap *map,
437 union perf_event *event, void *data1, 440 union perf_event *event, void *data1,
438 size_t len1, void *data2, size_t len2); 441 size_t len1, void *data2, size_t len2);
439 442
440int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 443int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr,
441 struct perf_tool *tool, process_auxtrace_t fn); 444 struct perf_tool *tool, process_auxtrace_t fn);
442 445
443int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm, 446int auxtrace_mmap__read_snapshot(struct perf_mmap *map,
444 struct auxtrace_record *itr, 447 struct auxtrace_record *itr,
445 struct perf_tool *tool, process_auxtrace_t fn, 448 struct perf_tool *tool, process_auxtrace_t fn,
446 size_t snapshot_size); 449 size_t snapshot_size);
@@ -517,15 +520,12 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
517 struct perf_tool *tool, 520 struct perf_tool *tool,
518 struct perf_session *session, 521 struct perf_session *session,
519 perf_event__handler_t process); 522 perf_event__handler_t process);
520int perf_event__process_auxtrace_info(struct perf_tool *tool, 523int perf_event__process_auxtrace_info(struct perf_session *session,
521 union perf_event *event, 524 union perf_event *event);
522 struct perf_session *session); 525s64 perf_event__process_auxtrace(struct perf_session *session,
523s64 perf_event__process_auxtrace(struct perf_tool *tool, 526 union perf_event *event);
524 union perf_event *event, 527int perf_event__process_auxtrace_error(struct perf_session *session,
525 struct perf_session *session); 528 union perf_event *event);
526int perf_event__process_auxtrace_error(struct perf_tool *tool,
527 union perf_event *event,
528 struct perf_session *session);
529int itrace_parse_synth_opts(const struct option *opt, const char *str, 529int itrace_parse_synth_opts(const struct option *opt, const char *str,
530 int unset); 530 int unset);
531void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts); 531void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts);
@@ -577,6 +577,23 @@ static inline void auxtrace__free(struct perf_session *session)
577 return session->auxtrace->free(session); 577 return session->auxtrace->free(session);
578} 578}
579 579
580#define ITRACE_HELP \
581" i: synthesize instructions events\n" \
582" b: synthesize branches events\n" \
583" c: synthesize branches events (calls only)\n" \
584" r: synthesize branches events (returns only)\n" \
585" x: synthesize transactions events\n" \
586" w: synthesize ptwrite events\n" \
587" p: synthesize power events\n" \
588" e: synthesize error events\n" \
589" d: create a debug log\n" \
590" g[len]: synthesize a call chain (use with i or x)\n" \
591" l[len]: synthesize last branch entries (use with i or x)\n" \
592" sNUMBER: skip initial number of events\n" \
593" PERIOD[ns|us|ms|i|t]: specify period to sample stream\n" \
594" concatenate multiple options. Default is ibxwpe or cewp\n"
595
596
580#else 597#else
581 598
582static inline struct auxtrace_record * 599static inline struct auxtrace_record *
@@ -717,6 +734,8 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
717 struct perf_evlist *evlist, int idx, 734 struct perf_evlist *evlist, int idx,
718 bool per_cpu); 735 bool per_cpu);
719 736
737#define ITRACE_HELP ""
738
720#endif 739#endif
721 740
722#endif 741#endif
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 47aac41349a2..f9ae1a993806 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -1615,7 +1615,7 @@ struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const cha
1615int bpf__setup_stdout(struct perf_evlist *evlist) 1615int bpf__setup_stdout(struct perf_evlist *evlist)
1616{ 1616{
1617 struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__"); 1617 struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
1618 return IS_ERR(evsel) ? PTR_ERR(evsel) : 0; 1618 return PTR_ERR_OR_ZERO(evsel);
1619} 1619}
1620 1620
1621#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) 1621#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index abd38abf1d91..2a36fab76994 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -182,20 +182,20 @@ err_put_field:
182} 182}
183 183
184static struct bt_ctf_field_type* 184static struct bt_ctf_field_type*
185get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) 185get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field)
186{ 186{
187 unsigned long flags = field->flags; 187 unsigned long flags = field->flags;
188 188
189 if (flags & FIELD_IS_STRING) 189 if (flags & TEP_FIELD_IS_STRING)
190 return cw->data.string; 190 return cw->data.string;
191 191
192 if (!(flags & FIELD_IS_SIGNED)) { 192 if (!(flags & TEP_FIELD_IS_SIGNED)) {
193 /* unsigned long are mostly pointers */ 193 /* unsigned long are mostly pointers */
194 if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) 194 if (flags & TEP_FIELD_IS_LONG || flags & TEP_FIELD_IS_POINTER)
195 return cw->data.u64_hex; 195 return cw->data.u64_hex;
196 } 196 }
197 197
198 if (flags & FIELD_IS_SIGNED) { 198 if (flags & TEP_FIELD_IS_SIGNED) {
199 if (field->size == 8) 199 if (field->size == 8)
200 return cw->data.s64; 200 return cw->data.s64;
201 else 201 else
@@ -287,7 +287,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
287 struct bt_ctf_event_class *event_class, 287 struct bt_ctf_event_class *event_class,
288 struct bt_ctf_event *event, 288 struct bt_ctf_event *event,
289 struct perf_sample *sample, 289 struct perf_sample *sample,
290 struct format_field *fmtf) 290 struct tep_format_field *fmtf)
291{ 291{
292 struct bt_ctf_field_type *type; 292 struct bt_ctf_field_type *type;
293 struct bt_ctf_field *array_field; 293 struct bt_ctf_field *array_field;
@@ -304,10 +304,10 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
304 name = fmtf->alias; 304 name = fmtf->alias;
305 offset = fmtf->offset; 305 offset = fmtf->offset;
306 len = fmtf->size; 306 len = fmtf->size;
307 if (flags & FIELD_IS_STRING) 307 if (flags & TEP_FIELD_IS_STRING)
308 flags &= ~FIELD_IS_ARRAY; 308 flags &= ~TEP_FIELD_IS_ARRAY;
309 309
310 if (flags & FIELD_IS_DYNAMIC) { 310 if (flags & TEP_FIELD_IS_DYNAMIC) {
311 unsigned long long tmp_val; 311 unsigned long long tmp_val;
312 312
313 tmp_val = tep_read_number(fmtf->event->pevent, 313 tmp_val = tep_read_number(fmtf->event->pevent,
@@ -317,7 +317,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
317 offset &= 0xffff; 317 offset &= 0xffff;
318 } 318 }
319 319
320 if (flags & FIELD_IS_ARRAY) { 320 if (flags & TEP_FIELD_IS_ARRAY) {
321 321
322 type = bt_ctf_event_class_get_field_by_name( 322 type = bt_ctf_event_class_get_field_by_name(
323 event_class, name); 323 event_class, name);
@@ -338,7 +338,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
338 type = get_tracepoint_field_type(cw, fmtf); 338 type = get_tracepoint_field_type(cw, fmtf);
339 339
340 for (i = 0; i < n_items; i++) { 340 for (i = 0; i < n_items; i++) {
341 if (flags & FIELD_IS_ARRAY) 341 if (flags & TEP_FIELD_IS_ARRAY)
342 field = bt_ctf_field_array_get_field(array_field, i); 342 field = bt_ctf_field_array_get_field(array_field, i);
343 else 343 else
344 field = bt_ctf_field_create(type); 344 field = bt_ctf_field_create(type);
@@ -348,7 +348,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
348 return -1; 348 return -1;
349 } 349 }
350 350
351 if (flags & FIELD_IS_STRING) 351 if (flags & TEP_FIELD_IS_STRING)
352 ret = string_set_value(field, data + offset + i * len); 352 ret = string_set_value(field, data + offset + i * len);
353 else { 353 else {
354 unsigned long long value_int; 354 unsigned long long value_int;
@@ -357,7 +357,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
357 fmtf->event->pevent, 357 fmtf->event->pevent,
358 data + offset + i * len, len); 358 data + offset + i * len, len);
359 359
360 if (!(flags & FIELD_IS_SIGNED)) 360 if (!(flags & TEP_FIELD_IS_SIGNED))
361 ret = bt_ctf_field_unsigned_integer_set_value( 361 ret = bt_ctf_field_unsigned_integer_set_value(
362 field, value_int); 362 field, value_int);
363 else 363 else
@@ -369,7 +369,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
369 pr_err("failed to set file value %s\n", name); 369 pr_err("failed to set file value %s\n", name);
370 goto err_put_field; 370 goto err_put_field;
371 } 371 }
372 if (!(flags & FIELD_IS_ARRAY)) { 372 if (!(flags & TEP_FIELD_IS_ARRAY)) {
373 ret = bt_ctf_event_set_payload(event, name, field); 373 ret = bt_ctf_event_set_payload(event, name, field);
374 if (ret) { 374 if (ret) {
375 pr_err("failed to set payload %s\n", name); 375 pr_err("failed to set payload %s\n", name);
@@ -378,7 +378,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
378 } 378 }
379 bt_ctf_field_put(field); 379 bt_ctf_field_put(field);
380 } 380 }
381 if (flags & FIELD_IS_ARRAY) { 381 if (flags & TEP_FIELD_IS_ARRAY) {
382 ret = bt_ctf_event_set_payload(event, name, array_field); 382 ret = bt_ctf_event_set_payload(event, name, array_field);
383 if (ret) { 383 if (ret) {
384 pr_err("Failed add payload array %s\n", name); 384 pr_err("Failed add payload array %s\n", name);
@@ -396,10 +396,10 @@ err_put_field:
396static int add_tracepoint_fields_values(struct ctf_writer *cw, 396static int add_tracepoint_fields_values(struct ctf_writer *cw,
397 struct bt_ctf_event_class *event_class, 397 struct bt_ctf_event_class *event_class,
398 struct bt_ctf_event *event, 398 struct bt_ctf_event *event,
399 struct format_field *fields, 399 struct tep_format_field *fields,
400 struct perf_sample *sample) 400 struct perf_sample *sample)
401{ 401{
402 struct format_field *field; 402 struct tep_format_field *field;
403 int ret; 403 int ret;
404 404
405 for (field = fields; field; field = field->next) { 405 for (field = fields; field; field = field->next) {
@@ -417,8 +417,8 @@ static int add_tracepoint_values(struct ctf_writer *cw,
417 struct perf_evsel *evsel, 417 struct perf_evsel *evsel,
418 struct perf_sample *sample) 418 struct perf_sample *sample)
419{ 419{
420 struct format_field *common_fields = evsel->tp_format->format.common_fields; 420 struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
421 struct format_field *fields = evsel->tp_format->format.fields; 421 struct tep_format_field *fields = evsel->tp_format->format.fields;
422 int ret; 422 int ret;
423 423
424 ret = add_tracepoint_fields_values(cw, event_class, event, 424 ret = add_tracepoint_fields_values(cw, event_class, event,
@@ -970,7 +970,7 @@ out:
970 970
971static int event_class_add_field(struct bt_ctf_event_class *event_class, 971static int event_class_add_field(struct bt_ctf_event_class *event_class,
972 struct bt_ctf_field_type *type, 972 struct bt_ctf_field_type *type,
973 struct format_field *field) 973 struct tep_format_field *field)
974{ 974{
975 struct bt_ctf_field_type *t = NULL; 975 struct bt_ctf_field_type *t = NULL;
976 char *name; 976 char *name;
@@ -1009,10 +1009,10 @@ static int event_class_add_field(struct bt_ctf_event_class *event_class,
1009} 1009}
1010 1010
1011static int add_tracepoint_fields_types(struct ctf_writer *cw, 1011static int add_tracepoint_fields_types(struct ctf_writer *cw,
1012 struct format_field *fields, 1012 struct tep_format_field *fields,
1013 struct bt_ctf_event_class *event_class) 1013 struct bt_ctf_event_class *event_class)
1014{ 1014{
1015 struct format_field *field; 1015 struct tep_format_field *field;
1016 int ret; 1016 int ret;
1017 1017
1018 for (field = fields; field; field = field->next) { 1018 for (field = fields; field; field = field->next) {
@@ -1030,15 +1030,15 @@ static int add_tracepoint_fields_types(struct ctf_writer *cw,
1030 * type and don't care that it is an array. What we don't 1030 * type and don't care that it is an array. What we don't
1031 * support is an array of strings. 1031 * support is an array of strings.
1032 */ 1032 */
1033 if (flags & FIELD_IS_STRING) 1033 if (flags & TEP_FIELD_IS_STRING)
1034 flags &= ~FIELD_IS_ARRAY; 1034 flags &= ~TEP_FIELD_IS_ARRAY;
1035 1035
1036 if (flags & FIELD_IS_ARRAY) 1036 if (flags & TEP_FIELD_IS_ARRAY)
1037 type = bt_ctf_field_type_array_create(type, field->arraylen); 1037 type = bt_ctf_field_type_array_create(type, field->arraylen);
1038 1038
1039 ret = event_class_add_field(event_class, type, field); 1039 ret = event_class_add_field(event_class, type, field);
1040 1040
1041 if (flags & FIELD_IS_ARRAY) 1041 if (flags & TEP_FIELD_IS_ARRAY)
1042 bt_ctf_field_type_put(type); 1042 bt_ctf_field_type_put(type);
1043 1043
1044 if (ret) { 1044 if (ret) {
@@ -1055,8 +1055,8 @@ static int add_tracepoint_types(struct ctf_writer *cw,
1055 struct perf_evsel *evsel, 1055 struct perf_evsel *evsel,
1056 struct bt_ctf_event_class *class) 1056 struct bt_ctf_event_class *class)
1057{ 1057{
1058 struct format_field *common_fields = evsel->tp_format->format.common_fields; 1058 struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
1059 struct format_field *fields = evsel->tp_format->format.fields; 1059 struct tep_format_field *fields = evsel->tp_format->format.fields;
1060 int ret; 1060 int ret;
1061 1061
1062 ret = add_tracepoint_fields_types(cw, common_fields, class); 1062 ret = add_tracepoint_fields_types(cw, common_fields, class);
@@ -1578,7 +1578,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1578{ 1578{
1579 struct perf_session *session; 1579 struct perf_session *session;
1580 struct perf_data data = { 1580 struct perf_data data = {
1581 .file.path = input, 1581 .file = { .path = input, .fd = -1 },
1582 .mode = PERF_DATA_MODE_READ, 1582 .mode = PERF_DATA_MODE_READ,
1583 .force = opts->force, 1583 .force = opts->force,
1584 }; 1584 };
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 7123746edcf4..69fbb0a72d0c 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -463,6 +463,28 @@ int db_export__branch_types(struct db_export *dbe)
463 if (err) 463 if (err)
464 break; 464 break;
465 } 465 }
466
467 /* Add trace begin / end variants */
468 for (i = 0; branch_types[i].name ; i++) {
469 const char *name = branch_types[i].name;
470 u32 type = branch_types[i].branch_type;
471 char buf[64];
472
473 if (type == PERF_IP_FLAG_BRANCH ||
474 (type & (PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END)))
475 continue;
476
477 snprintf(buf, sizeof(buf), "trace begin / %s", name);
478 err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_BEGIN, buf);
479 if (err)
480 break;
481
482 snprintf(buf, sizeof(buf), "%s / trace end", name);
483 err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_END, buf);
484 if (err)
485 break;
486 }
487
466 return err; 488 return err;
467} 489}
468 490
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 0cd42150f712..bc646185f8d9 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1081,6 +1081,7 @@ void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max
1081 } 1081 }
1082 1082
1083 *size += sizeof(struct cpu_map_data); 1083 *size += sizeof(struct cpu_map_data);
1084 *size = PERF_ALIGN(*size, sizeof(u64));
1084 return zalloc(*size); 1085 return zalloc(*size);
1085} 1086}
1086 1087
@@ -1560,26 +1561,9 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
1560 1561
1561 return NULL; 1562 return NULL;
1562 } 1563 }
1563try_again: 1564
1564 al->map = map_groups__find(mg, al->addr); 1565 al->map = map_groups__find(mg, al->addr);
1565 if (al->map == NULL) { 1566 if (al->map != NULL) {
1566 /*
1567 * If this is outside of all known maps, and is a negative
1568 * address, try to look it up in the kernel dso, as it might be
1569 * a vsyscall or vdso (which executes in user-mode).
1570 *
1571 * XXX This is nasty, we should have a symbol list in the
1572 * "[vdso]" dso, but for now lets use the old trick of looking
1573 * in the whole kernel symbol list.
1574 */
1575 if (cpumode == PERF_RECORD_MISC_USER && machine &&
1576 mg != &machine->kmaps &&
1577 machine__kernel_ip(machine, al->addr)) {
1578 mg = &machine->kmaps;
1579 load_map = true;
1580 goto try_again;
1581 }
1582 } else {
1583 /* 1567 /*
1584 * Kernel maps might be changed when loading symbols so loading 1568 * Kernel maps might be changed when loading symbols so loading
1585 * must be done prior to using kernel maps. 1569 * must be done prior to using kernel maps.
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index c980bbff6353..29d7b97f66fb 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -251,8 +251,9 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
251{ 251{
252 struct perf_evsel *evsel = zalloc(perf_evsel__object.size); 252 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
253 253
254 if (evsel != NULL) 254 if (!evsel)
255 perf_evsel__init(evsel, attr, idx); 255 return NULL;
256 perf_evsel__init(evsel, attr, idx);
256 257
257 if (perf_evsel__is_bpf_output(evsel)) { 258 if (perf_evsel__is_bpf_output(evsel)) {
258 evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | 259 evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
@@ -1088,6 +1089,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
1088 attr->exclude_user = 1; 1089 attr->exclude_user = 1;
1089 } 1090 }
1090 1091
1092 if (evsel->own_cpus)
1093 evsel->attr.read_format |= PERF_FORMAT_ID;
1094
1091 /* 1095 /*
1092 * Apply event specific term settings, 1096 * Apply event specific term settings,
1093 * it overloads any global configuration. 1097 * it overloads any global configuration.
@@ -2681,7 +2685,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
2681 return 0; 2685 return 0;
2682} 2686}
2683 2687
2684struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) 2688struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
2685{ 2689{
2686 return tep_find_field(evsel->tp_format, name); 2690 return tep_find_field(evsel->tp_format, name);
2687} 2691}
@@ -2689,7 +2693,7 @@ struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *nam
2689void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, 2693void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
2690 const char *name) 2694 const char *name)
2691{ 2695{
2692 struct format_field *field = perf_evsel__field(evsel, name); 2696 struct tep_format_field *field = perf_evsel__field(evsel, name);
2693 int offset; 2697 int offset;
2694 2698
2695 if (!field) 2699 if (!field)
@@ -2697,7 +2701,7 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
2697 2701
2698 offset = field->offset; 2702 offset = field->offset;
2699 2703
2700 if (field->flags & FIELD_IS_DYNAMIC) { 2704 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
2701 offset = *(int *)(sample->raw_data + field->offset); 2705 offset = *(int *)(sample->raw_data + field->offset);
2702 offset &= 0xffff; 2706 offset &= 0xffff;
2703 } 2707 }
@@ -2705,7 +2709,7 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
2705 return sample->raw_data + offset; 2709 return sample->raw_data + offset;
2706} 2710}
2707 2711
2708u64 format_field__intval(struct format_field *field, struct perf_sample *sample, 2712u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample,
2709 bool needs_swap) 2713 bool needs_swap)
2710{ 2714{
2711 u64 value; 2715 u64 value;
@@ -2747,7 +2751,7 @@ u64 format_field__intval(struct format_field *field, struct perf_sample *sample,
2747u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, 2751u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2748 const char *name) 2752 const char *name)
2749{ 2753{
2750 struct format_field *field = perf_evsel__field(evsel, name); 2754 struct tep_format_field *field = perf_evsel__field(evsel, name);
2751 2755
2752 if (!field) 2756 if (!field)
2753 return 0; 2757 return 0;
@@ -2939,3 +2943,32 @@ struct perf_env *perf_evsel__env(struct perf_evsel *evsel)
2939 return evsel->evlist->env; 2943 return evsel->evlist->env;
2940 return NULL; 2944 return NULL;
2941} 2945}
2946
2947static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
2948{
2949 int cpu, thread;
2950
2951 for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
2952 for (thread = 0; thread < xyarray__max_y(evsel->fd);
2953 thread++) {
2954 int fd = FD(evsel, cpu, thread);
2955
2956 if (perf_evlist__id_add_fd(evlist, evsel,
2957 cpu, thread, fd) < 0)
2958 return -1;
2959 }
2960 }
2961
2962 return 0;
2963}
2964
2965int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
2966{
2967 struct cpu_map *cpus = evsel->cpus;
2968 struct thread_map *threads = evsel->threads;
2969
2970 if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr))
2971 return -ENOMEM;
2972
2973 return store_evsel_ids(evsel, evlist);
2974}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 163c960614d3..4107c39f4a54 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -102,7 +102,7 @@ struct perf_evsel {
102 char *name; 102 char *name;
103 double scale; 103 double scale;
104 const char *unit; 104 const char *unit;
105 struct event_format *tp_format; 105 struct tep_event_format *tp_format;
106 off_t id_offset; 106 off_t id_offset;
107 struct perf_stat_evsel *stats; 107 struct perf_stat_evsel *stats;
108 void *priv; 108 void *priv;
@@ -211,7 +211,7 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
211 211
212struct perf_evsel *perf_evsel__new_cycles(bool precise); 212struct perf_evsel *perf_evsel__new_cycles(bool precise);
213 213
214struct event_format *event_format__new(const char *sys, const char *name); 214struct tep_event_format *event_format__new(const char *sys, const char *name);
215 215
216void perf_evsel__init(struct perf_evsel *evsel, 216void perf_evsel__init(struct perf_evsel *evsel,
217 struct perf_event_attr *attr, int idx); 217 struct perf_event_attr *attr, int idx);
@@ -296,11 +296,11 @@ static inline char *perf_evsel__strval(struct perf_evsel *evsel,
296 return perf_evsel__rawptr(evsel, sample, name); 296 return perf_evsel__rawptr(evsel, sample, name);
297} 297}
298 298
299struct format_field; 299struct tep_format_field;
300 300
301u64 format_field__intval(struct format_field *field, struct perf_sample *sample, bool needs_swap); 301u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap);
302 302
303struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); 303struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
304 304
305#define perf_evsel__match(evsel, t, c) \ 305#define perf_evsel__match(evsel, t, c) \
306 (evsel->attr.type == PERF_TYPE_##t && \ 306 (evsel->attr.type == PERF_TYPE_##t && \
@@ -481,4 +481,5 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
481 481
482struct perf_env *perf_evsel__env(struct perf_evsel *evsel); 482struct perf_env *perf_evsel__env(struct perf_evsel *evsel);
483 483
484int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist);
484#endif /* __PERF_EVSEL_H */ 485#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 06dfb027879d..0d0a4c6f368b 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -73,7 +73,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
73 } 73 }
74 74
75 if (details->trace_fields) { 75 if (details->trace_fields) {
76 struct format_field *field; 76 struct tep_format_field *field;
77 77
78 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { 78 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
79 printed += comma_fprintf(fp, &first, " (not a tracepoint)"); 79 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3cadc252dd89..1ec1d9bc2d63 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3206,7 +3206,7 @@ static int read_attr(int fd, struct perf_header *ph,
3206static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, 3206static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3207 struct tep_handle *pevent) 3207 struct tep_handle *pevent)
3208{ 3208{
3209 struct event_format *event; 3209 struct tep_event_format *event;
3210 char bf[128]; 3210 char bf[128];
3211 3211
3212 /* already prepared */ 3212 /* already prepared */
@@ -3448,10 +3448,10 @@ int perf_event__synthesize_features(struct perf_tool *tool,
3448 return ret; 3448 return ret;
3449} 3449}
3450 3450
3451int perf_event__process_feature(struct perf_tool *tool, 3451int perf_event__process_feature(struct perf_session *session,
3452 union perf_event *event, 3452 union perf_event *event)
3453 struct perf_session *session __maybe_unused)
3454{ 3453{
3454 struct perf_tool *tool = session->tool;
3455 struct feat_fd ff = { .fd = 0 }; 3455 struct feat_fd ff = { .fd = 0 };
3456 struct feature_event *fe = (struct feature_event *)event; 3456 struct feature_event *fe = (struct feature_event *)event;
3457 int type = fe->header.type; 3457 int type = fe->header.type;
@@ -3637,13 +3637,13 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
3637} 3637}
3638 3638
3639int perf_event__synthesize_attrs(struct perf_tool *tool, 3639int perf_event__synthesize_attrs(struct perf_tool *tool,
3640 struct perf_session *session, 3640 struct perf_evlist *evlist,
3641 perf_event__handler_t process) 3641 perf_event__handler_t process)
3642{ 3642{
3643 struct perf_evsel *evsel; 3643 struct perf_evsel *evsel;
3644 int err = 0; 3644 int err = 0;
3645 3645
3646 evlist__for_each_entry(session->evlist, evsel) { 3646 evlist__for_each_entry(evlist, evsel) {
3647 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, 3647 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
3648 evsel->id, process); 3648 evsel->id, process);
3649 if (err) { 3649 if (err) {
@@ -3856,9 +3856,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3856 return aligned_size; 3856 return aligned_size;
3857} 3857}
3858 3858
3859int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, 3859int perf_event__process_tracing_data(struct perf_session *session,
3860 union perf_event *event, 3860 union perf_event *event)
3861 struct perf_session *session)
3862{ 3861{
3863 ssize_t size_read, padding, size = event->tracing_data.size; 3862 ssize_t size_read, padding, size = event->tracing_data.size;
3864 int fd = perf_data__fd(session->data); 3863 int fd = perf_data__fd(session->data);
@@ -3924,9 +3923,8 @@ int perf_event__synthesize_build_id(struct perf_tool *tool,
3924 return err; 3923 return err;
3925} 3924}
3926 3925
3927int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, 3926int perf_event__process_build_id(struct perf_session *session,
3928 union perf_event *event, 3927 union perf_event *event)
3929 struct perf_session *session)
3930{ 3928{
3931 __event_process_build_id(&event->build_id, 3929 __event_process_build_id(&event->build_id,
3932 event->build_id.filename, 3930 event->build_id.filename,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 6d7fe44aadc0..e17903caa71d 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -116,15 +116,14 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool,
116 perf_event__handler_t process, 116 perf_event__handler_t process,
117 bool is_pipe); 117 bool is_pipe);
118 118
119int perf_event__process_feature(struct perf_tool *tool, 119int perf_event__process_feature(struct perf_session *session,
120 union perf_event *event, 120 union perf_event *event);
121 struct perf_session *session);
122 121
123int perf_event__synthesize_attr(struct perf_tool *tool, 122int perf_event__synthesize_attr(struct perf_tool *tool,
124 struct perf_event_attr *attr, u32 ids, u64 *id, 123 struct perf_event_attr *attr, u32 ids, u64 *id,
125 perf_event__handler_t process); 124 perf_event__handler_t process);
126int perf_event__synthesize_attrs(struct perf_tool *tool, 125int perf_event__synthesize_attrs(struct perf_tool *tool,
127 struct perf_session *session, 126 struct perf_evlist *evlist,
128 perf_event__handler_t process); 127 perf_event__handler_t process);
129int perf_event__synthesize_event_update_unit(struct perf_tool *tool, 128int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
130 struct perf_evsel *evsel, 129 struct perf_evsel *evsel,
@@ -148,17 +147,15 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp);
148int perf_event__synthesize_tracing_data(struct perf_tool *tool, 147int perf_event__synthesize_tracing_data(struct perf_tool *tool,
149 int fd, struct perf_evlist *evlist, 148 int fd, struct perf_evlist *evlist,
150 perf_event__handler_t process); 149 perf_event__handler_t process);
151int perf_event__process_tracing_data(struct perf_tool *tool, 150int perf_event__process_tracing_data(struct perf_session *session,
152 union perf_event *event, 151 union perf_event *event);
153 struct perf_session *session);
154 152
155int perf_event__synthesize_build_id(struct perf_tool *tool, 153int perf_event__synthesize_build_id(struct perf_tool *tool,
156 struct dso *pos, u16 misc, 154 struct dso *pos, u16 misc,
157 perf_event__handler_t process, 155 perf_event__handler_t process,
158 struct machine *machine); 156 struct machine *machine);
159int perf_event__process_build_id(struct perf_tool *tool, 157int perf_event__process_build_id(struct perf_session *session,
160 union perf_event *event, 158 union perf_event *event);
161 struct perf_session *session);
162bool is_perf_magic(u64 magic); 159bool is_perf_magic(u64 magic);
163 160
164#define NAME_ALIGN 64 161#define NAME_ALIGN 64
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 d404bed7003a..58f6a9ceb590 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -1165,7 +1165,7 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1165 decoder->pge = false; 1165 decoder->pge = false;
1166 decoder->continuous_period = false; 1166 decoder->continuous_period = false;
1167 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1167 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1168 decoder->state.to_ip = 0; 1168 decoder->state.type |= INTEL_PT_TRACE_END;
1169 return 0; 1169 return 0;
1170 } 1170 }
1171 if (err == INTEL_PT_RETURN) 1171 if (err == INTEL_PT_RETURN)
@@ -1179,9 +1179,13 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1179 decoder->continuous_period = false; 1179 decoder->continuous_period = false;
1180 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1180 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1181 decoder->state.from_ip = decoder->ip; 1181 decoder->state.from_ip = decoder->ip;
1182 decoder->state.to_ip = 0; 1182 if (decoder->packet.count == 0) {
1183 if (decoder->packet.count != 0) 1183 decoder->state.to_ip = 0;
1184 } else {
1185 decoder->state.to_ip = decoder->last_ip;
1184 decoder->ip = decoder->last_ip; 1186 decoder->ip = decoder->last_ip;
1187 }
1188 decoder->state.type |= INTEL_PT_TRACE_END;
1185 } else { 1189 } else {
1186 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1190 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1187 decoder->state.from_ip = decoder->ip; 1191 decoder->state.from_ip = decoder->ip;
@@ -1208,7 +1212,8 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1208 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1212 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1209 decoder->ip = to_ip; 1213 decoder->ip = to_ip;
1210 decoder->state.from_ip = decoder->ip; 1214 decoder->state.from_ip = decoder->ip;
1211 decoder->state.to_ip = 0; 1215 decoder->state.to_ip = to_ip;
1216 decoder->state.type |= INTEL_PT_TRACE_END;
1212 return 0; 1217 return 0;
1213 } 1218 }
1214 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", 1219 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
@@ -1640,14 +1645,15 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1640 1645
1641 case INTEL_PT_TIP_PGD: 1646 case INTEL_PT_TIP_PGD:
1642 decoder->state.from_ip = decoder->ip; 1647 decoder->state.from_ip = decoder->ip;
1643 decoder->state.to_ip = 0; 1648 if (decoder->packet.count == 0) {
1644 if (decoder->packet.count != 0) { 1649 decoder->state.to_ip = 0;
1650 } else {
1645 intel_pt_set_ip(decoder); 1651 intel_pt_set_ip(decoder);
1646 intel_pt_log("Omitting PGD ip " x64_fmt "\n", 1652 decoder->state.to_ip = decoder->ip;
1647 decoder->ip);
1648 } 1653 }
1649 decoder->pge = false; 1654 decoder->pge = false;
1650 decoder->continuous_period = false; 1655 decoder->continuous_period = false;
1656 decoder->state.type |= INTEL_PT_TRACE_END;
1651 return 0; 1657 return 0;
1652 1658
1653 case INTEL_PT_TIP_PGE: 1659 case INTEL_PT_TIP_PGE:
@@ -1661,6 +1667,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1661 intel_pt_set_ip(decoder); 1667 intel_pt_set_ip(decoder);
1662 decoder->state.to_ip = decoder->ip; 1668 decoder->state.to_ip = decoder->ip;
1663 } 1669 }
1670 decoder->state.type |= INTEL_PT_TRACE_BEGIN;
1664 return 0; 1671 return 0;
1665 1672
1666 case INTEL_PT_TIP: 1673 case INTEL_PT_TIP:
@@ -1739,6 +1746,7 @@ next:
1739 intel_pt_set_ip(decoder); 1746 intel_pt_set_ip(decoder);
1740 decoder->state.from_ip = 0; 1747 decoder->state.from_ip = 0;
1741 decoder->state.to_ip = decoder->ip; 1748 decoder->state.to_ip = decoder->ip;
1749 decoder->state.type |= INTEL_PT_TRACE_BEGIN;
1742 return 0; 1750 return 0;
1743 } 1751 }
1744 1752
@@ -2077,9 +2085,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
2077 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; 2085 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
2078 if (intel_pt_have_ip(decoder)) 2086 if (intel_pt_have_ip(decoder))
2079 intel_pt_set_ip(decoder); 2087 intel_pt_set_ip(decoder);
2080 if (decoder->ip) 2088 if (!decoder->ip)
2081 return 0; 2089 break;
2082 break; 2090 if (decoder->packet.type == INTEL_PT_TIP_PGE)
2091 decoder->state.type |= INTEL_PT_TRACE_BEGIN;
2092 if (decoder->packet.type == INTEL_PT_TIP_PGD)
2093 decoder->state.type |= INTEL_PT_TRACE_END;
2094 return 0;
2083 2095
2084 case INTEL_PT_FUP: 2096 case INTEL_PT_FUP:
2085 if (intel_pt_have_ip(decoder)) 2097 if (intel_pt_have_ip(decoder))
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 51c18d67f4ca..ed088d4726ba 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -37,6 +37,8 @@ enum intel_pt_sample_type {
37 INTEL_PT_EX_STOP = 1 << 6, 37 INTEL_PT_EX_STOP = 1 << 6,
38 INTEL_PT_PWR_EXIT = 1 << 7, 38 INTEL_PT_PWR_EXIT = 1 << 7,
39 INTEL_PT_CBR_CHG = 1 << 8, 39 INTEL_PT_CBR_CHG = 1 << 8,
40 INTEL_PT_TRACE_BEGIN = 1 << 9,
41 INTEL_PT_TRACE_END = 1 << 10,
40}; 42};
41 43
42enum intel_pt_period_type { 44enum intel_pt_period_type {
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index aec68908d604..48c1d415c6b0 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -908,6 +908,11 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
908 ptq->insn_len = ptq->state->insn_len; 908 ptq->insn_len = ptq->state->insn_len;
909 memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ); 909 memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ);
910 } 910 }
911
912 if (ptq->state->type & INTEL_PT_TRACE_BEGIN)
913 ptq->flags |= PERF_IP_FLAG_TRACE_BEGIN;
914 if (ptq->state->type & INTEL_PT_TRACE_END)
915 ptq->flags |= PERF_IP_FLAG_TRACE_END;
911} 916}
912 917
913static int intel_pt_setup_queue(struct intel_pt *pt, 918static int intel_pt_setup_queue(struct intel_pt *pt,
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 19262f98cd4e..5b0b60f00275 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -19,7 +19,7 @@
19#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ 19#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \
20 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ 20 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
21 "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \ 21 "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \
22 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \ 22 "$CLANG_OPTIONS $PERF_BPF_INC_OPTIONS $KERNEL_INC_OPTIONS " \
23 "-Wno-unused-value -Wno-pointer-sign " \ 23 "-Wno-unused-value -Wno-pointer-sign " \
24 "-working-directory $WORKING_DIR " \ 24 "-working-directory $WORKING_DIR " \
25 "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE" 25 "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index c4acd2001db0..111ae858cbcb 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -2286,7 +2286,8 @@ static int append_inlines(struct callchain_cursor *cursor,
2286 if (!symbol_conf.inline_name || !map || !sym) 2286 if (!symbol_conf.inline_name || !map || !sym)
2287 return ret; 2287 return ret;
2288 2288
2289 addr = map__rip_2objdump(map, ip); 2289 addr = map__map_ip(map, ip);
2290 addr = map__rip_2objdump(map, addr);
2290 2291
2291 inline_node = inlines__tree_find(&map->dso->inlined_nodes, addr); 2292 inline_node = inlines__tree_find(&map->dso->inlined_nodes, addr);
2292 if (!inline_node) { 2293 if (!inline_node) {
@@ -2312,7 +2313,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
2312{ 2313{
2313 struct callchain_cursor *cursor = arg; 2314 struct callchain_cursor *cursor = arg;
2314 const char *srcline = NULL; 2315 const char *srcline = NULL;
2315 u64 addr; 2316 u64 addr = entry->ip;
2316 2317
2317 if (symbol_conf.hide_unresolved && entry->sym == NULL) 2318 if (symbol_conf.hide_unresolved && entry->sym == NULL)
2318 return 0; 2319 return 0;
@@ -2324,7 +2325,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
2324 * Convert entry->ip from a virtual address to an offset in 2325 * Convert entry->ip from a virtual address to an offset in
2325 * its corresponding binary. 2326 * its corresponding binary.
2326 */ 2327 */
2327 addr = map__map_ip(entry->map, entry->ip); 2328 if (entry->map)
2329 addr = map__map_ip(entry->map, entry->ip);
2328 2330
2329 srcline = callchain_srcline(entry->map, entry->sym, addr); 2331 srcline = callchain_srcline(entry->map, entry->sym, addr);
2330 return callchain_cursor_append(cursor, entry->ip, 2332 return callchain_cursor_append(cursor, entry->ip,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 36d0763311ef..354e54550d2b 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -320,12 +320,11 @@ int map__load(struct map *map)
320 build_id__sprintf(map->dso->build_id, 320 build_id__sprintf(map->dso->build_id,
321 sizeof(map->dso->build_id), 321 sizeof(map->dso->build_id),
322 sbuild_id); 322 sbuild_id);
323 pr_warning("%s with build id %s not found", 323 pr_debug("%s with build id %s not found", name, sbuild_id);
324 name, sbuild_id);
325 } else 324 } else
326 pr_warning("Failed to open %s", name); 325 pr_debug("Failed to open %s", name);
327 326
328 pr_warning(", continuing without symbols\n"); 327 pr_debug(", continuing without symbols\n");
329 return -1; 328 return -1;
330 } else if (nr == 0) { 329 } else if (nr == 0) {
331#ifdef HAVE_LIBELF_SUPPORT 330#ifdef HAVE_LIBELF_SUPPORT
@@ -334,12 +333,11 @@ int map__load(struct map *map)
334 333
335 if (len > sizeof(DSO__DELETED) && 334 if (len > sizeof(DSO__DELETED) &&
336 strcmp(name + real_len + 1, DSO__DELETED) == 0) { 335 strcmp(name + real_len + 1, DSO__DELETED) == 0) {
337 pr_warning("%.*s was updated (is prelink enabled?). " 336 pr_debug("%.*s was updated (is prelink enabled?). "
338 "Restart the long running apps that use it!\n", 337 "Restart the long running apps that use it!\n",
339 (int)real_len, name); 338 (int)real_len, name);
340 } else { 339 } else {
341 pr_warning("no symbols found in %s, maybe install " 340 pr_debug("no symbols found in %s, maybe install a debug package?\n", name);
342 "a debug package?\n", name);
343 } 341 }
344#endif 342#endif
345 return -1; 343 return -1;
@@ -576,6 +574,13 @@ struct symbol *map_groups__find_symbol(struct map_groups *mg,
576 return NULL; 574 return NULL;
577} 575}
578 576
577static bool map__contains_symbol(struct map *map, struct symbol *sym)
578{
579 u64 ip = map->unmap_ip(map, sym->start);
580
581 return ip >= map->start && ip < map->end;
582}
583
579struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, 584struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
580 struct map **mapp) 585 struct map **mapp)
581{ 586{
@@ -591,6 +596,10 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
591 596
592 if (sym == NULL) 597 if (sym == NULL)
593 continue; 598 continue;
599 if (!map__contains_symbol(pos, sym)) {
600 sym = NULL;
601 continue;
602 }
594 if (mapp != NULL) 603 if (mapp != NULL)
595 *mapp = pos; 604 *mapp = pos;
596 goto out; 605 goto out;
@@ -701,8 +710,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
701 if (verbose >= 2) { 710 if (verbose >= 2) {
702 711
703 if (use_browser) { 712 if (use_browser) {
704 pr_warning("overlapping maps in %s " 713 pr_debug("overlapping maps in %s (disable tui for more info)\n",
705 "(disable tui for more info)\n",
706 map->dso->name); 714 map->dso->name);
707 } else { 715 } else {
708 fputs("overlapping maps:\n", fp); 716 fputs("overlapping maps:\n", fp);
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 215f69f41672..cdb95b3a1213 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -281,7 +281,7 @@ int perf_mmap__read_init(struct perf_mmap *map)
281} 281}
282 282
283int perf_mmap__push(struct perf_mmap *md, void *to, 283int perf_mmap__push(struct perf_mmap *md, void *to,
284 int push(void *to, void *buf, size_t size)) 284 int push(struct perf_mmap *map, void *to, void *buf, size_t size))
285{ 285{
286 u64 head = perf_mmap__read_head(md); 286 u64 head = perf_mmap__read_head(md);
287 unsigned char *data = md->base + page_size; 287 unsigned char *data = md->base + page_size;
@@ -300,7 +300,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to,
300 size = md->mask + 1 - (md->start & md->mask); 300 size = md->mask + 1 - (md->start & md->mask);
301 md->start += size; 301 md->start += size;
302 302
303 if (push(to, buf, size) < 0) { 303 if (push(md, to, buf, size) < 0) {
304 rc = -1; 304 rc = -1;
305 goto out; 305 goto out;
306 } 306 }
@@ -310,7 +310,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to,
310 size = md->end - md->start; 310 size = md->end - md->start;
311 md->start += size; 311 md->start += size;
312 312
313 if (push(to, buf, size) < 0) { 313 if (push(md, to, buf, size) < 0) {
314 rc = -1; 314 rc = -1;
315 goto out; 315 goto out;
316 } 316 }
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index 05a6d47c7956..cc5e2d6d17a9 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -4,7 +4,7 @@
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <linux/refcount.h> 5#include <linux/refcount.h>
6#include <linux/types.h> 6#include <linux/types.h>
7#include <asm/barrier.h> 7#include <linux/ring_buffer.h>
8#include <stdbool.h> 8#include <stdbool.h>
9#include "auxtrace.h" 9#include "auxtrace.h"
10#include "event.h" 10#include "event.h"
@@ -71,21 +71,12 @@ void perf_mmap__consume(struct perf_mmap *map);
71 71
72static inline u64 perf_mmap__read_head(struct perf_mmap *mm) 72static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
73{ 73{
74 struct perf_event_mmap_page *pc = mm->base; 74 return ring_buffer_read_head(mm->base);
75 u64 head = READ_ONCE(pc->data_head);
76 rmb();
77 return head;
78} 75}
79 76
80static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail) 77static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
81{ 78{
82 struct perf_event_mmap_page *pc = md->base; 79 ring_buffer_write_tail(md->base, tail);
83
84 /*
85 * ensure all reads are done before we write the tail out.
86 */
87 mb();
88 pc->data_tail = tail;
89} 80}
90 81
91union perf_event *perf_mmap__read_forward(struct perf_mmap *map); 82union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
@@ -93,7 +84,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
93union perf_event *perf_mmap__read_event(struct perf_mmap *map); 84union perf_event *perf_mmap__read_event(struct perf_mmap *map);
94 85
95int perf_mmap__push(struct perf_mmap *md, void *to, 86int perf_mmap__push(struct perf_mmap *md, void *to,
96 int push(void *to, void *buf, size_t size)); 87 int push(struct perf_mmap *map, void *to, void *buf, size_t size));
97 88
98size_t perf_mmap__mmap_len(struct perf_mmap *map); 89size_t perf_mmap__mmap_len(struct perf_mmap *map);
99 90
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index bad9e0296e9a..1904e7f6ec84 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -80,14 +80,20 @@ static union perf_event *dup_event(struct ordered_events *oe,
80 return oe->copy_on_queue ? __dup_event(oe, event) : event; 80 return oe->copy_on_queue ? __dup_event(oe, event) : event;
81} 81}
82 82
83static void free_dup_event(struct ordered_events *oe, union perf_event *event) 83static void __free_dup_event(struct ordered_events *oe, union perf_event *event)
84{ 84{
85 if (event && oe->copy_on_queue) { 85 if (event) {
86 oe->cur_alloc_size -= event->header.size; 86 oe->cur_alloc_size -= event->header.size;
87 free(event); 87 free(event);
88 } 88 }
89} 89}
90 90
91static void free_dup_event(struct ordered_events *oe, union perf_event *event)
92{
93 if (oe->copy_on_queue)
94 __free_dup_event(oe, event);
95}
96
91#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event)) 97#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
92static struct ordered_event *alloc_event(struct ordered_events *oe, 98static struct ordered_event *alloc_event(struct ordered_events *oe,
93 union perf_event *event) 99 union perf_event *event)
@@ -95,21 +101,49 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
95 struct list_head *cache = &oe->cache; 101 struct list_head *cache = &oe->cache;
96 struct ordered_event *new = NULL; 102 struct ordered_event *new = NULL;
97 union perf_event *new_event; 103 union perf_event *new_event;
104 size_t size;
98 105
99 new_event = dup_event(oe, event); 106 new_event = dup_event(oe, event);
100 if (!new_event) 107 if (!new_event)
101 return NULL; 108 return NULL;
102 109
110 /*
111 * We maintain the following scheme of buffers for ordered
112 * event allocation:
113 *
114 * to_free list -> buffer1 (64K)
115 * buffer2 (64K)
116 * ...
117 *
118 * Each buffer keeps an array of ordered events objects:
119 * buffer -> event[0]
120 * event[1]
121 * ...
122 *
123 * Each allocated ordered event is linked to one of
124 * following lists:
125 * - time ordered list 'events'
126 * - list of currently removed events 'cache'
127 *
128 * Allocation of the ordered event uses the following order
129 * to get the memory:
130 * - use recently removed object from 'cache' list
131 * - use available object in current allocation buffer
132 * - allocate new buffer if the current buffer is full
133 *
134 * Removal of ordered event object moves it from events to
135 * the cache list.
136 */
137 size = sizeof(*oe->buffer) + MAX_SAMPLE_BUFFER * sizeof(*new);
138
103 if (!list_empty(cache)) { 139 if (!list_empty(cache)) {
104 new = list_entry(cache->next, struct ordered_event, list); 140 new = list_entry(cache->next, struct ordered_event, list);
105 list_del(&new->list); 141 list_del(&new->list);
106 } else if (oe->buffer) { 142 } else if (oe->buffer) {
107 new = oe->buffer + oe->buffer_idx; 143 new = &oe->buffer->event[oe->buffer_idx];
108 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER) 144 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
109 oe->buffer = NULL; 145 oe->buffer = NULL;
110 } else if (oe->cur_alloc_size < oe->max_alloc_size) { 146 } else if ((oe->cur_alloc_size + size) < oe->max_alloc_size) {
111 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
112
113 oe->buffer = malloc(size); 147 oe->buffer = malloc(size);
114 if (!oe->buffer) { 148 if (!oe->buffer) {
115 free_dup_event(oe, new_event); 149 free_dup_event(oe, new_event);
@@ -122,11 +156,11 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
122 oe->cur_alloc_size += size; 156 oe->cur_alloc_size += size;
123 list_add(&oe->buffer->list, &oe->to_free); 157 list_add(&oe->buffer->list, &oe->to_free);
124 158
125 /* First entry is abused to maintain the to_free list. */ 159 oe->buffer_idx = 1;
126 oe->buffer_idx = 2; 160 new = &oe->buffer->event[0];
127 new = oe->buffer + 1;
128 } else { 161 } else {
129 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size); 162 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
163 return NULL;
130 } 164 }
131 165
132 new->event = new_event; 166 new->event = new_event;
@@ -300,15 +334,38 @@ void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t d
300 oe->deliver = deliver; 334 oe->deliver = deliver;
301} 335}
302 336
337static void
338ordered_events_buffer__free(struct ordered_events_buffer *buffer,
339 unsigned int max, struct ordered_events *oe)
340{
341 if (oe->copy_on_queue) {
342 unsigned int i;
343
344 for (i = 0; i < max; i++)
345 __free_dup_event(oe, buffer->event[i].event);
346 }
347
348 free(buffer);
349}
350
303void ordered_events__free(struct ordered_events *oe) 351void ordered_events__free(struct ordered_events *oe)
304{ 352{
305 while (!list_empty(&oe->to_free)) { 353 struct ordered_events_buffer *buffer, *tmp;
306 struct ordered_event *event;
307 354
308 event = list_entry(oe->to_free.next, struct ordered_event, list); 355 if (list_empty(&oe->to_free))
309 list_del(&event->list); 356 return;
310 free_dup_event(oe, event->event); 357
311 free(event); 358 /*
359 * Current buffer might not have all the events allocated
360 * yet, we need to free only allocated ones ...
361 */
362 list_del(&oe->buffer->list);
363 ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
364
365 /* ... and continue with the rest */
366 list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
367 list_del(&buffer->list);
368 ordered_events_buffer__free(buffer, MAX_SAMPLE_BUFFER, oe);
312 } 369 }
313} 370}
314 371
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 8c7a2948593e..1338d5c345dc 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -25,23 +25,28 @@ struct ordered_events;
25typedef int (*ordered_events__deliver_t)(struct ordered_events *oe, 25typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
26 struct ordered_event *event); 26 struct ordered_event *event);
27 27
28struct ordered_events_buffer {
29 struct list_head list;
30 struct ordered_event event[0];
31};
32
28struct ordered_events { 33struct ordered_events {
29 u64 last_flush; 34 u64 last_flush;
30 u64 next_flush; 35 u64 next_flush;
31 u64 max_timestamp; 36 u64 max_timestamp;
32 u64 max_alloc_size; 37 u64 max_alloc_size;
33 u64 cur_alloc_size; 38 u64 cur_alloc_size;
34 struct list_head events; 39 struct list_head events;
35 struct list_head cache; 40 struct list_head cache;
36 struct list_head to_free; 41 struct list_head to_free;
37 struct ordered_event *buffer; 42 struct ordered_events_buffer *buffer;
38 struct ordered_event *last; 43 struct ordered_event *last;
39 ordered_events__deliver_t deliver; 44 ordered_events__deliver_t deliver;
40 int buffer_idx; 45 int buffer_idx;
41 unsigned int nr_events; 46 unsigned int nr_events;
42 enum oe_flush last_flush_type; 47 enum oe_flush last_flush_type;
43 u32 nr_unordered_events; 48 u32 nr_unordered_events;
44 bool copy_on_queue; 49 bool copy_on_queue;
45}; 50};
46 51
47int ordered_events__queue(struct ordered_events *oe, union perf_event *event, 52int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index afd68524ffa9..7799788f662f 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -930,13 +930,14 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
930 930
931static __u64 pmu_format_max_value(const unsigned long *format) 931static __u64 pmu_format_max_value(const unsigned long *format)
932{ 932{
933 __u64 w = 0; 933 int w;
934 int fbit;
935
936 for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS)
937 w |= (1ULL << fbit);
938 934
939 return w; 935 w = bitmap_weight(format, PERF_PMU_FORMAT_BITS);
936 if (!w)
937 return 0;
938 if (w < 64)
939 return (1ULL << w) - 1;
940 return -1;
940} 941}
941 942
942/* 943/*
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index ce501ba14b08..50150dfc0cdf 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -340,7 +340,7 @@ static bool is_tracepoint(struct pyrf_event *pevent)
340} 340}
341 341
342static PyObject* 342static PyObject*
343tracepoint_field(struct pyrf_event *pe, struct format_field *field) 343tracepoint_field(struct pyrf_event *pe, struct tep_format_field *field)
344{ 344{
345 struct tep_handle *pevent = field->event->pevent; 345 struct tep_handle *pevent = field->event->pevent;
346 void *data = pe->sample.raw_data; 346 void *data = pe->sample.raw_data;
@@ -348,28 +348,28 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
348 unsigned long long val; 348 unsigned long long val;
349 unsigned int offset, len; 349 unsigned int offset, len;
350 350
351 if (field->flags & FIELD_IS_ARRAY) { 351 if (field->flags & TEP_FIELD_IS_ARRAY) {
352 offset = field->offset; 352 offset = field->offset;
353 len = field->size; 353 len = field->size;
354 if (field->flags & FIELD_IS_DYNAMIC) { 354 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
355 val = tep_read_number(pevent, data + offset, len); 355 val = tep_read_number(pevent, data + offset, len);
356 offset = val; 356 offset = val;
357 len = offset >> 16; 357 len = offset >> 16;
358 offset &= 0xffff; 358 offset &= 0xffff;
359 } 359 }
360 if (field->flags & FIELD_IS_STRING && 360 if (field->flags & TEP_FIELD_IS_STRING &&
361 is_printable_array(data + offset, len)) { 361 is_printable_array(data + offset, len)) {
362 ret = _PyUnicode_FromString((char *)data + offset); 362 ret = _PyUnicode_FromString((char *)data + offset);
363 } else { 363 } else {
364 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); 364 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
365 field->flags &= ~FIELD_IS_STRING; 365 field->flags &= ~TEP_FIELD_IS_STRING;
366 } 366 }
367 } else { 367 } else {
368 val = tep_read_number(pevent, data + field->offset, 368 val = tep_read_number(pevent, data + field->offset,
369 field->size); 369 field->size);
370 if (field->flags & FIELD_IS_POINTER) 370 if (field->flags & TEP_FIELD_IS_POINTER)
371 ret = PyLong_FromUnsignedLong((unsigned long) val); 371 ret = PyLong_FromUnsignedLong((unsigned long) val);
372 else if (field->flags & FIELD_IS_SIGNED) 372 else if (field->flags & TEP_FIELD_IS_SIGNED)
373 ret = PyLong_FromLong((long) val); 373 ret = PyLong_FromLong((long) val);
374 else 374 else
375 ret = PyLong_FromUnsignedLong((unsigned long) val); 375 ret = PyLong_FromUnsignedLong((unsigned long) val);
@@ -383,10 +383,10 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
383{ 383{
384 const char *str = _PyUnicode_AsString(PyObject_Str(attr_name)); 384 const char *str = _PyUnicode_AsString(PyObject_Str(attr_name));
385 struct perf_evsel *evsel = pevent->evsel; 385 struct perf_evsel *evsel = pevent->evsel;
386 struct format_field *field; 386 struct tep_format_field *field;
387 387
388 if (!evsel->tp_format) { 388 if (!evsel->tp_format) {
389 struct event_format *tp_format; 389 struct tep_event_format *tp_format;
390 390
391 tp_format = trace_event__tp_format_id(evsel->attr.config); 391 tp_format = trace_event__tp_format_id(evsel->attr.config);
392 if (!tp_format) 392 if (!tp_format)
@@ -1240,7 +1240,7 @@ static struct {
1240static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, 1240static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
1241 PyObject *args, PyObject *kwargs) 1241 PyObject *args, PyObject *kwargs)
1242{ 1242{
1243 struct event_format *tp_format; 1243 struct tep_event_format *tp_format;
1244 static char *kwlist[] = { "sys", "name", NULL }; 1244 static char *kwlist[] = { "sys", "name", NULL };
1245 char *sys = NULL; 1245 char *sys = NULL;
1246 char *name = NULL; 1246 char *name = NULL;
diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c
index d2c78ffd9fee..a2eeebbfb25f 100644
--- a/tools/perf/util/s390-cpumsf.c
+++ b/tools/perf/util/s390-cpumsf.c
@@ -147,6 +147,9 @@
147#include <linux/bitops.h> 147#include <linux/bitops.h>
148#include <linux/log2.h> 148#include <linux/log2.h>
149 149
150#include <sys/stat.h>
151#include <sys/types.h>
152
150#include "cpumap.h" 153#include "cpumap.h"
151#include "color.h" 154#include "color.h"
152#include "evsel.h" 155#include "evsel.h"
@@ -159,6 +162,7 @@
159#include "auxtrace.h" 162#include "auxtrace.h"
160#include "s390-cpumsf.h" 163#include "s390-cpumsf.h"
161#include "s390-cpumsf-kernel.h" 164#include "s390-cpumsf-kernel.h"
165#include "config.h"
162 166
163struct s390_cpumsf { 167struct s390_cpumsf {
164 struct auxtrace auxtrace; 168 struct auxtrace auxtrace;
@@ -170,6 +174,8 @@ struct s390_cpumsf {
170 u32 pmu_type; 174 u32 pmu_type;
171 u16 machine_type; 175 u16 machine_type;
172 bool data_queued; 176 bool data_queued;
177 bool use_logfile;
178 char *logdir;
173}; 179};
174 180
175struct s390_cpumsf_queue { 181struct s390_cpumsf_queue {
@@ -177,6 +183,7 @@ struct s390_cpumsf_queue {
177 unsigned int queue_nr; 183 unsigned int queue_nr;
178 struct auxtrace_buffer *buffer; 184 struct auxtrace_buffer *buffer;
179 int cpu; 185 int cpu;
186 FILE *logfile;
180}; 187};
181 188
182/* Display s390 CPU measurement facility basic-sampling data entry */ 189/* Display s390 CPU measurement facility basic-sampling data entry */
@@ -595,6 +602,12 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
595 buffer->use_size = buffer->size; 602 buffer->use_size = buffer->size;
596 buffer->use_data = buffer->data; 603 buffer->use_data = buffer->data;
597 } 604 }
605 if (sfq->logfile) { /* Write into log file */
606 size_t rc = fwrite(buffer->data, buffer->size, 1,
607 sfq->logfile);
608 if (rc != 1)
609 pr_err("Failed to write auxiliary data\n");
610 }
598 } else 611 } else
599 buffer = sfq->buffer; 612 buffer = sfq->buffer;
600 613
@@ -606,6 +619,13 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
606 return -ENOMEM; 619 return -ENOMEM;
607 buffer->use_size = buffer->size; 620 buffer->use_size = buffer->size;
608 buffer->use_data = buffer->data; 621 buffer->use_data = buffer->data;
622
623 if (sfq->logfile) { /* Write into log file */
624 size_t rc = fwrite(buffer->data, buffer->size, 1,
625 sfq->logfile);
626 if (rc != 1)
627 pr_err("Failed to write auxiliary data\n");
628 }
609 } 629 }
610 pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n", 630 pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n",
611 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset, 631 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset,
@@ -640,6 +660,23 @@ s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr)
640 sfq->sf = sf; 660 sfq->sf = sf;
641 sfq->queue_nr = queue_nr; 661 sfq->queue_nr = queue_nr;
642 sfq->cpu = -1; 662 sfq->cpu = -1;
663 if (sf->use_logfile) {
664 char *name;
665 int rc;
666
667 rc = (sf->logdir)
668 ? asprintf(&name, "%s/aux.smp.%02x",
669 sf->logdir, queue_nr)
670 : asprintf(&name, "aux.smp.%02x", queue_nr);
671 if (rc > 0)
672 sfq->logfile = fopen(name, "w");
673 if (sfq->logfile == NULL) {
674 pr_err("Failed to open auxiliary log file %s,"
675 "continue...\n", name);
676 sf->use_logfile = false;
677 }
678 free(name);
679 }
643 return sfq; 680 return sfq;
644} 681}
645 682
@@ -850,8 +887,16 @@ static void s390_cpumsf_free_queues(struct perf_session *session)
850 struct auxtrace_queues *queues = &sf->queues; 887 struct auxtrace_queues *queues = &sf->queues;
851 unsigned int i; 888 unsigned int i;
852 889
853 for (i = 0; i < queues->nr_queues; i++) 890 for (i = 0; i < queues->nr_queues; i++) {
891 struct s390_cpumsf_queue *sfq = (struct s390_cpumsf_queue *)
892 queues->queue_array[i].priv;
893
894 if (sfq != NULL && sfq->logfile) {
895 fclose(sfq->logfile);
896 sfq->logfile = NULL;
897 }
854 zfree(&queues->queue_array[i].priv); 898 zfree(&queues->queue_array[i].priv);
899 }
855 auxtrace_queues__free(queues); 900 auxtrace_queues__free(queues);
856} 901}
857 902
@@ -864,6 +909,7 @@ static void s390_cpumsf_free(struct perf_session *session)
864 auxtrace_heap__free(&sf->heap); 909 auxtrace_heap__free(&sf->heap);
865 s390_cpumsf_free_queues(session); 910 s390_cpumsf_free_queues(session);
866 session->auxtrace = NULL; 911 session->auxtrace = NULL;
912 free(sf->logdir);
867 free(sf); 913 free(sf);
868} 914}
869 915
@@ -877,17 +923,55 @@ static int s390_cpumsf_get_type(const char *cpuid)
877 923
878/* Check itrace options set on perf report command. 924/* Check itrace options set on perf report command.
879 * Return true, if none are set or all options specified can be 925 * Return true, if none are set or all options specified can be
880 * handled on s390. 926 * handled on s390 (currently only option 'd' for logging.
881 * Return false otherwise. 927 * Return false otherwise.
882 */ 928 */
883static bool check_auxtrace_itrace(struct itrace_synth_opts *itops) 929static bool check_auxtrace_itrace(struct itrace_synth_opts *itops)
884{ 930{
931 bool ison = false;
932
885 if (!itops || !itops->set) 933 if (!itops || !itops->set)
886 return true; 934 return true;
887 pr_err("No --itrace options supported\n"); 935 ison = itops->inject || itops->instructions || itops->branches ||
936 itops->transactions || itops->ptwrites ||
937 itops->pwr_events || itops->errors ||
938 itops->dont_decode || itops->calls || itops->returns ||
939 itops->callchain || itops->thread_stack ||
940 itops->last_branch;
941 if (!ison)
942 return true;
943 pr_err("Unsupported --itrace options specified\n");
888 return false; 944 return false;
889} 945}
890 946
947/* Check for AUXTRACE dump directory if it is needed.
948 * On failure print an error message but continue.
949 * Return 0 on wrong keyword in config file and 1 otherwise.
950 */
951static int s390_cpumsf__config(const char *var, const char *value, void *cb)
952{
953 struct s390_cpumsf *sf = cb;
954 struct stat stbuf;
955 int rc;
956
957 if (strcmp(var, "auxtrace.dumpdir"))
958 return 0;
959 sf->logdir = strdup(value);
960 if (sf->logdir == NULL) {
961 pr_err("Failed to find auxtrace log directory %s,"
962 " continue with current directory...\n", value);
963 return 1;
964 }
965 rc = stat(sf->logdir, &stbuf);
966 if (rc == -1 || !S_ISDIR(stbuf.st_mode)) {
967 pr_err("Missing auxtrace log directory %s,"
968 " continue with current directory...\n", value);
969 free(sf->logdir);
970 sf->logdir = NULL;
971 }
972 return 1;
973}
974
891int s390_cpumsf_process_auxtrace_info(union perf_event *event, 975int s390_cpumsf_process_auxtrace_info(union perf_event *event,
892 struct perf_session *session) 976 struct perf_session *session)
893{ 977{
@@ -906,6 +990,9 @@ int s390_cpumsf_process_auxtrace_info(union perf_event *event,
906 err = -EINVAL; 990 err = -EINVAL;
907 goto err_free; 991 goto err_free;
908 } 992 }
993 sf->use_logfile = session->itrace_synth_opts->log;
994 if (sf->use_logfile)
995 perf_config(s390_cpumsf__config, sf);
909 996
910 err = auxtrace_queues__init(&sf->queues); 997 err = auxtrace_queues__init(&sf->queues);
911 if (err) 998 if (err)
@@ -940,6 +1027,7 @@ err_free_queues:
940 auxtrace_queues__free(&sf->queues); 1027 auxtrace_queues__free(&sf->queues);
941 session->auxtrace = NULL; 1028 session->auxtrace = NULL;
942err_free: 1029err_free:
1030 free(sf->logdir);
943 free(sf); 1031 free(sf);
944 return err; 1032 return err;
945} 1033}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 45484f0f7292..89cb887648f9 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -99,7 +99,7 @@ static void define_symbolic_value(const char *ev_name,
99 LEAVE; 99 LEAVE;
100} 100}
101 101
102static void define_symbolic_values(struct print_flag_sym *field, 102static void define_symbolic_values(struct tep_print_flag_sym *field,
103 const char *ev_name, 103 const char *ev_name,
104 const char *field_name) 104 const char *field_name)
105{ 105{
@@ -157,7 +157,7 @@ static void define_flag_value(const char *ev_name,
157 LEAVE; 157 LEAVE;
158} 158}
159 159
160static void define_flag_values(struct print_flag_sym *field, 160static void define_flag_values(struct tep_print_flag_sym *field,
161 const char *ev_name, 161 const char *ev_name,
162 const char *field_name) 162 const char *field_name)
163{ 163{
@@ -189,62 +189,62 @@ static void define_flag_field(const char *ev_name,
189 LEAVE; 189 LEAVE;
190} 190}
191 191
192static void define_event_symbols(struct event_format *event, 192static void define_event_symbols(struct tep_event_format *event,
193 const char *ev_name, 193 const char *ev_name,
194 struct print_arg *args) 194 struct tep_print_arg *args)
195{ 195{
196 if (args == NULL) 196 if (args == NULL)
197 return; 197 return;
198 198
199 switch (args->type) { 199 switch (args->type) {
200 case PRINT_NULL: 200 case TEP_PRINT_NULL:
201 break; 201 break;
202 case PRINT_ATOM: 202 case TEP_PRINT_ATOM:
203 define_flag_value(ev_name, cur_field_name, "0", 203 define_flag_value(ev_name, cur_field_name, "0",
204 args->atom.atom); 204 args->atom.atom);
205 zero_flag_atom = 0; 205 zero_flag_atom = 0;
206 break; 206 break;
207 case PRINT_FIELD: 207 case TEP_PRINT_FIELD:
208 free(cur_field_name); 208 free(cur_field_name);
209 cur_field_name = strdup(args->field.name); 209 cur_field_name = strdup(args->field.name);
210 break; 210 break;
211 case PRINT_FLAGS: 211 case TEP_PRINT_FLAGS:
212 define_event_symbols(event, ev_name, args->flags.field); 212 define_event_symbols(event, ev_name, args->flags.field);
213 define_flag_field(ev_name, cur_field_name, args->flags.delim); 213 define_flag_field(ev_name, cur_field_name, args->flags.delim);
214 define_flag_values(args->flags.flags, ev_name, cur_field_name); 214 define_flag_values(args->flags.flags, ev_name, cur_field_name);
215 break; 215 break;
216 case PRINT_SYMBOL: 216 case TEP_PRINT_SYMBOL:
217 define_event_symbols(event, ev_name, args->symbol.field); 217 define_event_symbols(event, ev_name, args->symbol.field);
218 define_symbolic_field(ev_name, cur_field_name); 218 define_symbolic_field(ev_name, cur_field_name);
219 define_symbolic_values(args->symbol.symbols, ev_name, 219 define_symbolic_values(args->symbol.symbols, ev_name,
220 cur_field_name); 220 cur_field_name);
221 break; 221 break;
222 case PRINT_HEX: 222 case TEP_PRINT_HEX:
223 case PRINT_HEX_STR: 223 case TEP_PRINT_HEX_STR:
224 define_event_symbols(event, ev_name, args->hex.field); 224 define_event_symbols(event, ev_name, args->hex.field);
225 define_event_symbols(event, ev_name, args->hex.size); 225 define_event_symbols(event, ev_name, args->hex.size);
226 break; 226 break;
227 case PRINT_INT_ARRAY: 227 case TEP_PRINT_INT_ARRAY:
228 define_event_symbols(event, ev_name, args->int_array.field); 228 define_event_symbols(event, ev_name, args->int_array.field);
229 define_event_symbols(event, ev_name, args->int_array.count); 229 define_event_symbols(event, ev_name, args->int_array.count);
230 define_event_symbols(event, ev_name, args->int_array.el_size); 230 define_event_symbols(event, ev_name, args->int_array.el_size);
231 break; 231 break;
232 case PRINT_BSTRING: 232 case TEP_PRINT_BSTRING:
233 case PRINT_DYNAMIC_ARRAY: 233 case TEP_PRINT_DYNAMIC_ARRAY:
234 case PRINT_DYNAMIC_ARRAY_LEN: 234 case TEP_PRINT_DYNAMIC_ARRAY_LEN:
235 case PRINT_STRING: 235 case TEP_PRINT_STRING:
236 case PRINT_BITMASK: 236 case TEP_PRINT_BITMASK:
237 break; 237 break;
238 case PRINT_TYPE: 238 case TEP_PRINT_TYPE:
239 define_event_symbols(event, ev_name, args->typecast.item); 239 define_event_symbols(event, ev_name, args->typecast.item);
240 break; 240 break;
241 case PRINT_OP: 241 case TEP_PRINT_OP:
242 if (strcmp(args->op.op, ":") == 0) 242 if (strcmp(args->op.op, ":") == 0)
243 zero_flag_atom = 1; 243 zero_flag_atom = 1;
244 define_event_symbols(event, ev_name, args->op.left); 244 define_event_symbols(event, ev_name, args->op.left);
245 define_event_symbols(event, ev_name, args->op.right); 245 define_event_symbols(event, ev_name, args->op.right);
246 break; 246 break;
247 case PRINT_FUNC: 247 case TEP_PRINT_FUNC:
248 default: 248 default:
249 pr_err("Unsupported print arg type\n"); 249 pr_err("Unsupported print arg type\n");
250 /* we should warn... */ 250 /* we should warn... */
@@ -338,8 +338,8 @@ static void perl_process_tracepoint(struct perf_sample *sample,
338 struct addr_location *al) 338 struct addr_location *al)
339{ 339{
340 struct thread *thread = al->thread; 340 struct thread *thread = al->thread;
341 struct event_format *event = evsel->tp_format; 341 struct tep_event_format *event = evsel->tp_format;
342 struct format_field *field; 342 struct tep_format_field *field;
343 static char handler[256]; 343 static char handler[256];
344 unsigned long long val; 344 unsigned long long val;
345 unsigned long s, ns; 345 unsigned long s, ns;
@@ -388,9 +388,9 @@ static void perl_process_tracepoint(struct perf_sample *sample,
388 /* common fields other than pid can be accessed via xsub fns */ 388 /* common fields other than pid can be accessed via xsub fns */
389 389
390 for (field = event->format.fields; field; field = field->next) { 390 for (field = event->format.fields; field; field = field->next) {
391 if (field->flags & FIELD_IS_STRING) { 391 if (field->flags & TEP_FIELD_IS_STRING) {
392 int offset; 392 int offset;
393 if (field->flags & FIELD_IS_DYNAMIC) { 393 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
394 offset = *(int *)(data + field->offset); 394 offset = *(int *)(data + field->offset);
395 offset &= 0xffff; 395 offset &= 0xffff;
396 } else 396 } else
@@ -399,7 +399,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
399 } else { /* FIELD_IS_NUMERIC */ 399 } else { /* FIELD_IS_NUMERIC */
400 val = read_size(event, data + field->offset, 400 val = read_size(event, data + field->offset,
401 field->size); 401 field->size);
402 if (field->flags & FIELD_IS_SIGNED) { 402 if (field->flags & TEP_FIELD_IS_SIGNED) {
403 XPUSHs(sv_2mortal(newSViv(val))); 403 XPUSHs(sv_2mortal(newSViv(val)));
404 } else { 404 } else {
405 XPUSHs(sv_2mortal(newSVuv(val))); 405 XPUSHs(sv_2mortal(newSVuv(val)));
@@ -537,8 +537,8 @@ static int perl_stop_script(void)
537 537
538static int perl_generate_script(struct tep_handle *pevent, const char *outfile) 538static int perl_generate_script(struct tep_handle *pevent, const char *outfile)
539{ 539{
540 struct event_format *event = NULL; 540 struct tep_event_format *event = NULL;
541 struct format_field *f; 541 struct tep_format_field *f;
542 char fname[PATH_MAX]; 542 char fname[PATH_MAX];
543 int not_first, count; 543 int not_first, count;
544 FILE *ofp; 544 FILE *ofp;
@@ -646,11 +646,11 @@ sub print_backtrace\n\
646 count++; 646 count++;
647 647
648 fprintf(ofp, "%s=", f->name); 648 fprintf(ofp, "%s=", f->name);
649 if (f->flags & FIELD_IS_STRING || 649 if (f->flags & TEP_FIELD_IS_STRING ||
650 f->flags & FIELD_IS_FLAG || 650 f->flags & TEP_FIELD_IS_FLAG ||
651 f->flags & FIELD_IS_SYMBOLIC) 651 f->flags & TEP_FIELD_IS_SYMBOLIC)
652 fprintf(ofp, "%%s"); 652 fprintf(ofp, "%%s");
653 else if (f->flags & FIELD_IS_SIGNED) 653 else if (f->flags & TEP_FIELD_IS_SIGNED)
654 fprintf(ofp, "%%d"); 654 fprintf(ofp, "%%d");
655 else 655 else
656 fprintf(ofp, "%%u"); 656 fprintf(ofp, "%%u");
@@ -668,7 +668,7 @@ sub print_backtrace\n\
668 if (++count % 5 == 0) 668 if (++count % 5 == 0)
669 fprintf(ofp, "\n\t "); 669 fprintf(ofp, "\n\t ");
670 670
671 if (f->flags & FIELD_IS_FLAG) { 671 if (f->flags & TEP_FIELD_IS_FLAG) {
672 if ((count - 1) % 5 != 0) { 672 if ((count - 1) % 5 != 0) {
673 fprintf(ofp, "\n\t "); 673 fprintf(ofp, "\n\t ");
674 count = 4; 674 count = 4;
@@ -678,7 +678,7 @@ sub print_backtrace\n\
678 event->name); 678 event->name);
679 fprintf(ofp, "\"%s\", $%s)", f->name, 679 fprintf(ofp, "\"%s\", $%s)", f->name,
680 f->name); 680 f->name);
681 } else if (f->flags & FIELD_IS_SYMBOLIC) { 681 } else if (f->flags & TEP_FIELD_IS_SYMBOLIC) {
682 if ((count - 1) % 5 != 0) { 682 if ((count - 1) % 5 != 0) {
683 fprintf(ofp, "\n\t "); 683 fprintf(ofp, "\n\t ");
684 count = 4; 684 count = 4;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index dfc6093f118c..69aa93d4ee99 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -193,7 +193,7 @@ static void try_call_object(const char *handler_name, PyObject *args)
193 call_object(handler, args, handler_name); 193 call_object(handler, args, handler_name);
194} 194}
195 195
196static void define_value(enum print_arg_type field_type, 196static void define_value(enum tep_print_arg_type field_type,
197 const char *ev_name, 197 const char *ev_name,
198 const char *field_name, 198 const char *field_name,
199 const char *field_value, 199 const char *field_value,
@@ -204,7 +204,7 @@ static void define_value(enum print_arg_type field_type,
204 unsigned long long value; 204 unsigned long long value;
205 unsigned n = 0; 205 unsigned n = 0;
206 206
207 if (field_type == PRINT_SYMBOL) 207 if (field_type == TEP_PRINT_SYMBOL)
208 handler_name = "define_symbolic_value"; 208 handler_name = "define_symbolic_value";
209 209
210 t = PyTuple_New(4); 210 t = PyTuple_New(4);
@@ -223,8 +223,8 @@ static void define_value(enum print_arg_type field_type,
223 Py_DECREF(t); 223 Py_DECREF(t);
224} 224}
225 225
226static void define_values(enum print_arg_type field_type, 226static void define_values(enum tep_print_arg_type field_type,
227 struct print_flag_sym *field, 227 struct tep_print_flag_sym *field,
228 const char *ev_name, 228 const char *ev_name,
229 const char *field_name) 229 const char *field_name)
230{ 230{
@@ -235,7 +235,7 @@ static void define_values(enum print_arg_type field_type,
235 define_values(field_type, field->next, ev_name, field_name); 235 define_values(field_type, field->next, ev_name, field_name);
236} 236}
237 237
238static void define_field(enum print_arg_type field_type, 238static void define_field(enum tep_print_arg_type field_type,
239 const char *ev_name, 239 const char *ev_name,
240 const char *field_name, 240 const char *field_name,
241 const char *delim) 241 const char *delim)
@@ -244,10 +244,10 @@ static void define_field(enum print_arg_type field_type,
244 PyObject *t; 244 PyObject *t;
245 unsigned n = 0; 245 unsigned n = 0;
246 246
247 if (field_type == PRINT_SYMBOL) 247 if (field_type == TEP_PRINT_SYMBOL)
248 handler_name = "define_symbolic_field"; 248 handler_name = "define_symbolic_field";
249 249
250 if (field_type == PRINT_FLAGS) 250 if (field_type == TEP_PRINT_FLAGS)
251 t = PyTuple_New(3); 251 t = PyTuple_New(3);
252 else 252 else
253 t = PyTuple_New(2); 253 t = PyTuple_New(2);
@@ -256,7 +256,7 @@ static void define_field(enum print_arg_type field_type,
256 256
257 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); 257 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
258 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); 258 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
259 if (field_type == PRINT_FLAGS) 259 if (field_type == TEP_PRINT_FLAGS)
260 PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); 260 PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim));
261 261
262 try_call_object(handler_name, t); 262 try_call_object(handler_name, t);
@@ -264,54 +264,54 @@ static void define_field(enum print_arg_type field_type,
264 Py_DECREF(t); 264 Py_DECREF(t);
265} 265}
266 266
267static void define_event_symbols(struct event_format *event, 267static void define_event_symbols(struct tep_event_format *event,
268 const char *ev_name, 268 const char *ev_name,
269 struct print_arg *args) 269 struct tep_print_arg *args)
270{ 270{
271 if (args == NULL) 271 if (args == NULL)
272 return; 272 return;
273 273
274 switch (args->type) { 274 switch (args->type) {
275 case PRINT_NULL: 275 case TEP_PRINT_NULL:
276 break; 276 break;
277 case PRINT_ATOM: 277 case TEP_PRINT_ATOM:
278 define_value(PRINT_FLAGS, ev_name, cur_field_name, "0", 278 define_value(TEP_PRINT_FLAGS, ev_name, cur_field_name, "0",
279 args->atom.atom); 279 args->atom.atom);
280 zero_flag_atom = 0; 280 zero_flag_atom = 0;
281 break; 281 break;
282 case PRINT_FIELD: 282 case TEP_PRINT_FIELD:
283 free(cur_field_name); 283 free(cur_field_name);
284 cur_field_name = strdup(args->field.name); 284 cur_field_name = strdup(args->field.name);
285 break; 285 break;
286 case PRINT_FLAGS: 286 case TEP_PRINT_FLAGS:
287 define_event_symbols(event, ev_name, args->flags.field); 287 define_event_symbols(event, ev_name, args->flags.field);
288 define_field(PRINT_FLAGS, ev_name, cur_field_name, 288 define_field(TEP_PRINT_FLAGS, ev_name, cur_field_name,
289 args->flags.delim); 289 args->flags.delim);
290 define_values(PRINT_FLAGS, args->flags.flags, ev_name, 290 define_values(TEP_PRINT_FLAGS, args->flags.flags, ev_name,
291 cur_field_name); 291 cur_field_name);
292 break; 292 break;
293 case PRINT_SYMBOL: 293 case TEP_PRINT_SYMBOL:
294 define_event_symbols(event, ev_name, args->symbol.field); 294 define_event_symbols(event, ev_name, args->symbol.field);
295 define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL); 295 define_field(TEP_PRINT_SYMBOL, ev_name, cur_field_name, NULL);
296 define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, 296 define_values(TEP_PRINT_SYMBOL, args->symbol.symbols, ev_name,
297 cur_field_name); 297 cur_field_name);
298 break; 298 break;
299 case PRINT_HEX: 299 case TEP_PRINT_HEX:
300 case PRINT_HEX_STR: 300 case TEP_PRINT_HEX_STR:
301 define_event_symbols(event, ev_name, args->hex.field); 301 define_event_symbols(event, ev_name, args->hex.field);
302 define_event_symbols(event, ev_name, args->hex.size); 302 define_event_symbols(event, ev_name, args->hex.size);
303 break; 303 break;
304 case PRINT_INT_ARRAY: 304 case TEP_PRINT_INT_ARRAY:
305 define_event_symbols(event, ev_name, args->int_array.field); 305 define_event_symbols(event, ev_name, args->int_array.field);
306 define_event_symbols(event, ev_name, args->int_array.count); 306 define_event_symbols(event, ev_name, args->int_array.count);
307 define_event_symbols(event, ev_name, args->int_array.el_size); 307 define_event_symbols(event, ev_name, args->int_array.el_size);
308 break; 308 break;
309 case PRINT_STRING: 309 case TEP_PRINT_STRING:
310 break; 310 break;
311 case PRINT_TYPE: 311 case TEP_PRINT_TYPE:
312 define_event_symbols(event, ev_name, args->typecast.item); 312 define_event_symbols(event, ev_name, args->typecast.item);
313 break; 313 break;
314 case PRINT_OP: 314 case TEP_PRINT_OP:
315 if (strcmp(args->op.op, ":") == 0) 315 if (strcmp(args->op.op, ":") == 0)
316 zero_flag_atom = 1; 316 zero_flag_atom = 1;
317 define_event_symbols(event, ev_name, args->op.left); 317 define_event_symbols(event, ev_name, args->op.left);
@@ -319,11 +319,11 @@ static void define_event_symbols(struct event_format *event,
319 break; 319 break;
320 default: 320 default:
321 /* gcc warns for these? */ 321 /* gcc warns for these? */
322 case PRINT_BSTRING: 322 case TEP_PRINT_BSTRING:
323 case PRINT_DYNAMIC_ARRAY: 323 case TEP_PRINT_DYNAMIC_ARRAY:
324 case PRINT_DYNAMIC_ARRAY_LEN: 324 case TEP_PRINT_DYNAMIC_ARRAY_LEN:
325 case PRINT_FUNC: 325 case TEP_PRINT_FUNC:
326 case PRINT_BITMASK: 326 case TEP_PRINT_BITMASK:
327 /* we should warn... */ 327 /* we should warn... */
328 return; 328 return;
329 } 329 }
@@ -332,10 +332,10 @@ static void define_event_symbols(struct event_format *event,
332 define_event_symbols(event, ev_name, args->next); 332 define_event_symbols(event, ev_name, args->next);
333} 333}
334 334
335static PyObject *get_field_numeric_entry(struct event_format *event, 335static PyObject *get_field_numeric_entry(struct tep_event_format *event,
336 struct format_field *field, void *data) 336 struct tep_format_field *field, void *data)
337{ 337{
338 bool is_array = field->flags & FIELD_IS_ARRAY; 338 bool is_array = field->flags & TEP_FIELD_IS_ARRAY;
339 PyObject *obj = NULL, *list = NULL; 339 PyObject *obj = NULL, *list = NULL;
340 unsigned long long val; 340 unsigned long long val;
341 unsigned int item_size, n_items, i; 341 unsigned int item_size, n_items, i;
@@ -353,7 +353,7 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
353 353
354 val = read_size(event, data + field->offset + i * item_size, 354 val = read_size(event, data + field->offset + i * item_size,
355 item_size); 355 item_size);
356 if (field->flags & FIELD_IS_SIGNED) { 356 if (field->flags & TEP_FIELD_IS_SIGNED) {
357 if ((long long)val >= LONG_MIN && 357 if ((long long)val >= LONG_MIN &&
358 (long long)val <= LONG_MAX) 358 (long long)val <= LONG_MAX)
359 obj = _PyLong_FromLong(val); 359 obj = _PyLong_FromLong(val);
@@ -790,11 +790,11 @@ static void python_process_tracepoint(struct perf_sample *sample,
790 struct perf_evsel *evsel, 790 struct perf_evsel *evsel,
791 struct addr_location *al) 791 struct addr_location *al)
792{ 792{
793 struct event_format *event = evsel->tp_format; 793 struct tep_event_format *event = evsel->tp_format;
794 PyObject *handler, *context, *t, *obj = NULL, *callchain; 794 PyObject *handler, *context, *t, *obj = NULL, *callchain;
795 PyObject *dict = NULL, *all_entries_dict = NULL; 795 PyObject *dict = NULL, *all_entries_dict = NULL;
796 static char handler_name[256]; 796 static char handler_name[256];
797 struct format_field *field; 797 struct tep_format_field *field;
798 unsigned long s, ns; 798 unsigned long s, ns;
799 unsigned n = 0; 799 unsigned n = 0;
800 int pid; 800 int pid;
@@ -867,22 +867,22 @@ static void python_process_tracepoint(struct perf_sample *sample,
867 unsigned int offset, len; 867 unsigned int offset, len;
868 unsigned long long val; 868 unsigned long long val;
869 869
870 if (field->flags & FIELD_IS_ARRAY) { 870 if (field->flags & TEP_FIELD_IS_ARRAY) {
871 offset = field->offset; 871 offset = field->offset;
872 len = field->size; 872 len = field->size;
873 if (field->flags & FIELD_IS_DYNAMIC) { 873 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
874 val = tep_read_number(scripting_context->pevent, 874 val = tep_read_number(scripting_context->pevent,
875 data + offset, len); 875 data + offset, len);
876 offset = val; 876 offset = val;
877 len = offset >> 16; 877 len = offset >> 16;
878 offset &= 0xffff; 878 offset &= 0xffff;
879 } 879 }
880 if (field->flags & FIELD_IS_STRING && 880 if (field->flags & TEP_FIELD_IS_STRING &&
881 is_printable_array(data + offset, len)) { 881 is_printable_array(data + offset, len)) {
882 obj = _PyUnicode_FromString((char *) data + offset); 882 obj = _PyUnicode_FromString((char *) data + offset);
883 } else { 883 } else {
884 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); 884 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
885 field->flags &= ~FIELD_IS_STRING; 885 field->flags &= ~TEP_FIELD_IS_STRING;
886 } 886 }
887 } else { /* FIELD_IS_NUMERIC */ 887 } else { /* FIELD_IS_NUMERIC */
888 obj = get_field_numeric_entry(event, field, data); 888 obj = get_field_numeric_entry(event, field, data);
@@ -1590,8 +1590,8 @@ static int python_stop_script(void)
1590 1590
1591static int python_generate_script(struct tep_handle *pevent, const char *outfile) 1591static int python_generate_script(struct tep_handle *pevent, const char *outfile)
1592{ 1592{
1593 struct event_format *event = NULL; 1593 struct tep_event_format *event = NULL;
1594 struct format_field *f; 1594 struct tep_format_field *f;
1595 char fname[PATH_MAX]; 1595 char fname[PATH_MAX];
1596 int not_first, count; 1596 int not_first, count;
1597 FILE *ofp; 1597 FILE *ofp;
@@ -1686,12 +1686,12 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
1686 count++; 1686 count++;
1687 1687
1688 fprintf(ofp, "%s=", f->name); 1688 fprintf(ofp, "%s=", f->name);
1689 if (f->flags & FIELD_IS_STRING || 1689 if (f->flags & TEP_FIELD_IS_STRING ||
1690 f->flags & FIELD_IS_FLAG || 1690 f->flags & TEP_FIELD_IS_FLAG ||
1691 f->flags & FIELD_IS_ARRAY || 1691 f->flags & TEP_FIELD_IS_ARRAY ||
1692 f->flags & FIELD_IS_SYMBOLIC) 1692 f->flags & TEP_FIELD_IS_SYMBOLIC)
1693 fprintf(ofp, "%%s"); 1693 fprintf(ofp, "%%s");
1694 else if (f->flags & FIELD_IS_SIGNED) 1694 else if (f->flags & TEP_FIELD_IS_SIGNED)
1695 fprintf(ofp, "%%d"); 1695 fprintf(ofp, "%%d");
1696 else 1696 else
1697 fprintf(ofp, "%%u"); 1697 fprintf(ofp, "%%u");
@@ -1709,7 +1709,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
1709 if (++count % 5 == 0) 1709 if (++count % 5 == 0)
1710 fprintf(ofp, "\n\t\t"); 1710 fprintf(ofp, "\n\t\t");
1711 1711
1712 if (f->flags & FIELD_IS_FLAG) { 1712 if (f->flags & TEP_FIELD_IS_FLAG) {
1713 if ((count - 1) % 5 != 0) { 1713 if ((count - 1) % 5 != 0) {
1714 fprintf(ofp, "\n\t\t"); 1714 fprintf(ofp, "\n\t\t");
1715 count = 4; 1715 count = 4;
@@ -1719,7 +1719,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
1719 event->name); 1719 event->name);
1720 fprintf(ofp, "\"%s\", %s)", f->name, 1720 fprintf(ofp, "\"%s\", %s)", f->name,
1721 f->name); 1721 f->name);
1722 } else if (f->flags & FIELD_IS_SYMBOLIC) { 1722 } else if (f->flags & TEP_FIELD_IS_SYMBOLIC) {
1723 if ((count - 1) % 5 != 0) { 1723 if ((count - 1) % 5 != 0) {
1724 fprintf(ofp, "\n\t\t"); 1724 fprintf(ofp, "\n\t\t");
1725 count = 4; 1725 count = 4;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8b9369303561..7d2c8ce6cfad 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -199,12 +199,10 @@ void perf_session__delete(struct perf_session *session)
199 free(session); 199 free(session);
200} 200}
201 201
202static int process_event_synth_tracing_data_stub(struct perf_tool *tool 202static int process_event_synth_tracing_data_stub(struct perf_session *session
203 __maybe_unused, 203 __maybe_unused,
204 union perf_event *event 204 union perf_event *event
205 __maybe_unused, 205 __maybe_unused)
206 struct perf_session *session
207 __maybe_unused)
208{ 206{
209 dump_printf(": unhandled!\n"); 207 dump_printf(": unhandled!\n");
210 return 0; 208 return 0;
@@ -277,10 +275,8 @@ static int skipn(int fd, off_t n)
277 return 0; 275 return 0;
278} 276}
279 277
280static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused, 278static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused,
281 union perf_event *event, 279 union perf_event *event)
282 struct perf_session *session
283 __maybe_unused)
284{ 280{
285 dump_printf(": unhandled!\n"); 281 dump_printf(": unhandled!\n");
286 if (perf_data__is_pipe(session->data)) 282 if (perf_data__is_pipe(session->data))
@@ -288,9 +284,8 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
288 return event->auxtrace.size; 284 return event->auxtrace.size;
289} 285}
290 286
291static int process_event_op2_stub(struct perf_tool *tool __maybe_unused, 287static int process_event_op2_stub(struct perf_session *session __maybe_unused,
292 union perf_event *event __maybe_unused, 288 union perf_event *event __maybe_unused)
293 struct perf_session *session __maybe_unused)
294{ 289{
295 dump_printf(": unhandled!\n"); 290 dump_printf(": unhandled!\n");
296 return 0; 291 return 0;
@@ -298,9 +293,8 @@ static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
298 293
299 294
300static 295static
301int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused, 296int process_event_thread_map_stub(struct perf_session *session __maybe_unused,
302 union perf_event *event __maybe_unused, 297 union perf_event *event __maybe_unused)
303 struct perf_session *session __maybe_unused)
304{ 298{
305 if (dump_trace) 299 if (dump_trace)
306 perf_event__fprintf_thread_map(event, stdout); 300 perf_event__fprintf_thread_map(event, stdout);
@@ -310,9 +304,8 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
310} 304}
311 305
312static 306static
313int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused, 307int process_event_cpu_map_stub(struct perf_session *session __maybe_unused,
314 union perf_event *event __maybe_unused, 308 union perf_event *event __maybe_unused)
315 struct perf_session *session __maybe_unused)
316{ 309{
317 if (dump_trace) 310 if (dump_trace)
318 perf_event__fprintf_cpu_map(event, stdout); 311 perf_event__fprintf_cpu_map(event, stdout);
@@ -322,9 +315,8 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
322} 315}
323 316
324static 317static
325int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused, 318int process_event_stat_config_stub(struct perf_session *session __maybe_unused,
326 union perf_event *event __maybe_unused, 319 union perf_event *event __maybe_unused)
327 struct perf_session *session __maybe_unused)
328{ 320{
329 if (dump_trace) 321 if (dump_trace)
330 perf_event__fprintf_stat_config(event, stdout); 322 perf_event__fprintf_stat_config(event, stdout);
@@ -333,10 +325,8 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
333 return 0; 325 return 0;
334} 326}
335 327
336static int process_stat_stub(struct perf_tool *tool __maybe_unused, 328static int process_stat_stub(struct perf_session *perf_session __maybe_unused,
337 union perf_event *event __maybe_unused, 329 union perf_event *event)
338 struct perf_session *perf_session
339 __maybe_unused)
340{ 330{
341 if (dump_trace) 331 if (dump_trace)
342 perf_event__fprintf_stat(event, stdout); 332 perf_event__fprintf_stat(event, stdout);
@@ -345,10 +335,8 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
345 return 0; 335 return 0;
346} 336}
347 337
348static int process_stat_round_stub(struct perf_tool *tool __maybe_unused, 338static int process_stat_round_stub(struct perf_session *perf_session __maybe_unused,
349 union perf_event *event __maybe_unused, 339 union perf_event *event)
350 struct perf_session *perf_session
351 __maybe_unused)
352{ 340{
353 if (dump_trace) 341 if (dump_trace)
354 perf_event__fprintf_stat_round(event, stdout); 342 perf_event__fprintf_stat_round(event, stdout);
@@ -1374,37 +1362,37 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1374 case PERF_RECORD_HEADER_TRACING_DATA: 1362 case PERF_RECORD_HEADER_TRACING_DATA:
1375 /* setup for reading amidst mmap */ 1363 /* setup for reading amidst mmap */
1376 lseek(fd, file_offset, SEEK_SET); 1364 lseek(fd, file_offset, SEEK_SET);
1377 return tool->tracing_data(tool, event, session); 1365 return tool->tracing_data(session, event);
1378 case PERF_RECORD_HEADER_BUILD_ID: 1366 case PERF_RECORD_HEADER_BUILD_ID:
1379 return tool->build_id(tool, event, session); 1367 return tool->build_id(session, event);
1380 case PERF_RECORD_FINISHED_ROUND: 1368 case PERF_RECORD_FINISHED_ROUND:
1381 return tool->finished_round(tool, event, oe); 1369 return tool->finished_round(tool, event, oe);
1382 case PERF_RECORD_ID_INDEX: 1370 case PERF_RECORD_ID_INDEX:
1383 return tool->id_index(tool, event, session); 1371 return tool->id_index(session, event);
1384 case PERF_RECORD_AUXTRACE_INFO: 1372 case PERF_RECORD_AUXTRACE_INFO:
1385 return tool->auxtrace_info(tool, event, session); 1373 return tool->auxtrace_info(session, event);
1386 case PERF_RECORD_AUXTRACE: 1374 case PERF_RECORD_AUXTRACE:
1387 /* setup for reading amidst mmap */ 1375 /* setup for reading amidst mmap */
1388 lseek(fd, file_offset + event->header.size, SEEK_SET); 1376 lseek(fd, file_offset + event->header.size, SEEK_SET);
1389 return tool->auxtrace(tool, event, session); 1377 return tool->auxtrace(session, event);
1390 case PERF_RECORD_AUXTRACE_ERROR: 1378 case PERF_RECORD_AUXTRACE_ERROR:
1391 perf_session__auxtrace_error_inc(session, event); 1379 perf_session__auxtrace_error_inc(session, event);
1392 return tool->auxtrace_error(tool, event, session); 1380 return tool->auxtrace_error(session, event);
1393 case PERF_RECORD_THREAD_MAP: 1381 case PERF_RECORD_THREAD_MAP:
1394 return tool->thread_map(tool, event, session); 1382 return tool->thread_map(session, event);
1395 case PERF_RECORD_CPU_MAP: 1383 case PERF_RECORD_CPU_MAP:
1396 return tool->cpu_map(tool, event, session); 1384 return tool->cpu_map(session, event);
1397 case PERF_RECORD_STAT_CONFIG: 1385 case PERF_RECORD_STAT_CONFIG:
1398 return tool->stat_config(tool, event, session); 1386 return tool->stat_config(session, event);
1399 case PERF_RECORD_STAT: 1387 case PERF_RECORD_STAT:
1400 return tool->stat(tool, event, session); 1388 return tool->stat(session, event);
1401 case PERF_RECORD_STAT_ROUND: 1389 case PERF_RECORD_STAT_ROUND:
1402 return tool->stat_round(tool, event, session); 1390 return tool->stat_round(session, event);
1403 case PERF_RECORD_TIME_CONV: 1391 case PERF_RECORD_TIME_CONV:
1404 session->time_conv = event->time_conv; 1392 session->time_conv = event->time_conv;
1405 return tool->time_conv(tool, event, session); 1393 return tool->time_conv(session, event);
1406 case PERF_RECORD_HEADER_FEATURE: 1394 case PERF_RECORD_HEADER_FEATURE:
1407 return tool->feature(tool, event, session); 1395 return tool->feature(session, event);
1408 default: 1396 default:
1409 return -EINVAL; 1397 return -EINVAL;
1410 } 1398 }
@@ -2133,9 +2121,8 @@ out:
2133 return err; 2121 return err;
2134} 2122}
2135 2123
2136int perf_event__process_id_index(struct perf_tool *tool __maybe_unused, 2124int perf_event__process_id_index(struct perf_session *session,
2137 union perf_event *event, 2125 union perf_event *event)
2138 struct perf_session *session)
2139{ 2126{
2140 struct perf_evlist *evlist = session->evlist; 2127 struct perf_evlist *evlist = session->evlist;
2141 struct id_index_event *ie = &event->id_index; 2128 struct id_index_event *ie = &event->id_index;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index da40b4b380ca..d96eccd7d27f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -120,9 +120,8 @@ int perf_session__deliver_synth_event(struct perf_session *session,
120 union perf_event *event, 120 union perf_event *event,
121 struct perf_sample *sample); 121 struct perf_sample *sample);
122 122
123int perf_event__process_id_index(struct perf_tool *tool, 123int perf_event__process_id_index(struct perf_session *session,
124 union perf_event *event, 124 union perf_event *event);
125 struct perf_session *session);
126 125
127int perf_event__synthesize_id_index(struct perf_tool *tool, 126int perf_event__synthesize_id_index(struct perf_tool *tool,
128 perf_event__handler_t process, 127 perf_event__handler_t process,
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 97efbcad076e..63f758c655d5 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -5,16 +5,18 @@ from subprocess import Popen, PIPE
5from re import sub 5from re import sub
6 6
7def clang_has_option(option): 7def clang_has_option(option):
8 return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if "unknown argument" in o] == [ ] 8 return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if b"unknown argument" in o] == [ ]
9 9
10cc = getenv("CC") 10cc = getenv("CC")
11if cc == "clang": 11if cc == "clang":
12 from _sysconfigdata import build_time_vars 12 from distutils.sysconfig import get_config_vars
13 build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"]) 13 vars = get_config_vars()
14 if not clang_has_option("-mcet"): 14 for var in ('CFLAGS', 'OPT'):
15 build_time_vars["CFLAGS"] = sub("-mcet", "", build_time_vars["CFLAGS"]) 15 vars[var] = sub("-specs=[^ ]+", "", vars[var])
16 if not clang_has_option("-fcf-protection"): 16 if not clang_has_option("-mcet"):
17 build_time_vars["CFLAGS"] = sub("-fcf-protection", "", build_time_vars["CFLAGS"]) 17 vars[var] = sub("-mcet", "", vars[var])
18 if not clang_has_option("-fcf-protection"):
19 vars[var] = sub("-fcf-protection", "", vars[var])
18 20
19from distutils.core import setup, Extension 21from distutils.core import setup, Extension
20 22
@@ -35,7 +37,7 @@ class install_lib(_install_lib):
35 37
36cflags = getenv('CFLAGS', '').split() 38cflags = getenv('CFLAGS', '').split()
37# switch off several checks (need to be at the end of cflags list) 39# switch off several checks (need to be at the end of cflags list)
38cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ] 40cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-redundant-decls' ]
39if cc != "clang": 41if cc != "clang":
40 cflags += ['-Wno-cast-function-type' ] 42 cflags += ['-Wno-cast-function-type' ]
41 43
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b284276ec963..f96c005b3c41 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1884,7 +1884,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd,
1884struct hpp_dynamic_entry { 1884struct hpp_dynamic_entry {
1885 struct perf_hpp_fmt hpp; 1885 struct perf_hpp_fmt hpp;
1886 struct perf_evsel *evsel; 1886 struct perf_evsel *evsel;
1887 struct format_field *field; 1887 struct tep_format_field *field;
1888 unsigned dynamic_len; 1888 unsigned dynamic_len;
1889 bool raw_trace; 1889 bool raw_trace;
1890}; 1890};
@@ -1899,7 +1899,7 @@ static int hde_width(struct hpp_dynamic_entry *hde)
1899 if (namelen > len) 1899 if (namelen > len)
1900 len = namelen; 1900 len = namelen;
1901 1901
1902 if (!(hde->field->flags & FIELD_IS_STRING)) { 1902 if (!(hde->field->flags & TEP_FIELD_IS_STRING)) {
1903 /* length for print hex numbers */ 1903 /* length for print hex numbers */
1904 fieldlen = hde->field->size * 2 + 2; 1904 fieldlen = hde->field->size * 2 + 2;
1905 } 1905 }
@@ -1915,7 +1915,7 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde,
1915 struct hist_entry *he) 1915 struct hist_entry *he)
1916{ 1916{
1917 char *str, *pos; 1917 char *str, *pos;
1918 struct format_field *field = hde->field; 1918 struct tep_format_field *field = hde->field;
1919 size_t namelen; 1919 size_t namelen;
1920 bool last = false; 1920 bool last = false;
1921 1921
@@ -2000,7 +2000,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
2000 struct hpp_dynamic_entry *hde; 2000 struct hpp_dynamic_entry *hde;
2001 size_t len = fmt->user_len; 2001 size_t len = fmt->user_len;
2002 char *str, *pos; 2002 char *str, *pos;
2003 struct format_field *field; 2003 struct tep_format_field *field;
2004 size_t namelen; 2004 size_t namelen;
2005 bool last = false; 2005 bool last = false;
2006 int ret; 2006 int ret;
@@ -2060,7 +2060,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
2060 struct hist_entry *a, struct hist_entry *b) 2060 struct hist_entry *a, struct hist_entry *b)
2061{ 2061{
2062 struct hpp_dynamic_entry *hde; 2062 struct hpp_dynamic_entry *hde;
2063 struct format_field *field; 2063 struct tep_format_field *field;
2064 unsigned offset, size; 2064 unsigned offset, size;
2065 2065
2066 hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 2066 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
@@ -2071,7 +2071,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
2071 } 2071 }
2072 2072
2073 field = hde->field; 2073 field = hde->field;
2074 if (field->flags & FIELD_IS_DYNAMIC) { 2074 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
2075 unsigned long long dyn; 2075 unsigned long long dyn;
2076 2076
2077 tep_read_number_field(field, a->raw_data, &dyn); 2077 tep_read_number_field(field, a->raw_data, &dyn);
@@ -2117,7 +2117,7 @@ static void hde_free(struct perf_hpp_fmt *fmt)
2117} 2117}
2118 2118
2119static struct hpp_dynamic_entry * 2119static struct hpp_dynamic_entry *
2120__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field, 2120__alloc_dynamic_entry(struct perf_evsel *evsel, struct tep_format_field *field,
2121 int level) 2121 int level)
2122{ 2122{
2123 struct hpp_dynamic_entry *hde; 2123 struct hpp_dynamic_entry *hde;
@@ -2252,7 +2252,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
2252} 2252}
2253 2253
2254static int __dynamic_dimension__add(struct perf_evsel *evsel, 2254static int __dynamic_dimension__add(struct perf_evsel *evsel,
2255 struct format_field *field, 2255 struct tep_format_field *field,
2256 bool raw_trace, int level) 2256 bool raw_trace, int level)
2257{ 2257{
2258 struct hpp_dynamic_entry *hde; 2258 struct hpp_dynamic_entry *hde;
@@ -2270,7 +2270,7 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
2270static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level) 2270static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level)
2271{ 2271{
2272 int ret; 2272 int ret;
2273 struct format_field *field; 2273 struct tep_format_field *field;
2274 2274
2275 field = evsel->tp_format->format.fields; 2275 field = evsel->tp_format->format.fields;
2276 while (field) { 2276 while (field) {
@@ -2305,7 +2305,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
2305{ 2305{
2306 int ret = -ESRCH; 2306 int ret = -ESRCH;
2307 struct perf_evsel *evsel; 2307 struct perf_evsel *evsel;
2308 struct format_field *field; 2308 struct tep_format_field *field;
2309 2309
2310 evlist__for_each_entry(evlist, evsel) { 2310 evlist__for_each_entry(evlist, evsel) {
2311 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 2311 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
@@ -2327,7 +2327,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
2327{ 2327{
2328 char *str, *event_name, *field_name, *opt_name; 2328 char *str, *event_name, *field_name, *opt_name;
2329 struct perf_evsel *evsel; 2329 struct perf_evsel *evsel;
2330 struct format_field *field; 2330 struct tep_format_field *field;
2331 bool raw_trace = symbol_conf.raw_trace; 2331 bool raw_trace = symbol_conf.raw_trace;
2332 int ret = 0; 2332 int ret = 0;
2333 2333
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index 09d6746e6ec8..e767c4a9d4d2 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -85,6 +85,9 @@ static struct symbol *new_inline_sym(struct dso *dso,
85 struct symbol *inline_sym; 85 struct symbol *inline_sym;
86 char *demangled = NULL; 86 char *demangled = NULL;
87 87
88 if (!funcname)
89 funcname = "??";
90
88 if (dso) { 91 if (dso) {
89 demangled = dso__demangle_sym(dso, 0, funcname); 92 demangled = dso__demangle_sym(dso, 0, funcname);
90 if (demangled) 93 if (demangled)
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
new file mode 100644
index 000000000000..e7b4c44ebb62
--- /dev/null
+++ b/tools/perf/util/stat-display.c
@@ -0,0 +1,1166 @@
1#include <stdio.h>
2#include <inttypes.h>
3#include <linux/time64.h>
4#include <math.h>
5#include "evlist.h"
6#include "evsel.h"
7#include "stat.h"
8#include "top.h"
9#include "thread_map.h"
10#include "cpumap.h"
11#include "string2.h"
12#include "sane_ctype.h"
13#include "cgroup.h"
14#include <math.h>
15#include <api/fs/fs.h>
16
17#define CNTR_NOT_SUPPORTED "<not supported>"
18#define CNTR_NOT_COUNTED "<not counted>"
19
20static bool is_duration_time(struct perf_evsel *evsel)
21{
22 return !strcmp(evsel->name, "duration_time");
23}
24
25static void print_running(struct perf_stat_config *config,
26 u64 run, u64 ena)
27{
28 if (config->csv_output) {
29 fprintf(config->output, "%s%" PRIu64 "%s%.2f",
30 config->csv_sep,
31 run,
32 config->csv_sep,
33 ena ? 100.0 * run / ena : 100.0);
34 } else if (run != ena) {
35 fprintf(config->output, " (%.2f%%)", 100.0 * run / ena);
36 }
37}
38
39static void print_noise_pct(struct perf_stat_config *config,
40 double total, double avg)
41{
42 double pct = rel_stddev_stats(total, avg);
43
44 if (config->csv_output)
45 fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
46 else if (pct)
47 fprintf(config->output, " ( +-%6.2f%% )", pct);
48}
49
50static void print_noise(struct perf_stat_config *config,
51 struct perf_evsel *evsel, double avg)
52{
53 struct perf_stat_evsel *ps;
54
55 if (config->run_count == 1)
56 return;
57
58 ps = evsel->stats;
59 print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
60}
61
62static void aggr_printout(struct perf_stat_config *config,
63 struct perf_evsel *evsel, int id, int nr)
64{
65 switch (config->aggr_mode) {
66 case AGGR_CORE:
67 fprintf(config->output, "S%d-C%*d%s%*d%s",
68 cpu_map__id_to_socket(id),
69 config->csv_output ? 0 : -8,
70 cpu_map__id_to_cpu(id),
71 config->csv_sep,
72 config->csv_output ? 0 : 4,
73 nr,
74 config->csv_sep);
75 break;
76 case AGGR_SOCKET:
77 fprintf(config->output, "S%*d%s%*d%s",
78 config->csv_output ? 0 : -5,
79 id,
80 config->csv_sep,
81 config->csv_output ? 0 : 4,
82 nr,
83 config->csv_sep);
84 break;
85 case AGGR_NONE:
86 fprintf(config->output, "CPU%*d%s",
87 config->csv_output ? 0 : -4,
88 perf_evsel__cpus(evsel)->map[id], config->csv_sep);
89 break;
90 case AGGR_THREAD:
91 fprintf(config->output, "%*s-%*d%s",
92 config->csv_output ? 0 : 16,
93 thread_map__comm(evsel->threads, id),
94 config->csv_output ? 0 : -8,
95 thread_map__pid(evsel->threads, id),
96 config->csv_sep);
97 break;
98 case AGGR_GLOBAL:
99 case AGGR_UNSET:
100 default:
101 break;
102 }
103}
104
105struct outstate {
106 FILE *fh;
107 bool newline;
108 const char *prefix;
109 int nfields;
110 int id, nr;
111 struct perf_evsel *evsel;
112};
113
114#define METRIC_LEN 35
115
116static void new_line_std(struct perf_stat_config *config __maybe_unused,
117 void *ctx)
118{
119 struct outstate *os = ctx;
120
121 os->newline = true;
122}
123
124static void do_new_line_std(struct perf_stat_config *config,
125 struct outstate *os)
126{
127 fputc('\n', os->fh);
128 fputs(os->prefix, os->fh);
129 aggr_printout(config, os->evsel, os->id, os->nr);
130 if (config->aggr_mode == AGGR_NONE)
131 fprintf(os->fh, " ");
132 fprintf(os->fh, " ");
133}
134
135static void print_metric_std(struct perf_stat_config *config,
136 void *ctx, const char *color, const char *fmt,
137 const char *unit, double val)
138{
139 struct outstate *os = ctx;
140 FILE *out = os->fh;
141 int n;
142 bool newline = os->newline;
143
144 os->newline = false;
145
146 if (unit == NULL || fmt == NULL) {
147 fprintf(out, "%-*s", METRIC_LEN, "");
148 return;
149 }
150
151 if (newline)
152 do_new_line_std(config, os);
153
154 n = fprintf(out, " # ");
155 if (color)
156 n += color_fprintf(out, color, fmt, val);
157 else
158 n += fprintf(out, fmt, val);
159 fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
160}
161
162static void new_line_csv(struct perf_stat_config *config, void *ctx)
163{
164 struct outstate *os = ctx;
165 int i;
166
167 fputc('\n', os->fh);
168 if (os->prefix)
169 fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
170 aggr_printout(config, os->evsel, os->id, os->nr);
171 for (i = 0; i < os->nfields; i++)
172 fputs(config->csv_sep, os->fh);
173}
174
175static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
176 void *ctx,
177 const char *color __maybe_unused,
178 const char *fmt, const char *unit, double val)
179{
180 struct outstate *os = ctx;
181 FILE *out = os->fh;
182 char buf[64], *vals, *ends;
183
184 if (unit == NULL || fmt == NULL) {
185 fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
186 return;
187 }
188 snprintf(buf, sizeof(buf), fmt, val);
189 ends = vals = ltrim(buf);
190 while (isdigit(*ends) || *ends == '.')
191 ends++;
192 *ends = 0;
193 while (isspace(*unit))
194 unit++;
195 fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit);
196}
197
198/* Filter out some columns that don't work well in metrics only mode */
199
200static bool valid_only_metric(const char *unit)
201{
202 if (!unit)
203 return false;
204 if (strstr(unit, "/sec") ||
205 strstr(unit, "hz") ||
206 strstr(unit, "Hz") ||
207 strstr(unit, "CPUs utilized"))
208 return false;
209 return true;
210}
211
212static const char *fixunit(char *buf, struct perf_evsel *evsel,
213 const char *unit)
214{
215 if (!strncmp(unit, "of all", 6)) {
216 snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
217 unit);
218 return buf;
219 }
220 return unit;
221}
222
223static void print_metric_only(struct perf_stat_config *config,
224 void *ctx, const char *color, const char *fmt,
225 const char *unit, double val)
226{
227 struct outstate *os = ctx;
228 FILE *out = os->fh;
229 char buf[1024], str[1024];
230 unsigned mlen = config->metric_only_len;
231
232 if (!valid_only_metric(unit))
233 return;
234 unit = fixunit(buf, os->evsel, unit);
235 if (mlen < strlen(unit))
236 mlen = strlen(unit) + 1;
237
238 if (color)
239 mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
240
241 color_snprintf(str, sizeof(str), color ?: "", fmt, val);
242 fprintf(out, "%*s ", mlen, str);
243}
244
245static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
246 void *ctx, const char *color __maybe_unused,
247 const char *fmt,
248 const char *unit, double val)
249{
250 struct outstate *os = ctx;
251 FILE *out = os->fh;
252 char buf[64], *vals, *ends;
253 char tbuf[1024];
254
255 if (!valid_only_metric(unit))
256 return;
257 unit = fixunit(tbuf, os->evsel, unit);
258 snprintf(buf, sizeof buf, fmt, val);
259 ends = vals = ltrim(buf);
260 while (isdigit(*ends) || *ends == '.')
261 ends++;
262 *ends = 0;
263 fprintf(out, "%s%s", vals, config->csv_sep);
264}
265
266static void new_line_metric(struct perf_stat_config *config __maybe_unused,
267 void *ctx __maybe_unused)
268{
269}
270
271static void print_metric_header(struct perf_stat_config *config,
272 void *ctx, const char *color __maybe_unused,
273 const char *fmt __maybe_unused,
274 const char *unit, double val __maybe_unused)
275{
276 struct outstate *os = ctx;
277 char tbuf[1024];
278
279 if (!valid_only_metric(unit))
280 return;
281 unit = fixunit(tbuf, os->evsel, unit);
282 if (config->csv_output)
283 fprintf(os->fh, "%s%s", unit, config->csv_sep);
284 else
285 fprintf(os->fh, "%*s ", config->metric_only_len, unit);
286}
287
288static int first_shadow_cpu(struct perf_stat_config *config,
289 struct perf_evsel *evsel, int id)
290{
291 struct perf_evlist *evlist = evsel->evlist;
292 int i;
293
294 if (!config->aggr_get_id)
295 return 0;
296
297 if (config->aggr_mode == AGGR_NONE)
298 return id;
299
300 if (config->aggr_mode == AGGR_GLOBAL)
301 return 0;
302
303 for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
304 int cpu2 = perf_evsel__cpus(evsel)->map[i];
305
306 if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
307 return cpu2;
308 }
309 return 0;
310}
311
312static void abs_printout(struct perf_stat_config *config,
313 int id, int nr, struct perf_evsel *evsel, double avg)
314{
315 FILE *output = config->output;
316 double sc = evsel->scale;
317 const char *fmt;
318
319 if (config->csv_output) {
320 fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
321 } else {
322 if (config->big_num)
323 fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
324 else
325 fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
326 }
327
328 aggr_printout(config, evsel, id, nr);
329
330 fprintf(output, fmt, avg, config->csv_sep);
331
332 if (evsel->unit)
333 fprintf(output, "%-*s%s",
334 config->csv_output ? 0 : config->unit_width,
335 evsel->unit, config->csv_sep);
336
337 fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
338
339 if (evsel->cgrp)
340 fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name);
341}
342
343static bool is_mixed_hw_group(struct perf_evsel *counter)
344{
345 struct perf_evlist *evlist = counter->evlist;
346 u32 pmu_type = counter->attr.type;
347 struct perf_evsel *pos;
348
349 if (counter->nr_members < 2)
350 return false;
351
352 evlist__for_each_entry(evlist, pos) {
353 /* software events can be part of any hardware group */
354 if (pos->attr.type == PERF_TYPE_SOFTWARE)
355 continue;
356 if (pmu_type == PERF_TYPE_SOFTWARE) {
357 pmu_type = pos->attr.type;
358 continue;
359 }
360 if (pmu_type != pos->attr.type)
361 return true;
362 }
363
364 return false;
365}
366
367static void printout(struct perf_stat_config *config, int id, int nr,
368 struct perf_evsel *counter, double uval,
369 char *prefix, u64 run, u64 ena, double noise,
370 struct runtime_stat *st)
371{
372 struct perf_stat_output_ctx out;
373 struct outstate os = {
374 .fh = config->output,
375 .prefix = prefix ? prefix : "",
376 .id = id,
377 .nr = nr,
378 .evsel = counter,
379 };
380 print_metric_t pm = print_metric_std;
381 new_line_t nl;
382
383 if (config->metric_only) {
384 nl = new_line_metric;
385 if (config->csv_output)
386 pm = print_metric_only_csv;
387 else
388 pm = print_metric_only;
389 } else
390 nl = new_line_std;
391
392 if (config->csv_output && !config->metric_only) {
393 static int aggr_fields[] = {
394 [AGGR_GLOBAL] = 0,
395 [AGGR_THREAD] = 1,
396 [AGGR_NONE] = 1,
397 [AGGR_SOCKET] = 2,
398 [AGGR_CORE] = 2,
399 };
400
401 pm = print_metric_csv;
402 nl = new_line_csv;
403 os.nfields = 3;
404 os.nfields += aggr_fields[config->aggr_mode];
405 if (counter->cgrp)
406 os.nfields++;
407 }
408 if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
409 if (config->metric_only) {
410 pm(config, &os, NULL, "", "", 0);
411 return;
412 }
413 aggr_printout(config, counter, id, nr);
414
415 fprintf(config->output, "%*s%s",
416 config->csv_output ? 0 : 18,
417 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
418 config->csv_sep);
419
420 if (counter->supported) {
421 config->print_free_counters_hint = 1;
422 if (is_mixed_hw_group(counter))
423 config->print_mixed_hw_group_error = 1;
424 }
425
426 fprintf(config->output, "%-*s%s",
427 config->csv_output ? 0 : config->unit_width,
428 counter->unit, config->csv_sep);
429
430 fprintf(config->output, "%*s",
431 config->csv_output ? 0 : -25,
432 perf_evsel__name(counter));
433
434 if (counter->cgrp)
435 fprintf(config->output, "%s%s",
436 config->csv_sep, counter->cgrp->name);
437
438 if (!config->csv_output)
439 pm(config, &os, NULL, NULL, "", 0);
440 print_noise(config, counter, noise);
441 print_running(config, run, ena);
442 if (config->csv_output)
443 pm(config, &os, NULL, NULL, "", 0);
444 return;
445 }
446
447 if (!config->metric_only)
448 abs_printout(config, id, nr, counter, uval);
449
450 out.print_metric = pm;
451 out.new_line = nl;
452 out.ctx = &os;
453 out.force_header = false;
454
455 if (config->csv_output && !config->metric_only) {
456 print_noise(config, counter, noise);
457 print_running(config, run, ena);
458 }
459
460 perf_stat__print_shadow_stats(config, counter, uval,
461 first_shadow_cpu(config, counter, id),
462 &out, &config->metric_events, st);
463 if (!config->csv_output && !config->metric_only) {
464 print_noise(config, counter, noise);
465 print_running(config, run, ena);
466 }
467}
468
469static void aggr_update_shadow(struct perf_stat_config *config,
470 struct perf_evlist *evlist)
471{
472 int cpu, s2, id, s;
473 u64 val;
474 struct perf_evsel *counter;
475
476 for (s = 0; s < config->aggr_map->nr; s++) {
477 id = config->aggr_map->map[s];
478 evlist__for_each_entry(evlist, counter) {
479 val = 0;
480 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
481 s2 = config->aggr_get_id(config, evlist->cpus, cpu);
482 if (s2 != id)
483 continue;
484 val += perf_counts(counter->counts, cpu, 0)->val;
485 }
486 perf_stat__update_shadow_stats(counter, val,
487 first_shadow_cpu(config, counter, id),
488 &rt_stat);
489 }
490 }
491}
492
493static void uniquify_event_name(struct perf_evsel *counter)
494{
495 char *new_name;
496 char *config;
497
498 if (counter->uniquified_name ||
499 !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
500 strlen(counter->pmu_name)))
501 return;
502
503 config = strchr(counter->name, '/');
504 if (config) {
505 if (asprintf(&new_name,
506 "%s%s", counter->pmu_name, config) > 0) {
507 free(counter->name);
508 counter->name = new_name;
509 }
510 } else {
511 if (asprintf(&new_name,
512 "%s [%s]", counter->name, counter->pmu_name) > 0) {
513 free(counter->name);
514 counter->name = new_name;
515 }
516 }
517
518 counter->uniquified_name = true;
519}
520
521static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
522 void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
523 bool first),
524 void *data)
525{
526 struct perf_evlist *evlist = counter->evlist;
527 struct perf_evsel *alias;
528
529 alias = list_prepare_entry(counter, &(evlist->entries), node);
530 list_for_each_entry_continue (alias, &evlist->entries, node) {
531 if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
532 alias->scale != counter->scale ||
533 alias->cgrp != counter->cgrp ||
534 strcmp(alias->unit, counter->unit) ||
535 perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
536 break;
537 alias->merged_stat = true;
538 cb(config, alias, data, false);
539 }
540}
541
542static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
543 void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
544 bool first),
545 void *data)
546{
547 if (counter->merged_stat)
548 return false;
549 cb(config, counter, data, true);
550 if (config->no_merge)
551 uniquify_event_name(counter);
552 else if (counter->auto_merge_stats)
553 collect_all_aliases(config, counter, cb, data);
554 return true;
555}
556
557struct aggr_data {
558 u64 ena, run, val;
559 int id;
560 int nr;
561 int cpu;
562};
563
564static void aggr_cb(struct perf_stat_config *config,
565 struct perf_evsel *counter, void *data, bool first)
566{
567 struct aggr_data *ad = data;
568 int cpu, s2;
569
570 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
571 struct perf_counts_values *counts;
572
573 s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
574 if (s2 != ad->id)
575 continue;
576 if (first)
577 ad->nr++;
578 counts = perf_counts(counter->counts, cpu, 0);
579 /*
580 * When any result is bad, make them all to give
581 * consistent output in interval mode.
582 */
583 if (counts->ena == 0 || counts->run == 0 ||
584 counter->counts->scaled == -1) {
585 ad->ena = 0;
586 ad->run = 0;
587 break;
588 }
589 ad->val += counts->val;
590 ad->ena += counts->ena;
591 ad->run += counts->run;
592 }
593}
594
595static void print_aggr(struct perf_stat_config *config,
596 struct perf_evlist *evlist,
597 char *prefix)
598{
599 bool metric_only = config->metric_only;
600 FILE *output = config->output;
601 struct perf_evsel *counter;
602 int s, id, nr;
603 double uval;
604 u64 ena, run, val;
605 bool first;
606
607 if (!(config->aggr_map || config->aggr_get_id))
608 return;
609
610 aggr_update_shadow(config, evlist);
611
612 /*
613 * With metric_only everything is on a single line.
614 * Without each counter has its own line.
615 */
616 for (s = 0; s < config->aggr_map->nr; s++) {
617 struct aggr_data ad;
618 if (prefix && metric_only)
619 fprintf(output, "%s", prefix);
620
621 ad.id = id = config->aggr_map->map[s];
622 first = true;
623 evlist__for_each_entry(evlist, counter) {
624 if (is_duration_time(counter))
625 continue;
626
627 ad.val = ad.ena = ad.run = 0;
628 ad.nr = 0;
629 if (!collect_data(config, counter, aggr_cb, &ad))
630 continue;
631 nr = ad.nr;
632 ena = ad.ena;
633 run = ad.run;
634 val = ad.val;
635 if (first && metric_only) {
636 first = false;
637 aggr_printout(config, counter, id, nr);
638 }
639 if (prefix && !metric_only)
640 fprintf(output, "%s", prefix);
641
642 uval = val * counter->scale;
643 printout(config, id, nr, counter, uval, prefix,
644 run, ena, 1.0, &rt_stat);
645 if (!metric_only)
646 fputc('\n', output);
647 }
648 if (metric_only)
649 fputc('\n', output);
650 }
651}
652
653static int cmp_val(const void *a, const void *b)
654{
655 return ((struct perf_aggr_thread_value *)b)->val -
656 ((struct perf_aggr_thread_value *)a)->val;
657}
658
659static struct perf_aggr_thread_value *sort_aggr_thread(
660 struct perf_evsel *counter,
661 int nthreads, int ncpus,
662 int *ret,
663 struct target *_target)
664{
665 int cpu, thread, i = 0;
666 double uval;
667 struct perf_aggr_thread_value *buf;
668
669 buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
670 if (!buf)
671 return NULL;
672
673 for (thread = 0; thread < nthreads; thread++) {
674 u64 ena = 0, run = 0, val = 0;
675
676 for (cpu = 0; cpu < ncpus; cpu++) {
677 val += perf_counts(counter->counts, cpu, thread)->val;
678 ena += perf_counts(counter->counts, cpu, thread)->ena;
679 run += perf_counts(counter->counts, cpu, thread)->run;
680 }
681
682 uval = val * counter->scale;
683
684 /*
685 * Skip value 0 when enabling --per-thread globally,
686 * otherwise too many 0 output.
687 */
688 if (uval == 0.0 && target__has_per_thread(_target))
689 continue;
690
691 buf[i].counter = counter;
692 buf[i].id = thread;
693 buf[i].uval = uval;
694 buf[i].val = val;
695 buf[i].run = run;
696 buf[i].ena = ena;
697 i++;
698 }
699
700 qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
701
702 if (ret)
703 *ret = i;
704
705 return buf;
706}
707
708static void print_aggr_thread(struct perf_stat_config *config,
709 struct target *_target,
710 struct perf_evsel *counter, char *prefix)
711{
712 FILE *output = config->output;
713 int nthreads = thread_map__nr(counter->threads);
714 int ncpus = cpu_map__nr(counter->cpus);
715 int thread, sorted_threads, id;
716 struct perf_aggr_thread_value *buf;
717
718 buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
719 if (!buf) {
720 perror("cannot sort aggr thread");
721 return;
722 }
723
724 for (thread = 0; thread < sorted_threads; thread++) {
725 if (prefix)
726 fprintf(output, "%s", prefix);
727
728 id = buf[thread].id;
729 if (config->stats)
730 printout(config, id, 0, buf[thread].counter, buf[thread].uval,
731 prefix, buf[thread].run, buf[thread].ena, 1.0,
732 &config->stats[id]);
733 else
734 printout(config, id, 0, buf[thread].counter, buf[thread].uval,
735 prefix, buf[thread].run, buf[thread].ena, 1.0,
736 &rt_stat);
737 fputc('\n', output);
738 }
739
740 free(buf);
741}
742
743struct caggr_data {
744 double avg, avg_enabled, avg_running;
745};
746
747static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
748 struct perf_evsel *counter, void *data,
749 bool first __maybe_unused)
750{
751 struct caggr_data *cd = data;
752 struct perf_stat_evsel *ps = counter->stats;
753
754 cd->avg += avg_stats(&ps->res_stats[0]);
755 cd->avg_enabled += avg_stats(&ps->res_stats[1]);
756 cd->avg_running += avg_stats(&ps->res_stats[2]);
757}
758
759/*
760 * Print out the results of a single counter:
761 * aggregated counts in system-wide mode
762 */
763static void print_counter_aggr(struct perf_stat_config *config,
764 struct perf_evsel *counter, char *prefix)
765{
766 bool metric_only = config->metric_only;
767 FILE *output = config->output;
768 double uval;
769 struct caggr_data cd = { .avg = 0.0 };
770
771 if (!collect_data(config, counter, counter_aggr_cb, &cd))
772 return;
773
774 if (prefix && !metric_only)
775 fprintf(output, "%s", prefix);
776
777 uval = cd.avg * counter->scale;
778 printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
779 cd.avg, &rt_stat);
780 if (!metric_only)
781 fprintf(output, "\n");
782}
783
784static void counter_cb(struct perf_stat_config *config __maybe_unused,
785 struct perf_evsel *counter, void *data,
786 bool first __maybe_unused)
787{
788 struct aggr_data *ad = data;
789
790 ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
791 ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
792 ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
793}
794
795/*
796 * Print out the results of a single counter:
797 * does not use aggregated count in system-wide
798 */
799static void print_counter(struct perf_stat_config *config,
800 struct perf_evsel *counter, char *prefix)
801{
802 FILE *output = config->output;
803 u64 ena, run, val;
804 double uval;
805 int cpu;
806
807 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
808 struct aggr_data ad = { .cpu = cpu };
809
810 if (!collect_data(config, counter, counter_cb, &ad))
811 return;
812 val = ad.val;
813 ena = ad.ena;
814 run = ad.run;
815
816 if (prefix)
817 fprintf(output, "%s", prefix);
818
819 uval = val * counter->scale;
820 printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
821 &rt_stat);
822
823 fputc('\n', output);
824 }
825}
826
827static void print_no_aggr_metric(struct perf_stat_config *config,
828 struct perf_evlist *evlist,
829 char *prefix)
830{
831 int cpu;
832 int nrcpus = 0;
833 struct perf_evsel *counter;
834 u64 ena, run, val;
835 double uval;
836
837 nrcpus = evlist->cpus->nr;
838 for (cpu = 0; cpu < nrcpus; cpu++) {
839 bool first = true;
840
841 if (prefix)
842 fputs(prefix, config->output);
843 evlist__for_each_entry(evlist, counter) {
844 if (is_duration_time(counter))
845 continue;
846 if (first) {
847 aggr_printout(config, counter, cpu, 0);
848 first = false;
849 }
850 val = perf_counts(counter->counts, cpu, 0)->val;
851 ena = perf_counts(counter->counts, cpu, 0)->ena;
852 run = perf_counts(counter->counts, cpu, 0)->run;
853
854 uval = val * counter->scale;
855 printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
856 &rt_stat);
857 }
858 fputc('\n', config->output);
859 }
860}
861
862static int aggr_header_lens[] = {
863 [AGGR_CORE] = 18,
864 [AGGR_SOCKET] = 12,
865 [AGGR_NONE] = 6,
866 [AGGR_THREAD] = 24,
867 [AGGR_GLOBAL] = 0,
868};
869
870static const char *aggr_header_csv[] = {
871 [AGGR_CORE] = "core,cpus,",
872 [AGGR_SOCKET] = "socket,cpus",
873 [AGGR_NONE] = "cpu,",
874 [AGGR_THREAD] = "comm-pid,",
875 [AGGR_GLOBAL] = ""
876};
877
878static void print_metric_headers(struct perf_stat_config *config,
879 struct perf_evlist *evlist,
880 const char *prefix, bool no_indent)
881{
882 struct perf_stat_output_ctx out;
883 struct perf_evsel *counter;
884 struct outstate os = {
885 .fh = config->output
886 };
887
888 if (prefix)
889 fprintf(config->output, "%s", prefix);
890
891 if (!config->csv_output && !no_indent)
892 fprintf(config->output, "%*s",
893 aggr_header_lens[config->aggr_mode], "");
894 if (config->csv_output) {
895 if (config->interval)
896 fputs("time,", config->output);
897 fputs(aggr_header_csv[config->aggr_mode], config->output);
898 }
899
900 /* Print metrics headers only */
901 evlist__for_each_entry(evlist, counter) {
902 if (is_duration_time(counter))
903 continue;
904 os.evsel = counter;
905 out.ctx = &os;
906 out.print_metric = print_metric_header;
907 out.new_line = new_line_metric;
908 out.force_header = true;
909 os.evsel = counter;
910 perf_stat__print_shadow_stats(config, counter, 0,
911 0,
912 &out,
913 &config->metric_events,
914 &rt_stat);
915 }
916 fputc('\n', config->output);
917}
918
919static void print_interval(struct perf_stat_config *config,
920 struct perf_evlist *evlist,
921 char *prefix, struct timespec *ts)
922{
923 bool metric_only = config->metric_only;
924 unsigned int unit_width = config->unit_width;
925 FILE *output = config->output;
926 static int num_print_interval;
927
928 if (config->interval_clear)
929 puts(CONSOLE_CLEAR);
930
931 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
932
933 if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
934 switch (config->aggr_mode) {
935 case AGGR_SOCKET:
936 fprintf(output, "# time socket cpus");
937 if (!metric_only)
938 fprintf(output, " counts %*s events\n", unit_width, "unit");
939 break;
940 case AGGR_CORE:
941 fprintf(output, "# time core cpus");
942 if (!metric_only)
943 fprintf(output, " counts %*s events\n", unit_width, "unit");
944 break;
945 case AGGR_NONE:
946 fprintf(output, "# time CPU ");
947 if (!metric_only)
948 fprintf(output, " counts %*s events\n", unit_width, "unit");
949 break;
950 case AGGR_THREAD:
951 fprintf(output, "# time comm-pid");
952 if (!metric_only)
953 fprintf(output, " counts %*s events\n", unit_width, "unit");
954 break;
955 case AGGR_GLOBAL:
956 default:
957 fprintf(output, "# time");
958 if (!metric_only)
959 fprintf(output, " counts %*s events\n", unit_width, "unit");
960 case AGGR_UNSET:
961 break;
962 }
963 }
964
965 if ((num_print_interval == 0 || config->interval_clear) && metric_only)
966 print_metric_headers(config, evlist, " ", true);
967 if (++num_print_interval == 25)
968 num_print_interval = 0;
969}
970
971static void print_header(struct perf_stat_config *config,
972 struct target *_target,
973 int argc, const char **argv)
974{
975 FILE *output = config->output;
976 int i;
977
978 fflush(stdout);
979
980 if (!config->csv_output) {
981 fprintf(output, "\n");
982 fprintf(output, " Performance counter stats for ");
983 if (_target->system_wide)
984 fprintf(output, "\'system wide");
985 else if (_target->cpu_list)
986 fprintf(output, "\'CPU(s) %s", _target->cpu_list);
987 else if (!target__has_task(_target)) {
988 fprintf(output, "\'%s", argv ? argv[0] : "pipe");
989 for (i = 1; argv && (i < argc); i++)
990 fprintf(output, " %s", argv[i]);
991 } else if (_target->pid)
992 fprintf(output, "process id \'%s", _target->pid);
993 else
994 fprintf(output, "thread id \'%s", _target->tid);
995
996 fprintf(output, "\'");
997 if (config->run_count > 1)
998 fprintf(output, " (%d runs)", config->run_count);
999 fprintf(output, ":\n\n");
1000 }
1001}
1002
1003static int get_precision(double num)
1004{
1005 if (num > 1)
1006 return 0;
1007
1008 return lround(ceil(-log10(num)));
1009}
1010
1011static void print_table(struct perf_stat_config *config,
1012 FILE *output, int precision, double avg)
1013{
1014 char tmp[64];
1015 int idx, indent = 0;
1016
1017 scnprintf(tmp, 64, " %17.*f", precision, avg);
1018 while (tmp[indent] == ' ')
1019 indent++;
1020
1021 fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
1022
1023 for (idx = 0; idx < config->run_count; idx++) {
1024 double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
1025 int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
1026
1027 fprintf(output, " %17.*f (%+.*f) ",
1028 precision, run, precision, run - avg);
1029
1030 for (h = 0; h < n; h++)
1031 fprintf(output, "#");
1032
1033 fprintf(output, "\n");
1034 }
1035
1036 fprintf(output, "\n%*s# Final result:\n", indent, "");
1037}
1038
1039static double timeval2double(struct timeval *t)
1040{
1041 return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
1042}
1043
1044static void print_footer(struct perf_stat_config *config)
1045{
1046 double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
1047 FILE *output = config->output;
1048 int n;
1049
1050 if (!config->null_run)
1051 fprintf(output, "\n");
1052
1053 if (config->run_count == 1) {
1054 fprintf(output, " %17.9f seconds time elapsed", avg);
1055
1056 if (config->ru_display) {
1057 double ru_utime = timeval2double(&config->ru_data.ru_utime);
1058 double ru_stime = timeval2double(&config->ru_data.ru_stime);
1059
1060 fprintf(output, "\n\n");
1061 fprintf(output, " %17.9f seconds user\n", ru_utime);
1062 fprintf(output, " %17.9f seconds sys\n", ru_stime);
1063 }
1064 } else {
1065 double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
1066 /*
1067 * Display at most 2 more significant
1068 * digits than the stddev inaccuracy.
1069 */
1070 int precision = get_precision(sd) + 2;
1071
1072 if (config->walltime_run_table)
1073 print_table(config, output, precision, avg);
1074
1075 fprintf(output, " %17.*f +- %.*f seconds time elapsed",
1076 precision, avg, precision, sd);
1077
1078 print_noise_pct(config, sd, avg);
1079 }
1080 fprintf(output, "\n\n");
1081
1082 if (config->print_free_counters_hint &&
1083 sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
1084 n > 0)
1085 fprintf(output,
1086"Some events weren't counted. Try disabling the NMI watchdog:\n"
1087" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1088" perf stat ...\n"
1089" echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1090
1091 if (config->print_mixed_hw_group_error)
1092 fprintf(output,
1093 "The events in group usually have to be from "
1094 "the same PMU. Try reorganizing the group.\n");
1095}
1096
1097void
1098perf_evlist__print_counters(struct perf_evlist *evlist,
1099 struct perf_stat_config *config,
1100 struct target *_target,
1101 struct timespec *ts,
1102 int argc, const char **argv)
1103{
1104 bool metric_only = config->metric_only;
1105 int interval = config->interval;
1106 struct perf_evsel *counter;
1107 char buf[64], *prefix = NULL;
1108
1109 if (interval)
1110 print_interval(config, evlist, prefix = buf, ts);
1111 else
1112 print_header(config, _target, argc, argv);
1113
1114 if (metric_only) {
1115 static int num_print_iv;
1116
1117 if (num_print_iv == 0 && !interval)
1118 print_metric_headers(config, evlist, prefix, false);
1119 if (num_print_iv++ == 25)
1120 num_print_iv = 0;
1121 if (config->aggr_mode == AGGR_GLOBAL && prefix)
1122 fprintf(config->output, "%s", prefix);
1123 }
1124
1125 switch (config->aggr_mode) {
1126 case AGGR_CORE:
1127 case AGGR_SOCKET:
1128 print_aggr(config, evlist, prefix);
1129 break;
1130 case AGGR_THREAD:
1131 evlist__for_each_entry(evlist, counter) {
1132 if (is_duration_time(counter))
1133 continue;
1134 print_aggr_thread(config, _target, counter, prefix);
1135 }
1136 break;
1137 case AGGR_GLOBAL:
1138 evlist__for_each_entry(evlist, counter) {
1139 if (is_duration_time(counter))
1140 continue;
1141 print_counter_aggr(config, counter, prefix);
1142 }
1143 if (metric_only)
1144 fputc('\n', config->output);
1145 break;
1146 case AGGR_NONE:
1147 if (metric_only)
1148 print_no_aggr_metric(config, evlist, prefix);
1149 else {
1150 evlist__for_each_entry(evlist, counter) {
1151 if (is_duration_time(counter))
1152 continue;
1153 print_counter(config, counter, prefix);
1154 }
1155 }
1156 break;
1157 case AGGR_UNSET:
1158 default:
1159 break;
1160 }
1161
1162 if (!interval && !config->csv_output)
1163 print_footer(config);
1164
1165 fflush(config->output);
1166}
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 99990f5f2512..8ad32763cfff 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -410,7 +410,8 @@ static double runtime_stat_n(struct runtime_stat *st,
410 return v->stats.n; 410 return v->stats.n;
411} 411}
412 412
413static void print_stalled_cycles_frontend(int cpu, 413static void print_stalled_cycles_frontend(struct perf_stat_config *config,
414 int cpu,
414 struct perf_evsel *evsel, double avg, 415 struct perf_evsel *evsel, double avg,
415 struct perf_stat_output_ctx *out, 416 struct perf_stat_output_ctx *out,
416 struct runtime_stat *st) 417 struct runtime_stat *st)
@@ -427,13 +428,14 @@ static void print_stalled_cycles_frontend(int cpu,
427 color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio); 428 color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
428 429
429 if (ratio) 430 if (ratio)
430 out->print_metric(out->ctx, color, "%7.2f%%", "frontend cycles idle", 431 out->print_metric(config, out->ctx, color, "%7.2f%%", "frontend cycles idle",
431 ratio); 432 ratio);
432 else 433 else
433 out->print_metric(out->ctx, NULL, NULL, "frontend cycles idle", 0); 434 out->print_metric(config, out->ctx, NULL, NULL, "frontend cycles idle", 0);
434} 435}
435 436
436static void print_stalled_cycles_backend(int cpu, 437static void print_stalled_cycles_backend(struct perf_stat_config *config,
438 int cpu,
437 struct perf_evsel *evsel, double avg, 439 struct perf_evsel *evsel, double avg,
438 struct perf_stat_output_ctx *out, 440 struct perf_stat_output_ctx *out,
439 struct runtime_stat *st) 441 struct runtime_stat *st)
@@ -449,10 +451,11 @@ static void print_stalled_cycles_backend(int cpu,
449 451
450 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); 452 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
451 453
452 out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio); 454 out->print_metric(config, out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
453} 455}
454 456
455static void print_branch_misses(int cpu, 457static void print_branch_misses(struct perf_stat_config *config,
458 int cpu,
456 struct perf_evsel *evsel, 459 struct perf_evsel *evsel,
457 double avg, 460 double avg,
458 struct perf_stat_output_ctx *out, 461 struct perf_stat_output_ctx *out,
@@ -469,10 +472,11 @@ static void print_branch_misses(int cpu,
469 472
470 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 473 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
471 474
472 out->print_metric(out->ctx, color, "%7.2f%%", "of all branches", ratio); 475 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all branches", ratio);
473} 476}
474 477
475static void print_l1_dcache_misses(int cpu, 478static void print_l1_dcache_misses(struct perf_stat_config *config,
479 int cpu,
476 struct perf_evsel *evsel, 480 struct perf_evsel *evsel,
477 double avg, 481 double avg,
478 struct perf_stat_output_ctx *out, 482 struct perf_stat_output_ctx *out,
@@ -490,10 +494,11 @@ static void print_l1_dcache_misses(int cpu,
490 494
491 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 495 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
492 496
493 out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio); 497 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
494} 498}
495 499
496static void print_l1_icache_misses(int cpu, 500static void print_l1_icache_misses(struct perf_stat_config *config,
501 int cpu,
497 struct perf_evsel *evsel, 502 struct perf_evsel *evsel,
498 double avg, 503 double avg,
499 struct perf_stat_output_ctx *out, 504 struct perf_stat_output_ctx *out,
@@ -510,10 +515,11 @@ static void print_l1_icache_misses(int cpu,
510 ratio = avg / total * 100.0; 515 ratio = avg / total * 100.0;
511 516
512 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 517 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
513 out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio); 518 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
514} 519}
515 520
516static void print_dtlb_cache_misses(int cpu, 521static void print_dtlb_cache_misses(struct perf_stat_config *config,
522 int cpu,
517 struct perf_evsel *evsel, 523 struct perf_evsel *evsel,
518 double avg, 524 double avg,
519 struct perf_stat_output_ctx *out, 525 struct perf_stat_output_ctx *out,
@@ -529,10 +535,11 @@ static void print_dtlb_cache_misses(int cpu,
529 ratio = avg / total * 100.0; 535 ratio = avg / total * 100.0;
530 536
531 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 537 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
532 out->print_metric(out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio); 538 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
533} 539}
534 540
535static void print_itlb_cache_misses(int cpu, 541static void print_itlb_cache_misses(struct perf_stat_config *config,
542 int cpu,
536 struct perf_evsel *evsel, 543 struct perf_evsel *evsel,
537 double avg, 544 double avg,
538 struct perf_stat_output_ctx *out, 545 struct perf_stat_output_ctx *out,
@@ -548,10 +555,11 @@ static void print_itlb_cache_misses(int cpu,
548 ratio = avg / total * 100.0; 555 ratio = avg / total * 100.0;
549 556
550 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 557 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
551 out->print_metric(out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio); 558 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
552} 559}
553 560
554static void print_ll_cache_misses(int cpu, 561static void print_ll_cache_misses(struct perf_stat_config *config,
562 int cpu,
555 struct perf_evsel *evsel, 563 struct perf_evsel *evsel,
556 double avg, 564 double avg,
557 struct perf_stat_output_ctx *out, 565 struct perf_stat_output_ctx *out,
@@ -567,7 +575,7 @@ static void print_ll_cache_misses(int cpu,
567 ratio = avg / total * 100.0; 575 ratio = avg / total * 100.0;
568 576
569 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 577 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
570 out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); 578 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
571} 579}
572 580
573/* 581/*
@@ -674,7 +682,8 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)
674 return sanitize_val(1.0 - sum); 682 return sanitize_val(1.0 - sum);
675} 683}
676 684
677static void print_smi_cost(int cpu, struct perf_evsel *evsel, 685static void print_smi_cost(struct perf_stat_config *config,
686 int cpu, struct perf_evsel *evsel,
678 struct perf_stat_output_ctx *out, 687 struct perf_stat_output_ctx *out,
679 struct runtime_stat *st) 688 struct runtime_stat *st)
680{ 689{
@@ -694,11 +703,12 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel,
694 703
695 if (cost > 10) 704 if (cost > 10)
696 color = PERF_COLOR_RED; 705 color = PERF_COLOR_RED;
697 out->print_metric(out->ctx, color, "%8.1f%%", "SMI cycles%", cost); 706 out->print_metric(config, out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
698 out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num); 707 out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num);
699} 708}
700 709
701static void generic_metric(const char *metric_expr, 710static void generic_metric(struct perf_stat_config *config,
711 const char *metric_expr,
702 struct perf_evsel **metric_events, 712 struct perf_evsel **metric_events,
703 char *name, 713 char *name,
704 const char *metric_name, 714 const char *metric_name,
@@ -737,20 +747,21 @@ static void generic_metric(const char *metric_expr,
737 const char *p = metric_expr; 747 const char *p = metric_expr;
738 748
739 if (expr__parse(&ratio, &pctx, &p) == 0) 749 if (expr__parse(&ratio, &pctx, &p) == 0)
740 print_metric(ctxp, NULL, "%8.1f", 750 print_metric(config, ctxp, NULL, "%8.1f",
741 metric_name ? 751 metric_name ?
742 metric_name : 752 metric_name :
743 out->force_header ? name : "", 753 out->force_header ? name : "",
744 ratio); 754 ratio);
745 else 755 else
746 print_metric(ctxp, NULL, NULL, 756 print_metric(config, ctxp, NULL, NULL,
747 out->force_header ? 757 out->force_header ?
748 (metric_name ? metric_name : name) : "", 0); 758 (metric_name ? metric_name : name) : "", 0);
749 } else 759 } else
750 print_metric(ctxp, NULL, NULL, "", 0); 760 print_metric(config, ctxp, NULL, NULL, "", 0);
751} 761}
752 762
753void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 763void perf_stat__print_shadow_stats(struct perf_stat_config *config,
764 struct perf_evsel *evsel,
754 double avg, int cpu, 765 double avg, int cpu,
755 struct perf_stat_output_ctx *out, 766 struct perf_stat_output_ctx *out,
756 struct rblist *metric_events, 767 struct rblist *metric_events,
@@ -769,10 +780,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
769 780
770 if (total) { 781 if (total) {
771 ratio = avg / total; 782 ratio = avg / total;
772 print_metric(ctxp, NULL, "%7.2f ", 783 print_metric(config, ctxp, NULL, "%7.2f ",
773 "insn per cycle", ratio); 784 "insn per cycle", ratio);
774 } else { 785 } else {
775 print_metric(ctxp, NULL, NULL, "insn per cycle", 0); 786 print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0);
776 } 787 }
777 788
778 total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT, 789 total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT,
@@ -783,20 +794,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
783 ctx, cpu)); 794 ctx, cpu));
784 795
785 if (total && avg) { 796 if (total && avg) {
786 out->new_line(ctxp); 797 out->new_line(config, ctxp);
787 ratio = total / avg; 798 ratio = total / avg;
788 print_metric(ctxp, NULL, "%7.2f ", 799 print_metric(config, ctxp, NULL, "%7.2f ",
789 "stalled cycles per insn", 800 "stalled cycles per insn",
790 ratio); 801 ratio);
791 } else if (have_frontend_stalled) { 802 } else if (have_frontend_stalled) {
792 print_metric(ctxp, NULL, NULL, 803 print_metric(config, ctxp, NULL, NULL,
793 "stalled cycles per insn", 0); 804 "stalled cycles per insn", 0);
794 } 805 }
795 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) { 806 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
796 if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0) 807 if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0)
797 print_branch_misses(cpu, evsel, avg, out, st); 808 print_branch_misses(config, cpu, evsel, avg, out, st);
798 else 809 else
799 print_metric(ctxp, NULL, NULL, "of all branches", 0); 810 print_metric(config, ctxp, NULL, NULL, "of all branches", 0);
800 } else if ( 811 } else if (
801 evsel->attr.type == PERF_TYPE_HW_CACHE && 812 evsel->attr.type == PERF_TYPE_HW_CACHE &&
802 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | 813 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D |
@@ -804,9 +815,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
804 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 815 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
805 816
806 if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0) 817 if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0)
807 print_l1_dcache_misses(cpu, evsel, avg, out, st); 818 print_l1_dcache_misses(config, cpu, evsel, avg, out, st);
808 else 819 else
809 print_metric(ctxp, NULL, NULL, "of all L1-dcache hits", 0); 820 print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0);
810 } else if ( 821 } else if (
811 evsel->attr.type == PERF_TYPE_HW_CACHE && 822 evsel->attr.type == PERF_TYPE_HW_CACHE &&
812 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I | 823 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I |
@@ -814,9 +825,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
814 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 825 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
815 826
816 if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0) 827 if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0)
817 print_l1_icache_misses(cpu, evsel, avg, out, st); 828 print_l1_icache_misses(config, cpu, evsel, avg, out, st);
818 else 829 else
819 print_metric(ctxp, NULL, NULL, "of all L1-icache hits", 0); 830 print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0);
820 } else if ( 831 } else if (
821 evsel->attr.type == PERF_TYPE_HW_CACHE && 832 evsel->attr.type == PERF_TYPE_HW_CACHE &&
822 evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB | 833 evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB |
@@ -824,9 +835,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
824 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 835 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
825 836
826 if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0) 837 if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0)
827 print_dtlb_cache_misses(cpu, evsel, avg, out, st); 838 print_dtlb_cache_misses(config, cpu, evsel, avg, out, st);
828 else 839 else
829 print_metric(ctxp, NULL, NULL, "of all dTLB cache hits", 0); 840 print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0);
830 } else if ( 841 } else if (
831 evsel->attr.type == PERF_TYPE_HW_CACHE && 842 evsel->attr.type == PERF_TYPE_HW_CACHE &&
832 evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB | 843 evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB |
@@ -834,9 +845,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
834 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 845 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
835 846
836 if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0) 847 if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0)
837 print_itlb_cache_misses(cpu, evsel, avg, out, st); 848 print_itlb_cache_misses(config, cpu, evsel, avg, out, st);
838 else 849 else
839 print_metric(ctxp, NULL, NULL, "of all iTLB cache hits", 0); 850 print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0);
840 } else if ( 851 } else if (
841 evsel->attr.type == PERF_TYPE_HW_CACHE && 852 evsel->attr.type == PERF_TYPE_HW_CACHE &&
842 evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL | 853 evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL |
@@ -844,9 +855,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
844 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 855 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
845 856
846 if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0) 857 if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0)
847 print_ll_cache_misses(cpu, evsel, avg, out, st); 858 print_ll_cache_misses(config, cpu, evsel, avg, out, st);
848 else 859 else
849 print_metric(ctxp, NULL, NULL, "of all LL-cache hits", 0); 860 print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0);
850 } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) { 861 } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
851 total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu); 862 total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu);
852 863
@@ -854,32 +865,32 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
854 ratio = avg * 100 / total; 865 ratio = avg * 100 / total;
855 866
856 if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0) 867 if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0)
857 print_metric(ctxp, NULL, "%8.3f %%", 868 print_metric(config, ctxp, NULL, "%8.3f %%",
858 "of all cache refs", ratio); 869 "of all cache refs", ratio);
859 else 870 else
860 print_metric(ctxp, NULL, NULL, "of all cache refs", 0); 871 print_metric(config, ctxp, NULL, NULL, "of all cache refs", 0);
861 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { 872 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
862 print_stalled_cycles_frontend(cpu, evsel, avg, out, st); 873 print_stalled_cycles_frontend(config, cpu, evsel, avg, out, st);
863 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) { 874 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
864 print_stalled_cycles_backend(cpu, evsel, avg, out, st); 875 print_stalled_cycles_backend(config, cpu, evsel, avg, out, st);
865 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 876 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
866 total = runtime_stat_avg(st, STAT_NSECS, 0, cpu); 877 total = runtime_stat_avg(st, STAT_NSECS, 0, cpu);
867 878
868 if (total) { 879 if (total) {
869 ratio = avg / total; 880 ratio = avg / total;
870 print_metric(ctxp, NULL, "%8.3f", "GHz", ratio); 881 print_metric(config, ctxp, NULL, "%8.3f", "GHz", ratio);
871 } else { 882 } else {
872 print_metric(ctxp, NULL, NULL, "Ghz", 0); 883 print_metric(config, ctxp, NULL, NULL, "Ghz", 0);
873 } 884 }
874 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) { 885 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) {
875 total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu); 886 total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
876 887
877 if (total) 888 if (total)
878 print_metric(ctxp, NULL, 889 print_metric(config, ctxp, NULL,
879 "%7.2f%%", "transactional cycles", 890 "%7.2f%%", "transactional cycles",
880 100.0 * (avg / total)); 891 100.0 * (avg / total));
881 else 892 else
882 print_metric(ctxp, NULL, NULL, "transactional cycles", 893 print_metric(config, ctxp, NULL, NULL, "transactional cycles",
883 0); 894 0);
884 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) { 895 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) {
885 total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu); 896 total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
@@ -888,10 +899,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
888 if (total2 < avg) 899 if (total2 < avg)
889 total2 = avg; 900 total2 = avg;
890 if (total) 901 if (total)
891 print_metric(ctxp, NULL, "%7.2f%%", "aborted cycles", 902 print_metric(config, ctxp, NULL, "%7.2f%%", "aborted cycles",
892 100.0 * ((total2-avg) / total)); 903 100.0 * ((total2-avg) / total));
893 else 904 else
894 print_metric(ctxp, NULL, NULL, "aborted cycles", 0); 905 print_metric(config, ctxp, NULL, NULL, "aborted cycles", 0);
895 } else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) { 906 } else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) {
896 total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, 907 total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
897 ctx, cpu); 908 ctx, cpu);
@@ -900,10 +911,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
900 ratio = total / avg; 911 ratio = total / avg;
901 912
902 if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0) 913 if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0)
903 print_metric(ctxp, NULL, "%8.0f", 914 print_metric(config, ctxp, NULL, "%8.0f",
904 "cycles / transaction", ratio); 915 "cycles / transaction", ratio);
905 else 916 else
906 print_metric(ctxp, NULL, NULL, "cycles / transaction", 917 print_metric(config, ctxp, NULL, NULL, "cycles / transaction",
907 0); 918 0);
908 } else if (perf_stat_evsel__is(evsel, ELISION_START)) { 919 } else if (perf_stat_evsel__is(evsel, ELISION_START)) {
909 total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, 920 total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
@@ -912,33 +923,33 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
912 if (avg) 923 if (avg)
913 ratio = total / avg; 924 ratio = total / avg;
914 925
915 print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio); 926 print_metric(config, ctxp, NULL, "%8.0f", "cycles / elision", ratio);
916 } else if (perf_evsel__is_clock(evsel)) { 927 } else if (perf_evsel__is_clock(evsel)) {
917 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0) 928 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
918 print_metric(ctxp, NULL, "%8.3f", "CPUs utilized", 929 print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized",
919 avg / (ratio * evsel->scale)); 930 avg / (ratio * evsel->scale));
920 else 931 else
921 print_metric(ctxp, NULL, NULL, "CPUs utilized", 0); 932 print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0);
922 } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) { 933 } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) {
923 double fe_bound = td_fe_bound(ctx, cpu, st); 934 double fe_bound = td_fe_bound(ctx, cpu, st);
924 935
925 if (fe_bound > 0.2) 936 if (fe_bound > 0.2)
926 color = PERF_COLOR_RED; 937 color = PERF_COLOR_RED;
927 print_metric(ctxp, color, "%8.1f%%", "frontend bound", 938 print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
928 fe_bound * 100.); 939 fe_bound * 100.);
929 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) { 940 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) {
930 double retiring = td_retiring(ctx, cpu, st); 941 double retiring = td_retiring(ctx, cpu, st);
931 942
932 if (retiring > 0.7) 943 if (retiring > 0.7)
933 color = PERF_COLOR_GREEN; 944 color = PERF_COLOR_GREEN;
934 print_metric(ctxp, color, "%8.1f%%", "retiring", 945 print_metric(config, ctxp, color, "%8.1f%%", "retiring",
935 retiring * 100.); 946 retiring * 100.);
936 } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) { 947 } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) {
937 double bad_spec = td_bad_spec(ctx, cpu, st); 948 double bad_spec = td_bad_spec(ctx, cpu, st);
938 949
939 if (bad_spec > 0.1) 950 if (bad_spec > 0.1)
940 color = PERF_COLOR_RED; 951 color = PERF_COLOR_RED;
941 print_metric(ctxp, color, "%8.1f%%", "bad speculation", 952 print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
942 bad_spec * 100.); 953 bad_spec * 100.);
943 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) { 954 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) {
944 double be_bound = td_be_bound(ctx, cpu, st); 955 double be_bound = td_be_bound(ctx, cpu, st);
@@ -955,12 +966,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
955 if (be_bound > 0.2) 966 if (be_bound > 0.2)
956 color = PERF_COLOR_RED; 967 color = PERF_COLOR_RED;
957 if (td_total_slots(ctx, cpu, st) > 0) 968 if (td_total_slots(ctx, cpu, st) > 0)
958 print_metric(ctxp, color, "%8.1f%%", name, 969 print_metric(config, ctxp, color, "%8.1f%%", name,
959 be_bound * 100.); 970 be_bound * 100.);
960 else 971 else
961 print_metric(ctxp, NULL, NULL, name, 0); 972 print_metric(config, ctxp, NULL, NULL, name, 0);
962 } else if (evsel->metric_expr) { 973 } else if (evsel->metric_expr) {
963 generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name, 974 generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name,
964 evsel->metric_name, avg, cpu, out, st); 975 evsel->metric_name, avg, cpu, out, st);
965 } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { 976 } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {
966 char unit = 'M'; 977 char unit = 'M';
@@ -975,9 +986,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
975 unit = 'K'; 986 unit = 'K';
976 } 987 }
977 snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit); 988 snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
978 print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio); 989 print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
979 } else if (perf_stat_evsel__is(evsel, SMI_NUM)) { 990 } else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
980 print_smi_cost(cpu, evsel, out, st); 991 print_smi_cost(config, cpu, evsel, out, st);
981 } else { 992 } else {
982 num = 0; 993 num = 0;
983 } 994 }
@@ -987,12 +998,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
987 998
988 list_for_each_entry (mexp, &me->head, nd) { 999 list_for_each_entry (mexp, &me->head, nd) {
989 if (num++ > 0) 1000 if (num++ > 0)
990 out->new_line(ctxp); 1001 out->new_line(config, ctxp);
991 generic_metric(mexp->metric_expr, mexp->metric_events, 1002 generic_metric(config, mexp->metric_expr, mexp->metric_events,
992 evsel->name, mexp->metric_name, 1003 evsel->name, mexp->metric_name,
993 avg, cpu, out, st); 1004 avg, cpu, out, st);
994 } 1005 }
995 } 1006 }
996 if (num == 0) 1007 if (num == 0)
997 print_metric(ctxp, NULL, NULL, NULL, 0); 1008 print_metric(config, ctxp, NULL, NULL, NULL, 0);
998} 1009}
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index a0061e0b0fad..4d40515307b8 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -374,9 +374,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
374 return 0; 374 return 0;
375} 375}
376 376
377int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused, 377int perf_event__process_stat_event(struct perf_session *session,
378 union perf_event *event, 378 union perf_event *event)
379 struct perf_session *session)
380{ 379{
381 struct perf_counts_values count; 380 struct perf_counts_values count;
382 struct stat_event *st = &event->stat; 381 struct stat_event *st = &event->stat;
@@ -435,3 +434,98 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
435 434
436 return ret; 435 return ret;
437} 436}
437
438int create_perf_stat_counter(struct perf_evsel *evsel,
439 struct perf_stat_config *config,
440 struct target *target)
441{
442 struct perf_event_attr *attr = &evsel->attr;
443 struct perf_evsel *leader = evsel->leader;
444
445 if (config->scale) {
446 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
447 PERF_FORMAT_TOTAL_TIME_RUNNING;
448 }
449
450 /*
451 * The event is part of non trivial group, let's enable
452 * the group read (for leader) and ID retrieval for all
453 * members.
454 */
455 if (leader->nr_members > 1)
456 attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
457
458 attr->inherit = !config->no_inherit;
459
460 /*
461 * Some events get initialized with sample_(period/type) set,
462 * like tracepoints. Clear it up for counting.
463 */
464 attr->sample_period = 0;
465
466 if (config->identifier)
467 attr->sample_type = PERF_SAMPLE_IDENTIFIER;
468
469 /*
470 * Disabling all counters initially, they will be enabled
471 * either manually by us or by kernel via enable_on_exec
472 * set later.
473 */
474 if (perf_evsel__is_group_leader(evsel)) {
475 attr->disabled = 1;
476
477 /*
478 * In case of initial_delay we enable tracee
479 * events manually.
480 */
481 if (target__none(target) && !config->initial_delay)
482 attr->enable_on_exec = 1;
483 }
484
485 if (target__has_cpu(target) && !target__has_per_thread(target))
486 return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
487
488 return perf_evsel__open_per_thread(evsel, evsel->threads);
489}
490
491int perf_stat_synthesize_config(struct perf_stat_config *config,
492 struct perf_tool *tool,
493 struct perf_evlist *evlist,
494 perf_event__handler_t process,
495 bool attrs)
496{
497 int err;
498
499 if (attrs) {
500 err = perf_event__synthesize_attrs(tool, evlist, process);
501 if (err < 0) {
502 pr_err("Couldn't synthesize attrs.\n");
503 return err;
504 }
505 }
506
507 err = perf_event__synthesize_extra_attr(tool, evlist, process,
508 attrs);
509
510 err = perf_event__synthesize_thread_map2(tool, evlist->threads,
511 process, NULL);
512 if (err < 0) {
513 pr_err("Couldn't synthesize thread map.\n");
514 return err;
515 }
516
517 err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
518 process, NULL);
519 if (err < 0) {
520 pr_err("Couldn't synthesize thread map.\n");
521 return err;
522 }
523
524 err = perf_event__synthesize_stat_config(tool, config, process, NULL);
525 if (err < 0) {
526 pr_err("Couldn't synthesize config.\n");
527 return err;
528 }
529
530 return 0;
531}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 36efb986f7fc..2f9c9159a364 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -4,8 +4,14 @@
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <stdio.h> 6#include <stdio.h>
7#include <sys/types.h>
8#include <sys/time.h>
9#include <sys/resource.h>
10#include <sys/wait.h>
7#include "xyarray.h" 11#include "xyarray.h"
8#include "rblist.h" 12#include "rblist.h"
13#include "perf.h"
14#include "event.h"
9 15
10struct stats { 16struct stats {
11 double n, mean, M2; 17 double n, mean, M2;
@@ -84,15 +90,42 @@ struct runtime_stat {
84 struct rblist value_list; 90 struct rblist value_list;
85}; 91};
86 92
93typedef int (*aggr_get_id_t)(struct perf_stat_config *config,
94 struct cpu_map *m, int cpu);
95
87struct perf_stat_config { 96struct perf_stat_config {
88 enum aggr_mode aggr_mode; 97 enum aggr_mode aggr_mode;
89 bool scale; 98 bool scale;
90 FILE *output; 99 bool no_inherit;
91 unsigned int interval; 100 bool identifier;
92 unsigned int timeout; 101 bool csv_output;
93 int times; 102 bool interval_clear;
94 struct runtime_stat *stats; 103 bool metric_only;
95 int stats_num; 104 bool null_run;
105 bool ru_display;
106 bool big_num;
107 bool no_merge;
108 bool walltime_run_table;
109 FILE *output;
110 unsigned int interval;
111 unsigned int timeout;
112 unsigned int initial_delay;
113 unsigned int unit_width;
114 unsigned int metric_only_len;
115 int times;
116 int run_count;
117 int print_free_counters_hint;
118 int print_mixed_hw_group_error;
119 struct runtime_stat *stats;
120 int stats_num;
121 const char *csv_sep;
122 struct stats *walltime_nsecs_stats;
123 struct rusage ru_data;
124 struct cpu_map *aggr_map;
125 aggr_get_id_t aggr_get_id;
126 struct cpu_map *cpus_aggr_map;
127 u64 *walltime_run;
128 struct rblist metric_events;
96}; 129};
97 130
98void update_stats(struct stats *stats, u64 val); 131void update_stats(struct stats *stats, u64 val);
@@ -130,9 +163,10 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
130extern struct runtime_stat rt_stat; 163extern struct runtime_stat rt_stat;
131extern struct stats walltime_nsecs_stats; 164extern struct stats walltime_nsecs_stats;
132 165
133typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit, 166typedef void (*print_metric_t)(struct perf_stat_config *config,
167 void *ctx, const char *color, const char *unit,
134 const char *fmt, double val); 168 const char *fmt, double val);
135typedef void (*new_line_t )(void *ctx); 169typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx);
136 170
137void runtime_stat__init(struct runtime_stat *st); 171void runtime_stat__init(struct runtime_stat *st);
138void runtime_stat__exit(struct runtime_stat *st); 172void runtime_stat__exit(struct runtime_stat *st);
@@ -148,7 +182,8 @@ struct perf_stat_output_ctx {
148 bool force_header; 182 bool force_header;
149}; 183};
150 184
151void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 185void perf_stat__print_shadow_stats(struct perf_stat_config *config,
186 struct perf_evsel *evsel,
152 double avg, int cpu, 187 double avg, int cpu,
153 struct perf_stat_output_ctx *out, 188 struct perf_stat_output_ctx *out,
154 struct rblist *metric_events, 189 struct rblist *metric_events,
@@ -164,11 +199,25 @@ int perf_stat_process_counter(struct perf_stat_config *config,
164struct perf_tool; 199struct perf_tool;
165union perf_event; 200union perf_event;
166struct perf_session; 201struct perf_session;
167int perf_event__process_stat_event(struct perf_tool *tool, 202int perf_event__process_stat_event(struct perf_session *session,
168 union perf_event *event, 203 union perf_event *event);
169 struct perf_session *session);
170 204
171size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp); 205size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
172size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp); 206size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
173size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp); 207size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
208
209int create_perf_stat_counter(struct perf_evsel *evsel,
210 struct perf_stat_config *config,
211 struct target *target);
212int perf_stat_synthesize_config(struct perf_stat_config *config,
213 struct perf_tool *tool,
214 struct perf_evlist *evlist,
215 perf_event__handler_t process,
216 bool attrs);
217void
218perf_evlist__print_counters(struct perf_evlist *evlist,
219 struct perf_stat_config *config,
220 struct target *_target,
221 struct timespec *ts,
222 int argc, const char **argv);
174#endif 223#endif
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 3d1cf5bf7f18..9005fbe0780e 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -98,19 +98,25 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
98 98
99 va_copy(ap_saved, ap); 99 va_copy(ap_saved, ap);
100 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 100 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
101 if (len < 0) 101 if (len < 0) {
102 va_end(ap_saved);
102 return len; 103 return len;
104 }
103 if (len > strbuf_avail(sb)) { 105 if (len > strbuf_avail(sb)) {
104 ret = strbuf_grow(sb, len); 106 ret = strbuf_grow(sb, len);
105 if (ret) 107 if (ret) {
108 va_end(ap_saved);
106 return ret; 109 return ret;
110 }
107 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); 111 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
108 va_end(ap_saved); 112 va_end(ap_saved);
109 if (len > strbuf_avail(sb)) { 113 if (len > strbuf_avail(sb)) {
110 pr_debug("this should not happen, your vsnprintf is broken"); 114 pr_debug("this should not happen, your vsnprintf is broken");
115 va_end(ap_saved);
111 return -EINVAL; 116 return -EINVAL;
112 } 117 }
113 } 118 }
119 va_end(ap_saved);
114 return strbuf_setlen(sb, sb->len + len); 120 return strbuf_setlen(sb, sb->len + len);
115} 121}
116 122
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index dd17d6a38d3a..c091635bf7dc 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -36,6 +36,7 @@
36 * @branch_count: the branch count when the entry was created 36 * @branch_count: the branch count when the entry was created
37 * @cp: call path 37 * @cp: call path
38 * @no_call: a 'call' was not seen 38 * @no_call: a 'call' was not seen
39 * @trace_end: a 'call' but trace ended
39 */ 40 */
40struct thread_stack_entry { 41struct thread_stack_entry {
41 u64 ret_addr; 42 u64 ret_addr;
@@ -44,6 +45,7 @@ struct thread_stack_entry {
44 u64 branch_count; 45 u64 branch_count;
45 struct call_path *cp; 46 struct call_path *cp;
46 bool no_call; 47 bool no_call;
48 bool trace_end;
47}; 49};
48 50
49/** 51/**
@@ -112,7 +114,8 @@ static struct thread_stack *thread_stack__new(struct thread *thread,
112 return ts; 114 return ts;
113} 115}
114 116
115static int thread_stack__push(struct thread_stack *ts, u64 ret_addr) 117static int thread_stack__push(struct thread_stack *ts, u64 ret_addr,
118 bool trace_end)
116{ 119{
117 int err = 0; 120 int err = 0;
118 121
@@ -124,6 +127,7 @@ static int thread_stack__push(struct thread_stack *ts, u64 ret_addr)
124 } 127 }
125 } 128 }
126 129
130 ts->stack[ts->cnt].trace_end = trace_end;
127 ts->stack[ts->cnt++].ret_addr = ret_addr; 131 ts->stack[ts->cnt++].ret_addr = ret_addr;
128 132
129 return err; 133 return err;
@@ -150,6 +154,18 @@ static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr)
150 } 154 }
151} 155}
152 156
157static void thread_stack__pop_trace_end(struct thread_stack *ts)
158{
159 size_t i;
160
161 for (i = ts->cnt; i; ) {
162 if (ts->stack[--i].trace_end)
163 ts->cnt = i;
164 else
165 return;
166 }
167}
168
153static bool thread_stack__in_kernel(struct thread_stack *ts) 169static bool thread_stack__in_kernel(struct thread_stack *ts)
154{ 170{
155 if (!ts->cnt) 171 if (!ts->cnt)
@@ -254,10 +270,19 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
254 ret_addr = from_ip + insn_len; 270 ret_addr = from_ip + insn_len;
255 if (ret_addr == to_ip) 271 if (ret_addr == to_ip)
256 return 0; /* Zero-length calls are excluded */ 272 return 0; /* Zero-length calls are excluded */
257 return thread_stack__push(thread->ts, ret_addr); 273 return thread_stack__push(thread->ts, ret_addr,
258 } else if (flags & PERF_IP_FLAG_RETURN) { 274 flags & PERF_IP_FLAG_TRACE_END);
259 if (!from_ip) 275 } else if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
260 return 0; 276 /*
277 * If the caller did not change the trace number (which would
278 * have flushed the stack) then try to make sense of the stack.
279 * Possibly, tracing began after returning to the current
280 * address, so try to pop that. Also, do not expect a call made
281 * when the trace ended, to return, so pop that.
282 */
283 thread_stack__pop(thread->ts, to_ip);
284 thread_stack__pop_trace_end(thread->ts);
285 } else if ((flags & PERF_IP_FLAG_RETURN) && from_ip) {
261 thread_stack__pop(thread->ts, to_ip); 286 thread_stack__pop(thread->ts, to_ip);
262 } 287 }
263 288
@@ -332,7 +357,7 @@ void call_return_processor__free(struct call_return_processor *crp)
332 357
333static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr, 358static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
334 u64 timestamp, u64 ref, struct call_path *cp, 359 u64 timestamp, u64 ref, struct call_path *cp,
335 bool no_call) 360 bool no_call, bool trace_end)
336{ 361{
337 struct thread_stack_entry *tse; 362 struct thread_stack_entry *tse;
338 int err; 363 int err;
@@ -350,6 +375,7 @@ static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
350 tse->branch_count = ts->branch_count; 375 tse->branch_count = ts->branch_count;
351 tse->cp = cp; 376 tse->cp = cp;
352 tse->no_call = no_call; 377 tse->no_call = no_call;
378 tse->trace_end = trace_end;
353 379
354 return 0; 380 return 0;
355} 381}
@@ -423,7 +449,7 @@ static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts,
423 return -ENOMEM; 449 return -ENOMEM;
424 450
425 return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp, 451 return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp,
426 true); 452 true, false);
427} 453}
428 454
429static int thread_stack__no_call_return(struct thread *thread, 455static int thread_stack__no_call_return(struct thread *thread,
@@ -455,7 +481,7 @@ static int thread_stack__no_call_return(struct thread *thread,
455 if (!cp) 481 if (!cp)
456 return -ENOMEM; 482 return -ENOMEM;
457 return thread_stack__push_cp(ts, 0, sample->time, ref, 483 return thread_stack__push_cp(ts, 0, sample->time, ref,
458 cp, true); 484 cp, true, false);
459 } 485 }
460 } else if (thread_stack__in_kernel(ts) && sample->ip < ks) { 486 } else if (thread_stack__in_kernel(ts) && sample->ip < ks) {
461 /* Return to userspace, so pop all kernel addresses */ 487 /* Return to userspace, so pop all kernel addresses */
@@ -480,7 +506,7 @@ static int thread_stack__no_call_return(struct thread *thread,
480 return -ENOMEM; 506 return -ENOMEM;
481 507
482 err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp, 508 err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp,
483 true); 509 true, false);
484 if (err) 510 if (err)
485 return err; 511 return err;
486 512
@@ -500,7 +526,7 @@ static int thread_stack__trace_begin(struct thread *thread,
500 526
501 /* Pop trace end */ 527 /* Pop trace end */
502 tse = &ts->stack[ts->cnt - 1]; 528 tse = &ts->stack[ts->cnt - 1];
503 if (tse->cp->sym == NULL && tse->cp->ip == 0) { 529 if (tse->trace_end) {
504 err = thread_stack__call_return(thread, ts, --ts->cnt, 530 err = thread_stack__call_return(thread, ts, --ts->cnt,
505 timestamp, ref, false); 531 timestamp, ref, false);
506 if (err) 532 if (err)
@@ -529,7 +555,7 @@ static int thread_stack__trace_end(struct thread_stack *ts,
529 ret_addr = sample->ip + sample->insn_len; 555 ret_addr = sample->ip + sample->insn_len;
530 556
531 return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp, 557 return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp,
532 false); 558 false, true);
533} 559}
534 560
535int thread_stack__process(struct thread *thread, struct comm *comm, 561int thread_stack__process(struct thread *thread, struct comm *comm,
@@ -579,6 +605,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
579 ts->last_time = sample->time; 605 ts->last_time = sample->time;
580 606
581 if (sample->flags & PERF_IP_FLAG_CALL) { 607 if (sample->flags & PERF_IP_FLAG_CALL) {
608 bool trace_end = sample->flags & PERF_IP_FLAG_TRACE_END;
582 struct call_path_root *cpr = ts->crp->cpr; 609 struct call_path_root *cpr = ts->crp->cpr;
583 struct call_path *cp; 610 struct call_path *cp;
584 u64 ret_addr; 611 u64 ret_addr;
@@ -596,7 +623,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
596 if (!cp) 623 if (!cp)
597 return -ENOMEM; 624 return -ENOMEM;
598 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref, 625 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
599 cp, false); 626 cp, false, trace_end);
600 } else if (sample->flags & PERF_IP_FLAG_RETURN) { 627 } else if (sample->flags & PERF_IP_FLAG_RETURN) {
601 if (!sample->ip || !sample->addr) 628 if (!sample->ip || !sample->addr)
602 return 0; 629 return 0;
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 183c91453522..56e4ca54020a 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -26,15 +26,12 @@ typedef int (*event_attr_op)(struct perf_tool *tool,
26 union perf_event *event, 26 union perf_event *event,
27 struct perf_evlist **pevlist); 27 struct perf_evlist **pevlist);
28 28
29typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event, 29typedef int (*event_op2)(struct perf_session *session, union perf_event *event);
30 struct perf_session *session); 30typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event);
31 31
32typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event, 32typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
33 struct ordered_events *oe); 33 struct ordered_events *oe);
34 34
35typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event,
36 struct perf_session *session);
37
38enum show_feature_header { 35enum show_feature_header {
39 SHOW_FEAT_NO_HEADER = 0, 36 SHOW_FEAT_NO_HEADER = 0,
40 SHOW_FEAT_HEADER, 37 SHOW_FEAT_HEADER,
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index c85d0d1a65ed..8ad8e755127b 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -377,7 +377,7 @@ out:
377 377
378static int record_saved_cmdline(void) 378static int record_saved_cmdline(void)
379{ 379{
380 unsigned int size; 380 unsigned long long size;
381 char *path; 381 char *path;
382 struct stat st; 382 struct stat st;
383 int ret, err = 0; 383 int ret, err = 0;
@@ -531,12 +531,14 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
531 "/tmp/perf-XXXXXX"); 531 "/tmp/perf-XXXXXX");
532 if (!mkstemp(tdata->temp_file)) { 532 if (!mkstemp(tdata->temp_file)) {
533 pr_debug("Can't make temp file"); 533 pr_debug("Can't make temp file");
534 free(tdata);
534 return NULL; 535 return NULL;
535 } 536 }
536 537
537 temp_fd = open(tdata->temp_file, O_RDWR); 538 temp_fd = open(tdata->temp_file, O_RDWR);
538 if (temp_fd < 0) { 539 if (temp_fd < 0) {
539 pr_debug("Can't read '%s'", tdata->temp_file); 540 pr_debug("Can't read '%s'", tdata->temp_file);
541 free(tdata);
540 return NULL; 542 return NULL;
541 } 543 }
542 544
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 920b1d58a068..32e558a65af3 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -33,14 +33,15 @@ static int get_common_field(struct scripting_context *context,
33 int *offset, int *size, const char *type) 33 int *offset, int *size, const char *type)
34{ 34{
35 struct tep_handle *pevent = context->pevent; 35 struct tep_handle *pevent = context->pevent;
36 struct event_format *event; 36 struct tep_event_format *event;
37 struct format_field *field; 37 struct tep_format_field *field;
38 38
39 if (!*size) { 39 if (!*size) {
40 if (!pevent->events) 40
41 event = tep_get_first_event(pevent);
42 if (!event)
41 return 0; 43 return 0;
42 44
43 event = pevent->events[0];
44 field = tep_find_common_field(event, type); 45 field = tep_find_common_field(event, type);
45 if (!field) 46 if (!field)
46 return 0; 47 return 0;
@@ -94,9 +95,9 @@ int common_pc(struct scripting_context *context)
94} 95}
95 96
96unsigned long long 97unsigned long long
97raw_field_value(struct event_format *event, const char *name, void *data) 98raw_field_value(struct tep_event_format *event, const char *name, void *data)
98{ 99{
99 struct format_field *field; 100 struct tep_format_field *field;
100 unsigned long long val; 101 unsigned long long val;
101 102
102 field = tep_find_any_field(event, name); 103 field = tep_find_any_field(event, name);
@@ -108,12 +109,12 @@ raw_field_value(struct event_format *event, const char *name, void *data)
108 return val; 109 return val;
109} 110}
110 111
111unsigned long long read_size(struct event_format *event, void *ptr, int size) 112unsigned long long read_size(struct tep_event_format *event, void *ptr, int size)
112{ 113{
113 return tep_read_number(event->pevent, ptr, size); 114 return tep_read_number(event->pevent, ptr, size);
114} 115}
115 116
116void event_format__fprintf(struct event_format *event, 117void event_format__fprintf(struct tep_event_format *event,
117 int cpu, void *data, int size, FILE *fp) 118 int cpu, void *data, int size, FILE *fp)
118{ 119{
119 struct tep_record record; 120 struct tep_record record;
@@ -130,7 +131,7 @@ void event_format__fprintf(struct event_format *event,
130 trace_seq_destroy(&s); 131 trace_seq_destroy(&s);
131} 132}
132 133
133void event_format__print(struct event_format *event, 134void event_format__print(struct tep_event_format *event,
134 int cpu, void *data, int size) 135 int cpu, void *data, int size)
135{ 136{
136 return event_format__fprintf(event, cpu, data, size, stdout); 137 return event_format__fprintf(event, cpu, data, size, stdout);
@@ -158,22 +159,22 @@ void parse_ftrace_printk(struct tep_handle *pevent,
158 printk = strdup(fmt+1); 159 printk = strdup(fmt+1);
159 line = strtok_r(NULL, "\n", &next); 160 line = strtok_r(NULL, "\n", &next);
160 tep_register_print_string(pevent, printk, addr); 161 tep_register_print_string(pevent, printk, addr);
162 free(printk);
161 } 163 }
162} 164}
163 165
164void parse_saved_cmdline(struct tep_handle *pevent, 166void parse_saved_cmdline(struct tep_handle *pevent,
165 char *file, unsigned int size __maybe_unused) 167 char *file, unsigned int size __maybe_unused)
166{ 168{
167 char *comm; 169 char comm[17]; /* Max comm length in the kernel is 16. */
168 char *line; 170 char *line;
169 char *next = NULL; 171 char *next = NULL;
170 int pid; 172 int pid;
171 173
172 line = strtok_r(file, "\n", &next); 174 line = strtok_r(file, "\n", &next);
173 while (line) { 175 while (line) {
174 sscanf(line, "%d %ms", &pid, &comm); 176 if (sscanf(line, "%d %16s", &pid, comm) == 2)
175 tep_register_comm(pevent, comm, pid); 177 tep_register_comm(pevent, comm, pid);
176 free(comm);
177 line = strtok_r(NULL, "\n", &next); 178 line = strtok_r(NULL, "\n", &next);
178 } 179 }
179} 180}
@@ -189,29 +190,33 @@ int parse_event_file(struct tep_handle *pevent,
189 return tep_parse_event(pevent, buf, size, sys); 190 return tep_parse_event(pevent, buf, size, sys);
190} 191}
191 192
192struct event_format *trace_find_next_event(struct tep_handle *pevent, 193struct tep_event_format *trace_find_next_event(struct tep_handle *pevent,
193 struct event_format *event) 194 struct tep_event_format *event)
194{ 195{
195 static int idx; 196 static int idx;
197 int events_count;
198 struct tep_event_format *all_events;
196 199
197 if (!pevent || !pevent->events) 200 all_events = tep_get_first_event(pevent);
201 events_count = tep_get_events_count(pevent);
202 if (!pevent || !all_events || events_count < 1)
198 return NULL; 203 return NULL;
199 204
200 if (!event) { 205 if (!event) {
201 idx = 0; 206 idx = 0;
202 return pevent->events[0]; 207 return all_events;
203 } 208 }
204 209
205 if (idx < pevent->nr_events && event == pevent->events[idx]) { 210 if (idx < events_count && event == (all_events + idx)) {
206 idx++; 211 idx++;
207 if (idx == pevent->nr_events) 212 if (idx == events_count)
208 return NULL; 213 return NULL;
209 return pevent->events[idx]; 214 return (all_events + idx);
210 } 215 }
211 216
212 for (idx = 1; idx < pevent->nr_events; idx++) { 217 for (idx = 1; idx < events_count; idx++) {
213 if (event == pevent->events[idx - 1]) 218 if (event == (all_events + (idx - 1)))
214 return pevent->events[idx]; 219 return (all_events + idx);
215 } 220 }
216 return NULL; 221 return NULL;
217} 222}
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 3dfc1db6b25b..76f12c705ef9 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -102,7 +102,7 @@ static unsigned int read4(struct tep_handle *pevent)
102 102
103 if (do_read(&data, 4) < 0) 103 if (do_read(&data, 4) < 0)
104 return 0; 104 return 0;
105 return __data2host4(pevent, data); 105 return __tep_data2host4(pevent, data);
106} 106}
107 107
108static unsigned long long read8(struct tep_handle *pevent) 108static unsigned long long read8(struct tep_handle *pevent)
@@ -111,7 +111,7 @@ static unsigned long long read8(struct tep_handle *pevent)
111 111
112 if (do_read(&data, 8) < 0) 112 if (do_read(&data, 8) < 0)
113 return 0; 113 return 0;
114 return __data2host8(pevent, data); 114 return __tep_data2host8(pevent, data);
115} 115}
116 116
117static char *read_string(void) 117static char *read_string(void)
@@ -241,7 +241,7 @@ static int read_header_files(struct tep_handle *pevent)
241 * The commit field in the page is of type long, 241 * The commit field in the page is of type long,
242 * use that instead, since it represents the kernel. 242 * use that instead, since it represents the kernel.
243 */ 243 */
244 tep_set_long_size(pevent, pevent->header_page_size_size); 244 tep_set_long_size(pevent, tep_get_header_page_size(pevent));
245 } 245 }
246 free(header_page); 246 free(header_page);
247 247
@@ -297,10 +297,8 @@ static int read_event_file(struct tep_handle *pevent, char *sys,
297 } 297 }
298 298
299 ret = do_read(buf, size); 299 ret = do_read(buf, size);
300 if (ret < 0) { 300 if (ret < 0)
301 free(buf);
302 goto out; 301 goto out;
303 }
304 302
305 ret = parse_event_file(pevent, buf, size, sys); 303 ret = parse_event_file(pevent, buf, size, sys);
306 if (ret < 0) 304 if (ret < 0)
@@ -349,9 +347,12 @@ static int read_event_files(struct tep_handle *pevent)
349 for (x=0; x < count; x++) { 347 for (x=0; x < count; x++) {
350 size = read8(pevent); 348 size = read8(pevent);
351 ret = read_event_file(pevent, sys, size); 349 ret = read_event_file(pevent, sys, size);
352 if (ret) 350 if (ret) {
351 free(sys);
353 return ret; 352 return ret;
353 }
354 } 354 }
355 free(sys);
355 } 356 }
356 return 0; 357 return 0;
357} 358}
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 58bb72f266f3..95664b2f771e 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -72,12 +72,12 @@ void trace_event__cleanup(struct trace_event *t)
72/* 72/*
73 * Returns pointer with encoded error via <linux/err.h> interface. 73 * Returns pointer with encoded error via <linux/err.h> interface.
74 */ 74 */
75static struct event_format* 75static struct tep_event_format*
76tp_format(const char *sys, const char *name) 76tp_format(const char *sys, const char *name)
77{ 77{
78 char *tp_dir = get_events_file(sys); 78 char *tp_dir = get_events_file(sys);
79 struct tep_handle *pevent = tevent.pevent; 79 struct tep_handle *pevent = tevent.pevent;
80 struct event_format *event = NULL; 80 struct tep_event_format *event = NULL;
81 char path[PATH_MAX]; 81 char path[PATH_MAX];
82 size_t size; 82 size_t size;
83 char *data; 83 char *data;
@@ -102,7 +102,7 @@ tp_format(const char *sys, const char *name)
102/* 102/*
103 * Returns pointer with encoded error via <linux/err.h> interface. 103 * Returns pointer with encoded error via <linux/err.h> interface.
104 */ 104 */
105struct event_format* 105struct tep_event_format*
106trace_event__tp_format(const char *sys, const char *name) 106trace_event__tp_format(const char *sys, const char *name)
107{ 107{
108 if (!tevent_initialized && trace_event__init2()) 108 if (!tevent_initialized && trace_event__init2())
@@ -111,7 +111,7 @@ trace_event__tp_format(const char *sys, const char *name)
111 return tp_format(sys, name); 111 return tp_format(sys, name);
112} 112}
113 113
114struct event_format *trace_event__tp_format_id(int id) 114struct tep_event_format *trace_event__tp_format_id(int id)
115{ 115{
116 if (!tevent_initialized && trace_event__init2()) 116 if (!tevent_initialized && trace_event__init2())
117 return ERR_PTR(-ENOMEM); 117 return ERR_PTR(-ENOMEM);
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 40204ec3a7a2..f024d73bfc40 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,6 +3,7 @@
3#define _PERF_UTIL_TRACE_EVENT_H 3#define _PERF_UTIL_TRACE_EVENT_H
4 4
5#include <traceevent/event-parse.h> 5#include <traceevent/event-parse.h>
6#include <traceevent/trace-seq.h>
6#include "parse-events.h" 7#include "parse-events.h"
7 8
8struct machine; 9struct machine;
@@ -10,28 +11,28 @@ struct perf_sample;
10union perf_event; 11union perf_event;
11struct perf_tool; 12struct perf_tool;
12struct thread; 13struct thread;
13struct plugin_list; 14struct tep_plugin_list;
14 15
15struct trace_event { 16struct trace_event {
16 struct tep_handle *pevent; 17 struct tep_handle *pevent;
17 struct plugin_list *plugin_list; 18 struct tep_plugin_list *plugin_list;
18}; 19};
19 20
20int trace_event__init(struct trace_event *t); 21int trace_event__init(struct trace_event *t);
21void trace_event__cleanup(struct trace_event *t); 22void trace_event__cleanup(struct trace_event *t);
22int trace_event__register_resolver(struct machine *machine, 23int trace_event__register_resolver(struct machine *machine,
23 tep_func_resolver_t *func); 24 tep_func_resolver_t *func);
24struct event_format* 25struct tep_event_format*
25trace_event__tp_format(const char *sys, const char *name); 26trace_event__tp_format(const char *sys, const char *name);
26 27
27struct event_format *trace_event__tp_format_id(int id); 28struct tep_event_format *trace_event__tp_format_id(int id);
28 29
29int bigendian(void); 30int bigendian(void);
30 31
31void event_format__fprintf(struct event_format *event, 32void event_format__fprintf(struct tep_event_format *event,
32 int cpu, void *data, int size, FILE *fp); 33 int cpu, void *data, int size, FILE *fp);
33 34
34void event_format__print(struct event_format *event, 35void event_format__print(struct tep_event_format *event,
35 int cpu, void *data, int size); 36 int cpu, void *data, int size);
36 37
37int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size); 38int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size);
@@ -39,7 +40,7 @@ int parse_event_file(struct tep_handle *pevent,
39 char *buf, unsigned long size, char *sys); 40 char *buf, unsigned long size, char *sys);
40 41
41unsigned long long 42unsigned long long
42raw_field_value(struct event_format *event, const char *name, void *data); 43raw_field_value(struct tep_event_format *event, const char *name, void *data);
43 44
44void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size); 45void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size);
45void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size); 46void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size);
@@ -47,9 +48,9 @@ void parse_saved_cmdline(struct tep_handle *pevent, char *file, unsigned int siz
47 48
48ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); 49ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
49 50
50struct event_format *trace_find_next_event(struct tep_handle *pevent, 51struct tep_event_format *trace_find_next_event(struct tep_handle *pevent,
51 struct event_format *event); 52 struct tep_event_format *event);
52unsigned long long read_size(struct event_format *event, void *ptr, int size); 53unsigned long long read_size(struct tep_event_format *event, void *ptr, int size);
53unsigned long long eval_flag(const char *flag); 54unsigned long long eval_flag(const char *flag);
54 55
55int read_tracing_data(int fd, struct list_head *pattrs); 56int read_tracing_data(int fd, struct list_head *pattrs);
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index eac5b858a371..093352e93d50 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -221,7 +221,7 @@ out:
221 return err; 221 return err;
222} 222}
223 223
224static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) 224int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
225{ 225{
226 void *ptr; 226 void *ptr;
227 loff_t pgoff; 227 loff_t pgoff;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index dc58254a2b69..14508ee7707a 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -6,6 +6,7 @@
6/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */ 6/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
7#define _DEFAULT_SOURCE 1 7#define _DEFAULT_SOURCE 1
8 8
9#include <fcntl.h>
9#include <stdbool.h> 10#include <stdbool.h>
10#include <stddef.h> 11#include <stddef.h>
11#include <stdlib.h> 12#include <stdlib.h>
@@ -35,6 +36,7 @@ bool lsdir_no_dot_filter(const char *name, struct dirent *d);
35int copyfile(const char *from, const char *to); 36int copyfile(const char *from, const char *to);
36int copyfile_mode(const char *from, const char *to, mode_t mode); 37int copyfile_mode(const char *from, const char *to, mode_t mode);
37int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi); 38int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
39int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size);
38 40
39ssize_t readn(int fd, void *buf, size_t n); 41ssize_t readn(int fd, void *buf, size_t n);
40ssize_t writen(int fd, const void *buf, size_t n); 42ssize_t writen(int fd, const void *buf, size_t n);