aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-26 14:25:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-26 14:25:21 -0400
commitd207ea8e74ff45be0838afa12bdd2492fa9dc8bc (patch)
tree97cfb3ed5c1bb42790e98e62b823526f61000b9f /tools/perf
parent2a8a2b7c49d6eb5f3348892c4676267376cfd40b (diff)
parent66e5db4a1ccc64f278653bc69dc406d184dc750a (diff)
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Thomas Gleixner: "Kernel: - Improve kallsyms coverage - Add x86 entry trampolines to kcore - Fix ARM SPE handling - Correct PPC event post processing Tools: - Make the build system more robust - Small fixes and enhancements all over the place - Update kernel ABI header copies - Preparatory work for converting libtraceevnt to a shared library - License cleanups" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (100 commits) tools arch: Update arch/x86/lib/memcpy_64.S copy used in 'perf bench mem memcpy' tools arch x86: Update tools's copy of cpufeatures.h perf python: Fix pyrf_evlist__read_on_cpu() interface perf mmap: Store real cpu number in 'struct perf_mmap' perf tools: Remove ext from struct kmod_path perf tools: Add gzip_is_compressed function perf tools: Add lzma_is_compressed function perf tools: Add is_compressed callback to compressions array perf tools: Move the temp file processing into decompress_kmodule perf tools: Use compression id in decompress_kmodule() perf tools: Store compression id into struct dso perf tools: Add compression id into 'struct kmod_path' perf tools: Make is_supported_compression() static perf tools: Make decompress_to_file() function static perf tools: Get rid of dso__needs_decompress() call in __open_dso() perf tools: Get rid of dso__needs_decompress() call in symbol__disassemble() perf tools: Get rid of dso__needs_decompress() call in read_object_code() tools lib traceevent: Change to SPDX License format perf llvm: Allow passing options to llc in addition to clang perf parser: Improve error message for PMU address filters ...
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-annotate.txt9
-rw-r--r--tools/perf/Documentation/perf-report.txt9
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/arch/arm64/util/arm-spe.c1
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c4
-rw-r--r--tools/perf/arch/s390/util/auxtrace.c1
-rw-r--r--tools/perf/arch/x86/Makefile3
-rw-r--r--tools/perf/builtin-annotate.c4
-rw-r--r--tools/perf/builtin-kmem.c6
-rw-r--r--tools/perf/builtin-report.c9
-rw-r--r--tools/perf/builtin-script.c6
-rw-r--r--tools/perf/builtin-trace.c191
-rwxr-xr-xtools/perf/check-headers.sh17
-rw-r--r--tools/perf/examples/bpf/augmented_syscalls.c55
-rw-r--r--tools/perf/examples/bpf/hello.c9
-rw-r--r--tools/perf/examples/bpf/sys_enter_openat.c33
-rw-r--r--tools/perf/include/bpf/bpf.h20
-rw-r--r--tools/perf/include/bpf/stdio.h19
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json32
-rw-r--r--tools/perf/pmu-events/arch/arm64/mapfile.csv1
-rw-r--r--tools/perf/tests/bitmap.c2
-rw-r--r--tools/perf/tests/code-reading.c4
-rw-r--r--tools/perf/tests/kmod-path.c136
-rw-r--r--tools/perf/tests/mem2node.c2
-rw-r--r--tools/perf/ui/browsers/annotate.c76
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c305
-rw-r--r--tools/perf/util/annotate.h54
-rw-r--r--tools/perf/util/auxtrace.c6
-rw-r--r--tools/perf/util/auxtrace.h1
-rw-r--r--tools/perf/util/bpf-loader.c48
-rw-r--r--tools/perf/util/bpf-loader.h23
-rw-r--r--tools/perf/util/compress.h2
-rw-r--r--tools/perf/util/data-convert-bt.c6
-rw-r--r--tools/perf/util/dso.c111
-rw-r--r--tools/perf/util/dso.h13
-rw-r--r--tools/perf/util/event.c13
-rw-r--r--tools/perf/util/evlist.c2
-rw-r--r--tools/perf/util/evsel.c2
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/header.c9
-rw-r--r--tools/perf/util/llvm-utils.c31
-rw-r--r--tools/perf/util/llvm-utils.h9
-rw-r--r--tools/perf/util/lzma.c20
-rw-r--r--tools/perf/util/machine.c4
-rw-r--r--tools/perf/util/machine.h2
-rw-r--r--tools/perf/util/map.c44
-rw-r--r--tools/perf/util/map.h1
-rw-r--r--tools/perf/util/mmap.c3
-rw-r--r--tools/perf/util/mmap.h3
-rw-r--r--tools/perf/util/namespaces.c3
-rw-r--r--tools/perf/util/parse-events.c20
-rw-r--r--tools/perf/util/python.c30
-rw-r--r--tools/perf/util/s390-cpumsf-kernel.h71
-rw-r--r--tools/perf/util/s390-cpumsf.c945
-rw-r--r--tools/perf/util/s390-cpumsf.h21
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c6
-rw-r--r--tools/perf/util/setup.py10
-rw-r--r--tools/perf/util/sort.c16
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/trace-event-parse.c34
-rw-r--r--tools/perf/util/trace-event-read.c44
-rw-r--r--tools/perf/util/trace-event-scripting.c4
-rw-r--r--tools/perf/util/trace-event.c28
-rw-r--r--tools/perf/util/trace-event.h20
-rw-r--r--tools/perf/util/zlib.c18
67 files changed, 2152 insertions, 495 deletions
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 749cc6055dac..e8c972f89357 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -118,6 +118,15 @@ OPTIONS
118--group:: 118--group::
119 Show event group information together 119 Show event group information together
120 120
121--percent-type::
122 Set annotation percent type from following choices:
123 global-period, local-period, global-hits, local-hits
124
125 The local/global keywords set if the percentage is computed
126 in the scope of the function (local) or the whole data (global).
127 The period/hits keywords set the base the percentage is computed
128 on - the samples period or the number of samples (hits).
129
121SEE ALSO 130SEE ALSO
122-------- 131--------
123linkperf:perf-record[1], linkperf:perf-report[1] 132linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 917e36fde6d8..474a4941f65d 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -477,6 +477,15 @@ include::itrace.txt[]
477 Display monitored tasks stored in perf data. Displaying pid/tid/ppid 477 Display monitored tasks stored in perf data. Displaying pid/tid/ppid
478 plus the command string aligned to distinguish parent and child tasks. 478 plus the command string aligned to distinguish parent and child tasks.
479 479
480--percent-type::
481 Set annotation percent type from following choices:
482 global-period, local-period, global-hits, local-hits
483
484 The local/global keywords set if the percentage is computed
485 in the scope of the function (local) or the whole data (global).
486 The period/hits keywords set the base the percentage is computed
487 on - the samples period or the number of samples (hits).
488
480include::callchain-overhead-calculation.txt[] 489include::callchain-overhead-calculation.txt[]
481 490
482SEE ALSO 491SEE ALSO
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 225454416ed5..7902a5681fc8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -84,10 +84,10 @@ endif # has_clean
84endif # MAKECMDGOALS 84endif # MAKECMDGOALS
85 85
86# 86#
87# The clean target is not really parallel, don't print the jobs info: 87# Explicitly disable parallelism for the clean target.
88# 88#
89clean: 89clean:
90 $(make) 90 $(make) -j1
91 91
92# 92#
93# The build-test target is not really parallel, don't print the jobs info, 93# The build-test target is not really parallel, don't print the jobs info,
diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c
index 1120e39c1b00..5ccfce87e693 100644
--- a/tools/perf/arch/arm64/util/arm-spe.c
+++ b/tools/perf/arch/arm64/util/arm-spe.c
@@ -194,6 +194,7 @@ struct auxtrace_record *arm_spe_recording_init(int *err,
194 sper->itr.read_finish = arm_spe_read_finish; 194 sper->itr.read_finish = arm_spe_read_finish;
195 sper->itr.alignment = 0; 195 sper->itr.alignment = 0;
196 196
197 *err = 0;
197 return &sper->itr; 198 return &sper->itr;
198} 199}
199 200
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index 53d83d7e6a09..20e7d74d86cd 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -141,8 +141,10 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
141 for (i = 0; i < ntevs; i++) { 141 for (i = 0; i < ntevs; i++) {
142 tev = &pev->tevs[i]; 142 tev = &pev->tevs[i];
143 map__for_each_symbol(map, sym, tmp) { 143 map__for_each_symbol(map, sym, tmp) {
144 if (map->unmap_ip(map, sym->start) == tev->point.address) 144 if (map->unmap_ip(map, sym->start) == tev->point.address) {
145 arch__fix_tev_from_maps(pev, tev, map, sym); 145 arch__fix_tev_from_maps(pev, tev, map, sym);
146 break;
147 }
146 } 148 }
147 } 149 }
148} 150}
diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c
index 3afe8256eff2..44c857388897 100644
--- a/tools/perf/arch/s390/util/auxtrace.c
+++ b/tools/perf/arch/s390/util/auxtrace.c
@@ -30,6 +30,7 @@ cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused,
30 struct auxtrace_info_event *auxtrace_info __maybe_unused, 30 struct auxtrace_info_event *auxtrace_info __maybe_unused,
31 size_t priv_size __maybe_unused) 31 size_t priv_size __maybe_unused)
32{ 32{
33 auxtrace_info->type = PERF_AUXTRACE_S390_CPUMSF;
33 return 0; 34 return 0;
34} 35}
35 36
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 1a38e78117ce..8cc6642fce7a 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -19,9 +19,6 @@ systbl := $(sys)/syscalltbl.sh
19_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)') 19_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
20 20
21$(header): $(sys)/syscall_64.tbl $(systbl) 21$(header): $(sys)/syscall_64.tbl $(systbl)
22 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
23 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
24 || echo "Warning: Kernel ABI header at 'tools/perf/arch/x86/entry/syscalls/syscall_64.tbl' differs from latest version at 'arch/x86/entry/syscalls/syscall_64.tbl'" >&2 )) || true
25 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@ 22 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
26 23
27clean:: 24clean::
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 8180319285af..830481b8db26 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -542,6 +542,10 @@ int cmd_annotate(int argc, const char **argv)
542 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode", 542 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
543 "'always' (default), 'never' or 'auto' only applicable to --stdio mode", 543 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
544 stdio__config_color, "always"), 544 stdio__config_color, "always"),
545 OPT_CALLBACK(0, "percent-type", &annotate.opts, "local-period",
546 "Set percent type local/global-period/hits",
547 annotate_parse_percent_type),
548
545 OPT_END() 549 OPT_END()
546 }; 550 };
547 int ret; 551 int ret;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 54d3f21b0e62..b63bca4b0c2a 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -729,7 +729,7 @@ static char *compact_gfp_string(unsigned long gfp_flags)
729static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample, 729static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
730 unsigned int gfp_flags) 730 unsigned int gfp_flags)
731{ 731{
732 struct pevent_record record = { 732 struct tep_record record = {
733 .cpu = sample->cpu, 733 .cpu = sample->cpu,
734 .data = sample->raw_data, 734 .data = sample->raw_data,
735 .size = sample->raw_size, 735 .size = sample->raw_size,
@@ -747,7 +747,7 @@ static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
747 } 747 }
748 748
749 trace_seq_init(&seq); 749 trace_seq_init(&seq);
750 pevent_event_info(&seq, evsel->tp_format, &record); 750 tep_event_info(&seq, evsel->tp_format, &record);
751 751
752 str = strtok_r(seq.buffer, " ", &pos); 752 str = strtok_r(seq.buffer, " ", &pos);
753 while (str) { 753 while (str) {
@@ -1974,7 +1974,7 @@ int cmd_kmem(int argc, const char **argv)
1974 goto out_delete; 1974 goto out_delete;
1975 } 1975 }
1976 1976
1977 kmem_page_size = pevent_get_page_size(evsel->tp_format->pevent); 1977 kmem_page_size = tep_get_page_size(evsel->tp_format->pevent);
1978 symbol_conf.use_callchain = true; 1978 symbol_conf.use_callchain = true;
1979 } 1979 }
1980 1980
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 02f7a3c27761..76e12bcd1765 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1124,6 +1124,9 @@ int cmd_report(int argc, const char **argv)
1124 "Time span of interest (start,stop)"), 1124 "Time span of interest (start,stop)"),
1125 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name, 1125 OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
1126 "Show inline function"), 1126 "Show inline function"),
1127 OPT_CALLBACK(0, "percent-type", &report.annotation_opts, "local-period",
1128 "Set percent type local/global-period/hits",
1129 annotate_parse_percent_type),
1127 OPT_END() 1130 OPT_END()
1128 }; 1131 };
1129 struct perf_data data = { 1132 struct perf_data data = {
@@ -1366,9 +1369,9 @@ repeat:
1366 } 1369 }
1367 1370
1368 if (session->tevent.pevent && 1371 if (session->tevent.pevent &&
1369 pevent_set_function_resolver(session->tevent.pevent, 1372 tep_set_function_resolver(session->tevent.pevent,
1370 machine__resolve_kernel_addr, 1373 machine__resolve_kernel_addr,
1371 &session->machines.host) < 0) { 1374 &session->machines.host) < 0) {
1372 pr_err("%s: failed to set libtraceevent function resolver\n", 1375 pr_err("%s: failed to set libtraceevent function resolver\n",
1373 __func__); 1376 __func__);
1374 return -1; 1377 return -1;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 568ddfac3213..ba481d73f910 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -3429,9 +3429,9 @@ int cmd_script(int argc, const char **argv)
3429 symbol_conf.use_callchain = false; 3429 symbol_conf.use_callchain = false;
3430 3430
3431 if (session->tevent.pevent && 3431 if (session->tevent.pevent &&
3432 pevent_set_function_resolver(session->tevent.pevent, 3432 tep_set_function_resolver(session->tevent.pevent,
3433 machine__resolve_kernel_addr, 3433 machine__resolve_kernel_addr,
3434 &session->machines.host) < 0) { 3434 &session->machines.host) < 0) {
3435 pr_err("%s: failed to set libtraceevent function resolver\n", __func__); 3435 pr_err("%s: failed to set libtraceevent function resolver\n", __func__);
3436 err = -1; 3436 err = -1;
3437 goto out_delete; 3437 goto out_delete;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 88561eed7950..22ab8e67c760 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -77,7 +77,8 @@ struct trace {
77 struct syscall *table; 77 struct syscall *table;
78 struct { 78 struct {
79 struct perf_evsel *sys_enter, 79 struct perf_evsel *sys_enter,
80 *sys_exit; 80 *sys_exit,
81 *augmented;
81 } events; 82 } events;
82 } syscalls; 83 } syscalls;
83 struct record_opts opts; 84 struct record_opts opts;
@@ -121,7 +122,6 @@ struct trace {
121 bool force; 122 bool force;
122 bool vfs_getname; 123 bool vfs_getname;
123 int trace_pgfaults; 124 int trace_pgfaults;
124 int open_id;
125}; 125};
126 126
127struct tp_field { 127struct tp_field {
@@ -157,13 +157,11 @@ TP_UINT_FIELD__SWAPPED(16);
157TP_UINT_FIELD__SWAPPED(32); 157TP_UINT_FIELD__SWAPPED(32);
158TP_UINT_FIELD__SWAPPED(64); 158TP_UINT_FIELD__SWAPPED(64);
159 159
160static int tp_field__init_uint(struct tp_field *field, 160static int __tp_field__init_uint(struct tp_field *field, int size, int offset, bool needs_swap)
161 struct format_field *format_field,
162 bool needs_swap)
163{ 161{
164 field->offset = format_field->offset; 162 field->offset = offset;
165 163
166 switch (format_field->size) { 164 switch (size) {
167 case 1: 165 case 1:
168 field->integer = tp_field__u8; 166 field->integer = tp_field__u8;
169 break; 167 break;
@@ -183,18 +181,28 @@ static int tp_field__init_uint(struct tp_field *field,
183 return 0; 181 return 0;
184} 182}
185 183
184static int tp_field__init_uint(struct tp_field *field, struct format_field *format_field, bool needs_swap)
185{
186 return __tp_field__init_uint(field, format_field->size, format_field->offset, needs_swap);
187}
188
186static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample) 189static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
187{ 190{
188 return sample->raw_data + field->offset; 191 return sample->raw_data + field->offset;
189} 192}
190 193
191static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field) 194static int __tp_field__init_ptr(struct tp_field *field, int offset)
192{ 195{
193 field->offset = format_field->offset; 196 field->offset = offset;
194 field->pointer = tp_field__ptr; 197 field->pointer = tp_field__ptr;
195 return 0; 198 return 0;
196} 199}
197 200
201static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
202{
203 return __tp_field__init_ptr(field, format_field->offset);
204}
205
198struct syscall_tp { 206struct syscall_tp {
199 struct tp_field id; 207 struct tp_field id;
200 union { 208 union {
@@ -240,7 +248,47 @@ static void perf_evsel__delete_priv(struct perf_evsel *evsel)
240 perf_evsel__delete(evsel); 248 perf_evsel__delete(evsel);
241} 249}
242 250
243static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler) 251static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel)
252{
253 struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp));
254
255 if (evsel->priv != NULL) {
256 if (perf_evsel__init_tp_uint_field(evsel, &sc->id, "__syscall_nr"))
257 goto out_delete;
258 return 0;
259 }
260
261 return -ENOMEM;
262out_delete:
263 zfree(&evsel->priv);
264 return -ENOENT;
265}
266
267static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel)
268{
269 struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp));
270
271 if (evsel->priv != NULL) { /* field, sizeof_field, offsetof_field */
272 if (__tp_field__init_uint(&sc->id, sizeof(long), sizeof(long long), evsel->needs_swap))
273 goto out_delete;
274
275 return 0;
276 }
277
278 return -ENOMEM;
279out_delete:
280 zfree(&evsel->priv);
281 return -EINVAL;
282}
283
284static int perf_evsel__init_augmented_syscall_tp_args(struct perf_evsel *evsel)
285{
286 struct syscall_tp *sc = evsel->priv;
287
288 return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64));
289}
290
291static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler)
244{ 292{
245 evsel->priv = malloc(sizeof(struct syscall_tp)); 293 evsel->priv = malloc(sizeof(struct syscall_tp));
246 if (evsel->priv != NULL) { 294 if (evsel->priv != NULL) {
@@ -258,7 +306,7 @@ out_delete:
258 return -ENOENT; 306 return -ENOENT;
259} 307}
260 308
261static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler) 309static struct perf_evsel *perf_evsel__raw_syscall_newtp(const char *direction, void *handler)
262{ 310{
263 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); 311 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
264 312
@@ -269,7 +317,7 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
269 if (IS_ERR(evsel)) 317 if (IS_ERR(evsel))
270 return NULL; 318 return NULL;
271 319
272 if (perf_evsel__init_syscall_tp(evsel, handler)) 320 if (perf_evsel__init_raw_syscall_tp(evsel, handler))
273 goto out_delete; 321 goto out_delete;
274 322
275 return evsel; 323 return evsel;
@@ -805,12 +853,17 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
805 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp); 853 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
806} 854}
807 855
856/*
857 * 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.
859 */
808struct syscall { 860struct syscall {
809 struct event_format *tp_format; 861 struct event_format *tp_format;
810 int nr_args; 862 int nr_args;
863 bool is_exit;
864 bool is_open;
811 struct format_field *args; 865 struct format_field *args;
812 const char *name; 866 const char *name;
813 bool is_exit;
814 struct syscall_fmt *fmt; 867 struct syscall_fmt *fmt;
815 struct syscall_arg_fmt *arg_fmt; 868 struct syscall_arg_fmt *arg_fmt;
816}; 869};
@@ -1299,6 +1352,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1299 } 1352 }
1300 1353
1301 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit"); 1354 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1355 sc->is_open = !strcmp(name, "open") || !strcmp(name, "openat");
1302 1356
1303 return syscall__set_arg_fmts(sc); 1357 return syscall__set_arg_fmts(sc);
1304} 1358}
@@ -1661,6 +1715,37 @@ out_put:
1661 return err; 1715 return err;
1662} 1716}
1663 1717
1718static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evsel,
1719 struct perf_sample *sample)
1720{
1721 struct thread_trace *ttrace;
1722 struct thread *thread;
1723 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
1724 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1725 char msg[1024];
1726 void *args;
1727
1728 if (sc == NULL)
1729 return -1;
1730
1731 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1732 ttrace = thread__trace(thread, trace->output);
1733 /*
1734 * We need to get ttrace just to make sure it is there when syscall__scnprintf_args()
1735 * and the rest of the beautifiers accessing it via struct syscall_arg touches it.
1736 */
1737 if (ttrace == NULL)
1738 goto out_put;
1739
1740 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
1741 syscall__scnprintf_args(sc, msg, sizeof(msg), args, trace, thread);
1742 fprintf(trace->output, "%s", msg);
1743 err = 0;
1744out_put:
1745 thread__put(thread);
1746 return err;
1747}
1748
1664static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel, 1749static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1665 struct perf_sample *sample, 1750 struct perf_sample *sample,
1666 struct callchain_cursor *cursor) 1751 struct callchain_cursor *cursor)
@@ -1722,7 +1807,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1722 1807
1723 ret = perf_evsel__sc_tp_uint(evsel, ret, sample); 1808 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
1724 1809
1725 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) { 1810 if (sc->is_open && ret >= 0 && ttrace->filename.pending_open) {
1726 trace__set_fd_pathname(thread, ret, ttrace->filename.name); 1811 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
1727 ttrace->filename.pending_open = false; 1812 ttrace->filename.pending_open = false;
1728 ++trace->stats.vfs_getname; 1813 ++trace->stats.vfs_getname;
@@ -1957,11 +2042,17 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1957 fprintf(trace->output, "%s:", evsel->name); 2042 fprintf(trace->output, "%s:", evsel->name);
1958 2043
1959 if (perf_evsel__is_bpf_output(evsel)) { 2044 if (perf_evsel__is_bpf_output(evsel)) {
1960 bpf_output__fprintf(trace, sample); 2045 if (evsel == trace->syscalls.events.augmented)
2046 trace__fprintf_sys_enter(trace, evsel, sample);
2047 else
2048 bpf_output__fprintf(trace, sample);
1961 } else if (evsel->tp_format) { 2049 } else if (evsel->tp_format) {
1962 event_format__fprintf(evsel->tp_format, sample->cpu, 2050 if (strncmp(evsel->tp_format->name, "sys_enter_", 10) ||
1963 sample->raw_data, sample->raw_size, 2051 trace__fprintf_sys_enter(trace, evsel, sample)) {
1964 trace->output); 2052 event_format__fprintf(evsel->tp_format, sample->cpu,
2053 sample->raw_data, sample->raw_size,
2054 trace->output);
2055 }
1965 } 2056 }
1966 2057
1967 fprintf(trace->output, "\n"); 2058 fprintf(trace->output, "\n");
@@ -2242,14 +2333,14 @@ static int trace__add_syscall_newtp(struct trace *trace)
2242 struct perf_evlist *evlist = trace->evlist; 2333 struct perf_evlist *evlist = trace->evlist;
2243 struct perf_evsel *sys_enter, *sys_exit; 2334 struct perf_evsel *sys_enter, *sys_exit;
2244 2335
2245 sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter); 2336 sys_enter = perf_evsel__raw_syscall_newtp("sys_enter", trace__sys_enter);
2246 if (sys_enter == NULL) 2337 if (sys_enter == NULL)
2247 goto out; 2338 goto out;
2248 2339
2249 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args)) 2340 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
2250 goto out_delete_sys_enter; 2341 goto out_delete_sys_enter;
2251 2342
2252 sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit); 2343 sys_exit = perf_evsel__raw_syscall_newtp("sys_exit", trace__sys_exit);
2253 if (sys_exit == NULL) 2344 if (sys_exit == NULL)
2254 goto out_delete_sys_enter; 2345 goto out_delete_sys_enter;
2255 2346
@@ -2671,7 +2762,7 @@ static int trace__replay(struct trace *trace)
2671 "syscalls:sys_enter"); 2762 "syscalls:sys_enter");
2672 2763
2673 if (evsel && 2764 if (evsel &&
2674 (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 || 2765 (perf_evsel__init_raw_syscall_tp(evsel, trace__sys_enter) < 0 ||
2675 perf_evsel__init_sc_tp_ptr_field(evsel, args))) { 2766 perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
2676 pr_err("Error during initialize raw_syscalls:sys_enter event\n"); 2767 pr_err("Error during initialize raw_syscalls:sys_enter event\n");
2677 goto out; 2768 goto out;
@@ -2683,7 +2774,7 @@ static int trace__replay(struct trace *trace)
2683 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, 2774 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2684 "syscalls:sys_exit"); 2775 "syscalls:sys_exit");
2685 if (evsel && 2776 if (evsel &&
2686 (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 || 2777 (perf_evsel__init_raw_syscall_tp(evsel, trace__sys_exit) < 0 ||
2687 perf_evsel__init_sc_tp_uint_field(evsel, ret))) { 2778 perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
2688 pr_err("Error during initialize raw_syscalls:sys_exit event\n"); 2779 pr_err("Error during initialize raw_syscalls:sys_exit event\n");
2689 goto out; 2780 goto out;
@@ -2923,6 +3014,36 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2923 evsel->handler = handler; 3014 evsel->handler = handler;
2924} 3015}
2925 3016
3017static int evlist__set_syscall_tp_fields(struct perf_evlist *evlist)
3018{
3019 struct perf_evsel *evsel;
3020
3021 evlist__for_each_entry(evlist, evsel) {
3022 if (evsel->priv || !evsel->tp_format)
3023 continue;
3024
3025 if (strcmp(evsel->tp_format->system, "syscalls"))
3026 continue;
3027
3028 if (perf_evsel__init_syscall_tp(evsel))
3029 return -1;
3030
3031 if (!strncmp(evsel->tp_format->name, "sys_enter_", 10)) {
3032 struct syscall_tp *sc = evsel->priv;
3033
3034 if (__tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64)))
3035 return -1;
3036 } else if (!strncmp(evsel->tp_format->name, "sys_exit_", 9)) {
3037 struct syscall_tp *sc = evsel->priv;
3038
3039 if (__tp_field__init_uint(&sc->ret, sizeof(u64), sc->id.offset + sizeof(u64), evsel->needs_swap))
3040 return -1;
3041 }
3042 }
3043
3044 return 0;
3045}
3046
2926/* 3047/*
2927 * XXX: Hackish, just splitting the combined -e+--event (syscalls 3048 * XXX: Hackish, just splitting the combined -e+--event (syscalls
2928 * (raw_syscalls:{sys_{enter,exit}} + events (tracepoints, HW, SW, etc) to use 3049 * (raw_syscalls:{sys_{enter,exit}} + events (tracepoints, HW, SW, etc) to use
@@ -3123,8 +3244,9 @@ int cmd_trace(int argc, const char **argv)
3123 }; 3244 };
3124 bool __maybe_unused max_stack_user_set = true; 3245 bool __maybe_unused max_stack_user_set = true;
3125 bool mmap_pages_user_set = true; 3246 bool mmap_pages_user_set = true;
3247 struct perf_evsel *evsel;
3126 const char * const trace_subcommands[] = { "record", NULL }; 3248 const char * const trace_subcommands[] = { "record", NULL };
3127 int err; 3249 int err = -1;
3128 char bf[BUFSIZ]; 3250 char bf[BUFSIZ];
3129 3251
3130 signal(SIGSEGV, sighandler_dump_stack); 3252 signal(SIGSEGV, sighandler_dump_stack);
@@ -3147,6 +3269,20 @@ int cmd_trace(int argc, const char **argv)
3147 "cgroup monitoring only available in system-wide mode"); 3269 "cgroup monitoring only available in system-wide mode");
3148 } 3270 }
3149 3271
3272 evsel = bpf__setup_output_event(trace.evlist, "__augmented_syscalls__");
3273 if (IS_ERR(evsel)) {
3274 bpf__strerror_setup_output_event(trace.evlist, PTR_ERR(evsel), bf, sizeof(bf));
3275 pr_err("ERROR: Setup trace syscalls enter failed: %s\n", bf);
3276 goto out;
3277 }
3278
3279 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;
3284 }
3285
3150 err = bpf__setup_stdout(trace.evlist); 3286 err = bpf__setup_stdout(trace.evlist);
3151 if (err) { 3287 if (err) {
3152 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf)); 3288 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
@@ -3182,8 +3318,13 @@ int cmd_trace(int argc, const char **argv)
3182 symbol_conf.use_callchain = true; 3318 symbol_conf.use_callchain = true;
3183 } 3319 }
3184 3320
3185 if (trace.evlist->nr_entries > 0) 3321 if (trace.evlist->nr_entries > 0) {
3186 evlist__set_evsel_handler(trace.evlist, trace__event_handler); 3322 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3323 if (evlist__set_syscall_tp_fields(trace.evlist)) {
3324 perror("failed to set syscalls:* tracepoint fields");
3325 goto out;
3326 }
3327 }
3187 3328
3188 if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) 3329 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3189 return trace__record(&trace, argc-1, &argv[1]); 3330 return trace__record(&trace, argc-1, &argv[1]);
@@ -3205,8 +3346,6 @@ int cmd_trace(int argc, const char **argv)
3205 } 3346 }
3206 } 3347 }
3207 3348
3208 trace.open_id = syscalltbl__id(trace.sctbl, "open");
3209
3210 err = target__validate(&trace.opts.target); 3349 err = target__validate(&trace.opts.target);
3211 if (err) { 3350 if (err) {
3212 target__strerror(&trace.opts.target, err, bf, sizeof(bf)); 3351 target__strerror(&trace.opts.target, err, bf, sizeof(bf));
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index de28466c0186..466540ee8ea7 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -67,8 +67,12 @@ check_2 () {
67 67
68 cmd="diff $* $file1 $file2 > /dev/null" 68 cmd="diff $* $file1 $file2 > /dev/null"
69 69
70 test -f $file2 && 70 test -f $file2 && {
71 eval $cmd || echo "Warning: Kernel ABI header at 'tools/$file' differs from latest version at '$file'" >&2 71 eval $cmd || {
72 echo "Warning: Kernel ABI header at '$file1' differs from latest version at '$file2'" >&2
73 echo diff -u $file1 $file2
74 }
75 }
72} 76}
73 77
74check () { 78check () {
@@ -76,7 +80,7 @@ check () {
76 80
77 shift 81 shift
78 82
79 check_2 ../$file ../../$file $* 83 check_2 tools/$file $file $*
80} 84}
81 85
82# Check if we have the kernel headers (tools/perf/../../include), else 86# Check if we have the kernel headers (tools/perf/../../include), else
@@ -84,6 +88,8 @@ check () {
84# differences. 88# differences.
85test -d ../../include || exit 0 89test -d ../../include || exit 0
86 90
91cd ../..
92
87# simple diff check 93# simple diff check
88for i in $HEADERS; do 94for i in $HEADERS; do
89 check $i -B 95 check $i -B
@@ -94,3 +100,8 @@ check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/ex
94check arch/x86/lib/memset_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"' 100check arch/x86/lib/memset_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
95check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common.h>"' 101check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common.h>"'
96check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"' 102check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"'
103
104# diff non-symmetric files
105check_2 tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl
106
107cd tools/perf
diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c
new file mode 100644
index 000000000000..69a31386d8cd
--- /dev/null
+++ b/tools/perf/examples/bpf/augmented_syscalls.c
@@ -0,0 +1,55 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Augment the openat syscall with the contents of the filename pointer argument.
4 *
5 * Test it with:
6 *
7 * perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null
8 *
9 * It'll catch some openat syscalls related to the dynamic linked and
10 * the last one should be the one for '/etc/passwd'.
11 *
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,
14 * which will be done as that feature is implemented in the next csets, for now
15 * it will appear in a dump done by the default tracepoint handler in 'perf trace',
16 * that uses bpf_output__fprintf() to just dump those contents, as done with
17 * the bpf-output event associated with the __bpf_output__ map declared in
18 * tools/perf/include/bpf/stdio.h.
19 */
20
21#include <stdio.h>
22
23struct bpf_map SEC("maps") __augmented_syscalls__ = {
24 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
25 .key_size = sizeof(int),
26 .value_size = sizeof(u32),
27 .max_entries = __NR_CPUS__,
28};
29
30struct syscall_enter_openat_args {
31 unsigned long long common_tp_fields;
32 long syscall_nr;
33 long dfd;
34 char *filename_ptr;
35 long flags;
36 long mode;
37};
38
39struct augmented_enter_openat_args {
40 struct syscall_enter_openat_args args;
41 char filename[64];
42};
43
44int syscall_enter(openat)(struct syscall_enter_openat_args *args)
45{
46 struct augmented_enter_openat_args augmented_args;
47
48 probe_read(&augmented_args.args, sizeof(augmented_args.args), args);
49 probe_read_str(&augmented_args.filename, sizeof(augmented_args.filename), args->filename_ptr);
50 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,
51 &augmented_args, sizeof(augmented_args));
52 return 1;
53}
54
55license(GPL);
diff --git a/tools/perf/examples/bpf/hello.c b/tools/perf/examples/bpf/hello.c
new file mode 100644
index 000000000000..cf3c2fdc7f79
--- /dev/null
+++ b/tools/perf/examples/bpf/hello.c
@@ -0,0 +1,9 @@
1#include <stdio.h>
2
3int syscall_enter(openat)(void *args)
4{
5 puts("Hello, world\n");
6 return 0;
7}
8
9license(GPL);
diff --git a/tools/perf/examples/bpf/sys_enter_openat.c b/tools/perf/examples/bpf/sys_enter_openat.c
new file mode 100644
index 000000000000..9cd124b09392
--- /dev/null
+++ b/tools/perf/examples/bpf/sys_enter_openat.c
@@ -0,0 +1,33 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Hook into 'openat' syscall entry tracepoint
4 *
5 * Test it with:
6 *
7 * perf trace -e tools/perf/examples/bpf/sys_enter_openat.c cat /etc/passwd > /dev/null
8 *
9 * It'll catch some openat syscalls related to the dynamic linked and
10 * the last one should be the one for '/etc/passwd'.
11 *
12 * The syscall_enter_openat_args can be used to get the syscall fields
13 * and use them for filtering calls, i.e. use in expressions for
14 * the return value.
15 */
16
17#include <bpf.h>
18
19struct syscall_enter_openat_args {
20 unsigned long long unused;
21 long syscall_nr;
22 long dfd;
23 char *filename_ptr;
24 long flags;
25 long mode;
26};
27
28int syscall_enter(openat)(struct syscall_enter_openat_args *args)
29{
30 return 1;
31}
32
33license(GPL);
diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h
index a63aa6241b7f..47897d65e799 100644
--- a/tools/perf/include/bpf/bpf.h
+++ b/tools/perf/include/bpf/bpf.h
@@ -4,13 +4,33 @@
4 4
5#include <uapi/linux/bpf.h> 5#include <uapi/linux/bpf.h>
6 6
7/*
8 * A helper structure used by eBPF C program to describe map attributes to
9 * elf_bpf loader, taken from tools/testing/selftests/bpf/bpf_helpers.h:
10 */
11struct bpf_map {
12 unsigned int type;
13 unsigned int key_size;
14 unsigned int value_size;
15 unsigned int max_entries;
16 unsigned int map_flags;
17 unsigned int inner_map_idx;
18 unsigned int numa_node;
19};
20
7#define SEC(NAME) __attribute__((section(NAME), used)) 21#define SEC(NAME) __attribute__((section(NAME), used))
8 22
9#define probe(function, vars) \ 23#define probe(function, vars) \
10 SEC(#function "=" #function " " #vars) function 24 SEC(#function "=" #function " " #vars) function
11 25
26#define syscall_enter(name) \
27 SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name
28
12#define license(name) \ 29#define license(name) \
13char _license[] SEC("license") = #name; \ 30char _license[] SEC("license") = #name; \
14int _version SEC("version") = LINUX_VERSION_CODE; 31int _version SEC("version") = LINUX_VERSION_CODE;
15 32
33static int (*probe_read)(void *dst, int size, const void *unsafe_addr) = (void *)BPF_FUNC_probe_read;
34static int (*probe_read_str)(void *dst, int size, const void *unsafe_addr) = (void *)BPF_FUNC_probe_read_str;
35
16#endif /* _PERF_BPF_H */ 36#endif /* _PERF_BPF_H */
diff --git a/tools/perf/include/bpf/stdio.h b/tools/perf/include/bpf/stdio.h
new file mode 100644
index 000000000000..2899cb7bfed8
--- /dev/null
+++ b/tools/perf/include/bpf/stdio.h
@@ -0,0 +1,19 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#include <bpf.h>
4
5struct bpf_map SEC("maps") __bpf_stdout__ = {
6 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
7 .key_size = sizeof(int),
8 .value_size = sizeof(u32),
9 .max_entries = __NR_CPUS__,
10};
11
12static int (*perf_event_output)(void *, struct bpf_map *, int, void *, unsigned long) =
13 (void *)BPF_FUNC_perf_event_output;
14
15#define puts(from) \
16 ({ const int __len = sizeof(from); \
17 char __from[__len] = from; \
18 perf_event_output(args, &__bpf_stdout__, BPF_F_CURRENT_CPU, \
19 &__from, __len & (sizeof(from) - 1)); })
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
new file mode 100644
index 000000000000..bc03c06c3918
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json
@@ -0,0 +1,32 @@
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/mapfile.csv b/tools/perf/pmu-events/arch/arm64/mapfile.csv
index f03e26ecb658..59cd8604b0bd 100644
--- a/tools/perf/pmu-events/arch/arm64/mapfile.csv
+++ b/tools/perf/pmu-events/arch/arm64/mapfile.csv
@@ -16,3 +16,4 @@
160x00000000420f5160,v1,cavium/thunderx2,core 160x00000000420f5160,v1,cavium/thunderx2,core
170x00000000430f0af0,v1,cavium/thunderx2,core 170x00000000430f0af0,v1,cavium/thunderx2,core
180x00000000480fd010,v1,hisilicon/hip08,core 180x00000000480fd010,v1,hisilicon/hip08,core
190x00000000500f0000,v1,ampere/emag,core
diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c
index 47bedf25ba69..96e7fc1ad3f9 100644
--- a/tools/perf/tests/bitmap.c
+++ b/tools/perf/tests/bitmap.c
@@ -16,8 +16,6 @@ static unsigned long *get_bitmap(const char *str, int nbits)
16 bm = bitmap_alloc(nbits); 16 bm = bitmap_alloc(nbits);
17 17
18 if (map && bm) { 18 if (map && bm) {
19 bitmap_zero(bm, nbits);
20
21 for (i = 0; i < map->nr; i++) 19 for (i = 0; i < map->nr; i++)
22 set_bit(map->map[i], bm); 20 set_bit(map->map[i], bm);
23 } 21 }
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 4892bd2dc33e..6b049f3f5cf4 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -232,6 +232,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
232 u64 objdump_addr; 232 u64 objdump_addr;
233 const char *objdump_name; 233 const char *objdump_name;
234 char decomp_name[KMOD_DECOMP_LEN]; 234 char decomp_name[KMOD_DECOMP_LEN];
235 bool decomp = false;
235 int ret; 236 int ret;
236 237
237 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 238 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
@@ -305,6 +306,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
305 return -1; 306 return -1;
306 } 307 }
307 308
309 decomp = true;
308 objdump_name = decomp_name; 310 objdump_name = decomp_name;
309 } 311 }
310 312
@@ -312,7 +314,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
312 objdump_addr = map__rip_2objdump(al.map, al.addr); 314 objdump_addr = map__rip_2objdump(al.map, al.addr);
313 ret = read_via_objdump(objdump_name, objdump_addr, buf2, len); 315 ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
314 316
315 if (dso__needs_decompress(al.map->dso)) 317 if (decomp)
316 unlink(objdump_name); 318 unlink(objdump_name);
317 319
318 if (ret > 0) { 320 if (ret > 0) {
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index 148dd31cc201..0579a70bbbff 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -5,34 +5,28 @@
5#include "dso.h" 5#include "dso.h"
6#include "debug.h" 6#include "debug.h"
7 7
8static int test(const char *path, bool alloc_name, bool alloc_ext, 8static int test(const char *path, bool alloc_name, bool kmod,
9 bool kmod, bool comp, const char *name, const char *ext) 9 int comp, const char *name)
10{ 10{
11 struct kmod_path m; 11 struct kmod_path m;
12 12
13 memset(&m, 0x0, sizeof(m)); 13 memset(&m, 0x0, sizeof(m));
14 14
15 TEST_ASSERT_VAL("kmod_path__parse", 15 TEST_ASSERT_VAL("kmod_path__parse",
16 !__kmod_path__parse(&m, path, alloc_name, alloc_ext)); 16 !__kmod_path__parse(&m, path, alloc_name));
17 17
18 pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n", 18 pr_debug("%s - alloc name %d, kmod %d, comp %d, name '%s'\n",
19 path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext); 19 path, alloc_name, m.kmod, m.comp, m.name);
20 20
21 TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod); 21 TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
22 TEST_ASSERT_VAL("wrong comp", m.comp == comp); 22 TEST_ASSERT_VAL("wrong comp", m.comp == comp);
23 23
24 if (ext)
25 TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext));
26 else
27 TEST_ASSERT_VAL("wrong ext", !m.ext);
28
29 if (name) 24 if (name)
30 TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name)); 25 TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
31 else 26 else
32 TEST_ASSERT_VAL("wrong name", !m.name); 27 TEST_ASSERT_VAL("wrong name", !m.name);
33 28
34 free(m.name); 29 free(m.name);
35 free(m.ext);
36 return 0; 30 return 0;
37} 31}
38 32
@@ -45,118 +39,118 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
45 return 0; 39 return 0;
46} 40}
47 41
48#define T(path, an, ae, k, c, n, e) \ 42#define T(path, an, k, c, n) \
49 TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e)) 43 TEST_ASSERT_VAL("failed", !test(path, an, k, c, n))
50 44
51#define M(path, c, e) \ 45#define M(path, c, e) \
52 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e)) 46 TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
53 47
54int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused) 48int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused)
55{ 49{
56 /* path alloc_name alloc_ext kmod comp name ext */ 50 /* path alloc_name kmod comp name */
57 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL); 51 T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
58 T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL); 52 T("/xxxx/xxxx/x-x.ko", false , true, 0 , NULL );
59 T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL); 53 T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
60 T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL); 54 T("/xxxx/xxxx/x-x.ko", false , true, 0 , NULL );
61 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 55 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
62 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true); 56 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true);
63 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false); 57 M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false);
64 58
65#ifdef HAVE_ZLIB_SUPPORT 59#ifdef HAVE_ZLIB_SUPPORT
66 /* path alloc_name alloc_ext kmod comp name ext */ 60 /* path alloc_name kmod comp name */
67 T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz"); 61 T("/xxxx/xxxx/x.ko.gz", true , true, 1 , "[x]");
68 T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz"); 62 T("/xxxx/xxxx/x.ko.gz", false , true, 1 , NULL );
69 T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL); 63 T("/xxxx/xxxx/x.ko.gz", true , true, 1 , "[x]");
70 T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL); 64 T("/xxxx/xxxx/x.ko.gz", false , true, 1 , NULL );
71 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 65 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
72 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true); 66 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
73 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false); 67 M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false);
74 68
75 /* path alloc_name alloc_ext kmod comp name ext */ 69 /* path alloc_name kmod comp name */
76 T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz"); 70 T("/xxxx/xxxx/x.gz", true , false, 1 , "x.gz");
77 T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz"); 71 T("/xxxx/xxxx/x.gz", false , false, 1 , NULL );
78 T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL); 72 T("/xxxx/xxxx/x.gz", true , false, 1 , "x.gz");
79 T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL); 73 T("/xxxx/xxxx/x.gz", false , false, 1 , NULL );
80 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 74 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
81 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false); 75 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false);
82 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false); 76 M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false);
83 77
84 /* path alloc_name alloc_ext kmod comp name ext */ 78 /* path alloc_name kmod comp name */
85 T("x.gz", true , true , false, true, "x.gz", "gz"); 79 T("x.gz", true , false, 1 , "x.gz");
86 T("x.gz", false , true , false, true, NULL , "gz"); 80 T("x.gz", false , false, 1 , NULL );
87 T("x.gz", true , false , false, true, "x.gz", NULL); 81 T("x.gz", true , false, 1 , "x.gz");
88 T("x.gz", false , false , false, true, NULL , NULL); 82 T("x.gz", false , false, 1 , NULL );
89 M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 83 M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
90 M("x.gz", PERF_RECORD_MISC_KERNEL, false); 84 M("x.gz", PERF_RECORD_MISC_KERNEL, false);
91 M("x.gz", PERF_RECORD_MISC_USER, false); 85 M("x.gz", PERF_RECORD_MISC_USER, false);
92 86
93 /* path alloc_name alloc_ext kmod comp name ext */ 87 /* path alloc_name kmod comp name */
94 T("x.ko.gz", true , true , true, true, "[x]", "gz"); 88 T("x.ko.gz", true , true, 1 , "[x]");
95 T("x.ko.gz", false , true , true, true, NULL , "gz"); 89 T("x.ko.gz", false , true, 1 , NULL );
96 T("x.ko.gz", true , false , true, true, "[x]", NULL); 90 T("x.ko.gz", true , true, 1 , "[x]");
97 T("x.ko.gz", false , false , true, true, NULL , NULL); 91 T("x.ko.gz", false , true, 1 , NULL );
98 M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 92 M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
99 M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true); 93 M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
100 M("x.ko.gz", PERF_RECORD_MISC_USER, false); 94 M("x.ko.gz", PERF_RECORD_MISC_USER, false);
101#endif 95#endif
102 96
103 /* path alloc_name alloc_ext kmod comp name ext */ 97 /* path alloc_name kmod comp name */
104 T("[test_module]", true , true , true, false, "[test_module]", NULL); 98 T("[test_module]", true , true, false, "[test_module]");
105 T("[test_module]", false , true , true, false, NULL , NULL); 99 T("[test_module]", false , true, false, NULL );
106 T("[test_module]", true , false , true, false, "[test_module]", NULL); 100 T("[test_module]", true , true, false, "[test_module]");
107 T("[test_module]", false , false , true, false, NULL , NULL); 101 T("[test_module]", false , true, false, NULL );
108 M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 102 M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
109 M("[test_module]", PERF_RECORD_MISC_KERNEL, true); 103 M("[test_module]", PERF_RECORD_MISC_KERNEL, true);
110 M("[test_module]", PERF_RECORD_MISC_USER, false); 104 M("[test_module]", PERF_RECORD_MISC_USER, false);
111 105
112 /* path alloc_name alloc_ext kmod comp name ext */ 106 /* path alloc_name kmod comp name */
113 T("[test.module]", true , true , true, false, "[test.module]", NULL); 107 T("[test.module]", true , true, false, "[test.module]");
114 T("[test.module]", false , true , true, false, NULL , NULL); 108 T("[test.module]", false , true, false, NULL );
115 T("[test.module]", true , false , true, false, "[test.module]", NULL); 109 T("[test.module]", true , true, false, "[test.module]");
116 T("[test.module]", false , false , true, false, NULL , NULL); 110 T("[test.module]", false , true, false, NULL );
117 M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true); 111 M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
118 M("[test.module]", PERF_RECORD_MISC_KERNEL, true); 112 M("[test.module]", PERF_RECORD_MISC_KERNEL, true);
119 M("[test.module]", PERF_RECORD_MISC_USER, false); 113 M("[test.module]", PERF_RECORD_MISC_USER, false);
120 114
121 /* path alloc_name alloc_ext kmod comp name ext */ 115 /* path alloc_name kmod comp name */
122 T("[vdso]", true , true , false, false, "[vdso]", NULL); 116 T("[vdso]", true , false, false, "[vdso]");
123 T("[vdso]", false , true , false, false, NULL , NULL); 117 T("[vdso]", false , false, false, NULL );
124 T("[vdso]", true , false , false, false, "[vdso]", NULL); 118 T("[vdso]", true , false, false, "[vdso]");
125 T("[vdso]", false , false , false, false, NULL , NULL); 119 T("[vdso]", false , false, false, NULL );
126 M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 120 M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
127 M("[vdso]", PERF_RECORD_MISC_KERNEL, false); 121 M("[vdso]", PERF_RECORD_MISC_KERNEL, false);
128 M("[vdso]", PERF_RECORD_MISC_USER, false); 122 M("[vdso]", PERF_RECORD_MISC_USER, false);
129 123
130 T("[vdso32]", true , true , false, false, "[vdso32]", NULL); 124 T("[vdso32]", true , false, false, "[vdso32]");
131 T("[vdso32]", false , true , false, false, NULL , NULL); 125 T("[vdso32]", false , false, false, NULL );
132 T("[vdso32]", true , false , false, false, "[vdso32]", NULL); 126 T("[vdso32]", true , false, false, "[vdso32]");
133 T("[vdso32]", false , false , false, false, NULL , NULL); 127 T("[vdso32]", false , false, false, NULL );
134 M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 128 M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
135 M("[vdso32]", PERF_RECORD_MISC_KERNEL, false); 129 M("[vdso32]", PERF_RECORD_MISC_KERNEL, false);
136 M("[vdso32]", PERF_RECORD_MISC_USER, false); 130 M("[vdso32]", PERF_RECORD_MISC_USER, false);
137 131
138 T("[vdsox32]", true , true , false, false, "[vdsox32]", NULL); 132 T("[vdsox32]", true , false, false, "[vdsox32]");
139 T("[vdsox32]", false , true , false, false, NULL , NULL); 133 T("[vdsox32]", false , false, false, NULL );
140 T("[vdsox32]", true , false , false, false, "[vdsox32]", NULL); 134 T("[vdsox32]", true , false, false, "[vdsox32]");
141 T("[vdsox32]", false , false , false, false, NULL , NULL); 135 T("[vdsox32]", false , false, false, NULL );
142 M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 136 M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
143 M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false); 137 M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false);
144 M("[vdsox32]", PERF_RECORD_MISC_USER, false); 138 M("[vdsox32]", PERF_RECORD_MISC_USER, false);
145 139
146 /* path alloc_name alloc_ext kmod comp name ext */ 140 /* path alloc_name kmod comp name */
147 T("[vsyscall]", true , true , false, false, "[vsyscall]", NULL); 141 T("[vsyscall]", true , false, false, "[vsyscall]");
148 T("[vsyscall]", false , true , false, false, NULL , NULL); 142 T("[vsyscall]", false , false, false, NULL );
149 T("[vsyscall]", true , false , false, false, "[vsyscall]", NULL); 143 T("[vsyscall]", true , false, false, "[vsyscall]");
150 T("[vsyscall]", false , false , false, false, NULL , NULL); 144 T("[vsyscall]", false , false, false, NULL );
151 M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 145 M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
152 M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false); 146 M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false);
153 M("[vsyscall]", PERF_RECORD_MISC_USER, false); 147 M("[vsyscall]", PERF_RECORD_MISC_USER, false);
154 148
155 /* path alloc_name alloc_ext kmod comp name ext */ 149 /* path alloc_name kmod comp name */
156 T("[kernel.kallsyms]", true , true , false, false, "[kernel.kallsyms]", NULL); 150 T("[kernel.kallsyms]", true , false, false, "[kernel.kallsyms]");
157 T("[kernel.kallsyms]", false , true , false, false, NULL , NULL); 151 T("[kernel.kallsyms]", false , false, false, NULL );
158 T("[kernel.kallsyms]", true , false , false, false, "[kernel.kallsyms]", NULL); 152 T("[kernel.kallsyms]", true , false, false, "[kernel.kallsyms]");
159 T("[kernel.kallsyms]", false , false , false, false, NULL , NULL); 153 T("[kernel.kallsyms]", false , false, false, NULL );
160 M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false); 154 M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
161 M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false); 155 M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false);
162 M("[kernel.kallsyms]", PERF_RECORD_MISC_USER, false); 156 M("[kernel.kallsyms]", PERF_RECORD_MISC_USER, false);
diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c
index 0c3c87f86e03..9e9e4d37cc77 100644
--- a/tools/perf/tests/mem2node.c
+++ b/tools/perf/tests/mem2node.c
@@ -24,8 +24,6 @@ static unsigned long *get_bitmap(const char *str, int nbits)
24 bm = bitmap_alloc(nbits); 24 bm = bitmap_alloc(nbits);
25 25
26 if (map && bm) { 26 if (map && bm) {
27 bitmap_zero(bm, nbits);
28
29 for (i = 0; i < map->nr; i++) { 27 for (i = 0; i < map->nr; i++) {
30 set_bit(map->map[i], bm); 28 set_bit(map->map[i], bm);
31 } 29 }
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 3b4f1c10ff57..1d00e5ec7906 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -15,6 +15,7 @@
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <linux/string.h> 16#include <linux/string.h>
17#include <sys/ttydefaults.h> 17#include <sys/ttydefaults.h>
18#include <asm/bug.h>
18 19
19struct disasm_line_samples { 20struct disasm_line_samples {
20 double percent; 21 double percent;
@@ -115,7 +116,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
115 if (!browser->navkeypressed) 116 if (!browser->navkeypressed)
116 ops.width += 1; 117 ops.width += 1;
117 118
118 annotation_line__write(al, notes, &ops); 119 annotation_line__write(al, notes, &ops, ab->opts);
119 120
120 if (ops.current_entry) 121 if (ops.current_entry)
121 ab->selection = al; 122 ab->selection = al;
@@ -227,10 +228,10 @@ static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
227{ 228{
228 int i; 229 int i;
229 230
230 for (i = 0; i < a->samples_nr; i++) { 231 for (i = 0; i < a->data_nr; i++) {
231 if (a->samples[i].percent == b->samples[i].percent) 232 if (a->data[i].percent == b->data[i].percent)
232 continue; 233 continue;
233 return a->samples[i].percent < b->samples[i].percent; 234 return a->data[i].percent < b->data[i].percent;
234 } 235 }
235 return 0; 236 return 0;
236} 237}
@@ -314,11 +315,14 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
314 continue; 315 continue;
315 } 316 }
316 317
317 for (i = 0; i < pos->al.samples_nr; i++) { 318 for (i = 0; i < pos->al.data_nr; i++) {
318 struct annotation_data *sample = &pos->al.samples[i]; 319 double percent;
319 320
320 if (max_percent < sample->percent) 321 percent = annotation_data__percent(&pos->al.data[i],
321 max_percent = sample->percent; 322 browser->opts->percent_type);
323
324 if (max_percent < percent)
325 max_percent = percent;
322 } 326 }
323 327
324 if (max_percent < 0.01 && pos->al.ipc == 0) { 328 if (max_percent < 0.01 && pos->al.ipc == 0) {
@@ -380,9 +384,10 @@ static void ui_browser__init_asm_mode(struct ui_browser *browser)
380#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 384#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
381 385
382static int sym_title(struct symbol *sym, struct map *map, char *title, 386static int sym_title(struct symbol *sym, struct map *map, char *title,
383 size_t sz) 387 size_t sz, int percent_type)
384{ 388{
385 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 389 return snprintf(title, sz, "%s %s [Percent: %s]", sym->name, map->dso->long_name,
390 percent_type_str(percent_type));
386} 391}
387 392
388/* 393/*
@@ -420,7 +425,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
420 425
421 pthread_mutex_unlock(&notes->lock); 426 pthread_mutex_unlock(&notes->lock);
422 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts); 427 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts);
423 sym_title(ms->sym, ms->map, title, sizeof(title)); 428 sym_title(ms->sym, ms->map, title, sizeof(title), browser->opts->percent_type);
424 ui_browser__show_title(&browser->b, title); 429 ui_browser__show_title(&browser->b, title);
425 return true; 430 return true;
426} 431}
@@ -595,6 +600,7 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
595 600
596static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help) 601static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
597{ 602{
603 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
598 struct map_symbol *ms = browser->priv; 604 struct map_symbol *ms = browser->priv;
599 struct symbol *sym = ms->sym; 605 struct symbol *sym = ms->sym;
600 char symbol_dso[SYM_TITLE_MAX_SIZE]; 606 char symbol_dso[SYM_TITLE_MAX_SIZE];
@@ -602,7 +608,7 @@ static int annotate_browser__show(struct ui_browser *browser, char *title, const
602 if (ui_browser__show(browser, title, help) < 0) 608 if (ui_browser__show(browser, title, help) < 0)
603 return -1; 609 return -1;
604 610
605 sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso)); 611 sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso), ab->opts->percent_type);
606 612
607 ui_browser__gotorc_title(browser, 0, 0); 613 ui_browser__gotorc_title(browser, 0, 0);
608 ui_browser__set_color(browser, HE_COLORSET_ROOT); 614 ui_browser__set_color(browser, HE_COLORSET_ROOT);
@@ -610,6 +616,39 @@ static int annotate_browser__show(struct ui_browser *browser, char *title, const
610 return 0; 616 return 0;
611} 617}
612 618
619static void
620switch_percent_type(struct annotation_options *opts, bool base)
621{
622 switch (opts->percent_type) {
623 case PERCENT_HITS_LOCAL:
624 if (base)
625 opts->percent_type = PERCENT_PERIOD_LOCAL;
626 else
627 opts->percent_type = PERCENT_HITS_GLOBAL;
628 break;
629 case PERCENT_HITS_GLOBAL:
630 if (base)
631 opts->percent_type = PERCENT_PERIOD_GLOBAL;
632 else
633 opts->percent_type = PERCENT_HITS_LOCAL;
634 break;
635 case PERCENT_PERIOD_LOCAL:
636 if (base)
637 opts->percent_type = PERCENT_HITS_LOCAL;
638 else
639 opts->percent_type = PERCENT_PERIOD_GLOBAL;
640 break;
641 case PERCENT_PERIOD_GLOBAL:
642 if (base)
643 opts->percent_type = PERCENT_HITS_GLOBAL;
644 else
645 opts->percent_type = PERCENT_PERIOD_LOCAL;
646 break;
647 default:
648 WARN_ON(1);
649 }
650}
651
613static int annotate_browser__run(struct annotate_browser *browser, 652static int annotate_browser__run(struct annotate_browser *browser,
614 struct perf_evsel *evsel, 653 struct perf_evsel *evsel,
615 struct hist_browser_timer *hbt) 654 struct hist_browser_timer *hbt)
@@ -624,8 +663,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
624 char title[256]; 663 char title[256];
625 int key; 664 int key;
626 665
627 annotation__scnprintf_samples_period(notes, title, sizeof(title), evsel); 666 hists__scnprintf_title(hists, title, sizeof(title));
628
629 if (annotate_browser__show(&browser->b, title, help) < 0) 667 if (annotate_browser__show(&browser->b, title, help) < 0)
630 return -1; 668 return -1;
631 669
@@ -701,6 +739,8 @@ static int annotate_browser__run(struct annotate_browser *browser,
701 "k Toggle line numbers\n" 739 "k Toggle line numbers\n"
702 "P Print to [symbol_name].annotation file.\n" 740 "P Print to [symbol_name].annotation file.\n"
703 "r Run available scripts\n" 741 "r Run available scripts\n"
742 "p Toggle percent type [local/global]\n"
743 "b Toggle percent base [period/hits]\n"
704 "? Search string backwards\n"); 744 "? Search string backwards\n");
705 continue; 745 continue;
706 case 'r': 746 case 'r':
@@ -781,7 +821,7 @@ show_sup_ins:
781 continue; 821 continue;
782 } 822 }
783 case 'P': 823 case 'P':
784 map_symbol__annotation_dump(ms, evsel); 824 map_symbol__annotation_dump(ms, evsel, browser->opts);
785 continue; 825 continue;
786 case 't': 826 case 't':
787 if (notes->options->show_total_period) { 827 if (notes->options->show_total_period) {
@@ -800,6 +840,12 @@ show_sup_ins:
800 notes->options->show_minmax_cycle = true; 840 notes->options->show_minmax_cycle = true;
801 annotation__update_column_widths(notes); 841 annotation__update_column_widths(notes);
802 continue; 842 continue;
843 case 'p':
844 case 'b':
845 switch_percent_type(browser->opts, key == 'b');
846 hists__scnprintf_title(hists, title, sizeof(title));
847 annotate_browser__show(&browser->b, title, help);
848 continue;
803 case K_LEFT: 849 case K_LEFT:
804 case K_ESC: 850 case K_ESC:
805 case 'q': 851 case 'q':
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index b604ef334dc9..7efe15b9618d 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -87,6 +87,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt.o
87libperf-$(CONFIG_AUXTRACE) += intel-bts.o 87libperf-$(CONFIG_AUXTRACE) += intel-bts.o
88libperf-$(CONFIG_AUXTRACE) += arm-spe.o 88libperf-$(CONFIG_AUXTRACE) += arm-spe.o
89libperf-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o 89libperf-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o
90libperf-$(CONFIG_AUXTRACE) += s390-cpumsf.o
90 91
91ifdef CONFIG_LIBOPENCSD 92ifdef CONFIG_LIBOPENCSD
92libperf-$(CONFIG_AUXTRACE) += cs-etm.o 93libperf-$(CONFIG_AUXTRACE) += cs-etm.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index f91775b4bc3c..20061cf42288 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -49,6 +49,7 @@ struct annotation_options annotation__default_options = {
49 .jump_arrows = true, 49 .jump_arrows = true,
50 .annotate_src = true, 50 .annotate_src = true,
51 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS, 51 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS,
52 .percent_type = PERCENT_PERIOD_LOCAL,
52}; 53};
53 54
54static regex_t file_lineno; 55static regex_t file_lineno;
@@ -1108,7 +1109,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize)
1108 if (perf_evsel__is_group_event(evsel)) 1109 if (perf_evsel__is_group_event(evsel))
1109 nr = evsel->nr_members; 1110 nr = evsel->nr_members;
1110 1111
1111 size += sizeof(al->samples[0]) * nr; 1112 size += sizeof(al->data[0]) * nr;
1112 1113
1113 al = zalloc(size); 1114 al = zalloc(size);
1114 if (al) { 1115 if (al) {
@@ -1117,7 +1118,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize)
1117 al->offset = args->offset; 1118 al->offset = args->offset;
1118 al->line = strdup(args->line); 1119 al->line = strdup(args->line);
1119 al->line_nr = args->line_nr; 1120 al->line_nr = args->line_nr;
1120 al->samples_nr = nr; 1121 al->data_nr = nr;
1121 } 1122 }
1122 1123
1123 return al; 1124 return al;
@@ -1297,7 +1298,8 @@ static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_wi
1297static int 1298static int
1298annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start, 1299annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
1299 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed, 1300 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
1300 int max_lines, struct annotation_line *queue, int addr_fmt_width) 1301 int max_lines, struct annotation_line *queue, int addr_fmt_width,
1302 int percent_type)
1301{ 1303{
1302 struct disasm_line *dl = container_of(al, struct disasm_line, al); 1304 struct disasm_line *dl = container_of(al, struct disasm_line, al);
1303 static const char *prev_line; 1305 static const char *prev_line;
@@ -1309,15 +1311,18 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1309 const char *color; 1311 const char *color;
1310 struct annotation *notes = symbol__annotation(sym); 1312 struct annotation *notes = symbol__annotation(sym);
1311 1313
1312 for (i = 0; i < al->samples_nr; i++) { 1314 for (i = 0; i < al->data_nr; i++) {
1313 struct annotation_data *sample = &al->samples[i]; 1315 double percent;
1314 1316
1315 if (sample->percent > max_percent) 1317 percent = annotation_data__percent(&al->data[i],
1316 max_percent = sample->percent; 1318 percent_type);
1319
1320 if (percent > max_percent)
1321 max_percent = percent;
1317 } 1322 }
1318 1323
1319 if (al->samples_nr > nr_percent) 1324 if (al->data_nr > nr_percent)
1320 nr_percent = al->samples_nr; 1325 nr_percent = al->data_nr;
1321 1326
1322 if (max_percent < min_pcnt) 1327 if (max_percent < min_pcnt)
1323 return -1; 1328 return -1;
@@ -1330,7 +1335,8 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1330 if (queue == al) 1335 if (queue == al)
1331 break; 1336 break;
1332 annotation_line__print(queue, sym, start, evsel, len, 1337 annotation_line__print(queue, sym, start, evsel, len,
1333 0, 0, 1, NULL, addr_fmt_width); 1338 0, 0, 1, NULL, addr_fmt_width,
1339 percent_type);
1334 } 1340 }
1335 } 1341 }
1336 1342
@@ -1351,18 +1357,20 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1351 } 1357 }
1352 1358
1353 for (i = 0; i < nr_percent; i++) { 1359 for (i = 0; i < nr_percent; i++) {
1354 struct annotation_data *sample = &al->samples[i]; 1360 struct annotation_data *data = &al->data[i];
1361 double percent;
1355 1362
1356 color = get_percent_color(sample->percent); 1363 percent = annotation_data__percent(data, percent_type);
1364 color = get_percent_color(percent);
1357 1365
1358 if (symbol_conf.show_total_period) 1366 if (symbol_conf.show_total_period)
1359 color_fprintf(stdout, color, " %11" PRIu64, 1367 color_fprintf(stdout, color, " %11" PRIu64,
1360 sample->he.period); 1368 data->he.period);
1361 else if (symbol_conf.show_nr_samples) 1369 else if (symbol_conf.show_nr_samples)
1362 color_fprintf(stdout, color, " %7" PRIu64, 1370 color_fprintf(stdout, color, " %7" PRIu64,
1363 sample->he.nr_samples); 1371 data->he.nr_samples);
1364 else 1372 else
1365 color_fprintf(stdout, color, " %7.2f", sample->percent); 1373 color_fprintf(stdout, color, " %7.2f", percent);
1366 } 1374 }
1367 1375
1368 printf(" : "); 1376 printf(" : ");
@@ -1621,6 +1629,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1621 char symfs_filename[PATH_MAX]; 1629 char symfs_filename[PATH_MAX];
1622 struct kcore_extract kce; 1630 struct kcore_extract kce;
1623 bool delete_extract = false; 1631 bool delete_extract = false;
1632 bool decomp = false;
1624 int stdout_fd[2]; 1633 int stdout_fd[2];
1625 int lineno = 0; 1634 int lineno = 0;
1626 int nline; 1635 int nline;
@@ -1654,6 +1663,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1654 tmp, sizeof(tmp)) < 0) 1663 tmp, sizeof(tmp)) < 0)
1655 goto out; 1664 goto out;
1656 1665
1666 decomp = true;
1657 strcpy(symfs_filename, tmp); 1667 strcpy(symfs_filename, tmp);
1658 } 1668 }
1659 1669
@@ -1740,7 +1750,7 @@ out_free_command:
1740out_remove_tmp: 1750out_remove_tmp:
1741 close(stdout_fd[0]); 1751 close(stdout_fd[0]);
1742 1752
1743 if (dso__needs_decompress(dso)) 1753 if (decomp)
1744 unlink(symfs_filename); 1754 unlink(symfs_filename);
1745 1755
1746 if (delete_extract) 1756 if (delete_extract)
@@ -1753,34 +1763,45 @@ out_close_stdout:
1753 goto out_free_command; 1763 goto out_free_command;
1754} 1764}
1755 1765
1756static void calc_percent(struct sym_hist *hist, 1766static void calc_percent(struct sym_hist *sym_hist,
1757 struct annotation_data *sample, 1767 struct hists *hists,
1768 struct annotation_data *data,
1758 s64 offset, s64 end) 1769 s64 offset, s64 end)
1759{ 1770{
1760 unsigned int hits = 0; 1771 unsigned int hits = 0;
1761 u64 period = 0; 1772 u64 period = 0;
1762 1773
1763 while (offset < end) { 1774 while (offset < end) {
1764 hits += hist->addr[offset].nr_samples; 1775 hits += sym_hist->addr[offset].nr_samples;
1765 period += hist->addr[offset].period; 1776 period += sym_hist->addr[offset].period;
1766 ++offset; 1777 ++offset;
1767 } 1778 }
1768 1779
1769 if (hist->nr_samples) { 1780 if (sym_hist->nr_samples) {
1770 sample->he.period = period; 1781 data->he.period = period;
1771 sample->he.nr_samples = hits; 1782 data->he.nr_samples = hits;
1772 sample->percent = 100.0 * hits / hist->nr_samples; 1783 data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
1773 } 1784 }
1785
1786 if (hists->stats.nr_non_filtered_samples)
1787 data->percent[PERCENT_HITS_GLOBAL] = 100.0 * hits / hists->stats.nr_non_filtered_samples;
1788
1789 if (sym_hist->period)
1790 data->percent[PERCENT_PERIOD_LOCAL] = 100.0 * period / sym_hist->period;
1791
1792 if (hists->stats.total_period)
1793 data->percent[PERCENT_PERIOD_GLOBAL] = 100.0 * period / hists->stats.total_period;
1774} 1794}
1775 1795
1776static void annotation__calc_percent(struct annotation *notes, 1796static void annotation__calc_percent(struct annotation *notes,
1777 struct perf_evsel *evsel, s64 len) 1797 struct perf_evsel *leader, s64 len)
1778{ 1798{
1779 struct annotation_line *al, *next; 1799 struct annotation_line *al, *next;
1800 struct perf_evsel *evsel;
1780 1801
1781 list_for_each_entry(al, &notes->src->source, node) { 1802 list_for_each_entry(al, &notes->src->source, node) {
1782 s64 end; 1803 s64 end;
1783 int i; 1804 int i = 0;
1784 1805
1785 if (al->offset == -1) 1806 if (al->offset == -1)
1786 continue; 1807 continue;
@@ -1788,14 +1809,17 @@ static void annotation__calc_percent(struct annotation *notes,
1788 next = annotation_line__next(al, &notes->src->source); 1809 next = annotation_line__next(al, &notes->src->source);
1789 end = next ? next->offset : len; 1810 end = next ? next->offset : len;
1790 1811
1791 for (i = 0; i < al->samples_nr; i++) { 1812 for_each_group_evsel(evsel, leader) {
1792 struct annotation_data *sample; 1813 struct hists *hists = evsel__hists(evsel);
1793 struct sym_hist *hist; 1814 struct annotation_data *data;
1815 struct sym_hist *sym_hist;
1816
1817 BUG_ON(i >= al->data_nr);
1794 1818
1795 hist = annotation__histogram(notes, evsel->idx + i); 1819 sym_hist = annotation__histogram(notes, evsel->idx);
1796 sample = &al->samples[i]; 1820 data = &al->data[i++];
1797 1821
1798 calc_percent(hist, sample, al->offset, end); 1822 calc_percent(sym_hist, hists, data, al->offset, end);
1799 } 1823 }
1800 } 1824 }
1801} 1825}
@@ -1846,7 +1870,8 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1846 return symbol__disassemble(sym, &args); 1870 return symbol__disassemble(sym, &args);
1847} 1871}
1848 1872
1849static void insert_source_line(struct rb_root *root, struct annotation_line *al) 1873static void insert_source_line(struct rb_root *root, struct annotation_line *al,
1874 struct annotation_options *opts)
1850{ 1875{
1851 struct annotation_line *iter; 1876 struct annotation_line *iter;
1852 struct rb_node **p = &root->rb_node; 1877 struct rb_node **p = &root->rb_node;
@@ -1859,8 +1884,10 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al)
1859 1884
1860 ret = strcmp(iter->path, al->path); 1885 ret = strcmp(iter->path, al->path);
1861 if (ret == 0) { 1886 if (ret == 0) {
1862 for (i = 0; i < al->samples_nr; i++) 1887 for (i = 0; i < al->data_nr; i++) {
1863 iter->samples[i].percent_sum += al->samples[i].percent; 1888 iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
1889 opts->percent_type);
1890 }
1864 return; 1891 return;
1865 } 1892 }
1866 1893
@@ -1870,8 +1897,10 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al)
1870 p = &(*p)->rb_right; 1897 p = &(*p)->rb_right;
1871 } 1898 }
1872 1899
1873 for (i = 0; i < al->samples_nr; i++) 1900 for (i = 0; i < al->data_nr; i++) {
1874 al->samples[i].percent_sum = al->samples[i].percent; 1901 al->data[i].percent_sum = annotation_data__percent(&al->data[i],
1902 opts->percent_type);
1903 }
1875 1904
1876 rb_link_node(&al->rb_node, parent, p); 1905 rb_link_node(&al->rb_node, parent, p);
1877 rb_insert_color(&al->rb_node, root); 1906 rb_insert_color(&al->rb_node, root);
@@ -1881,10 +1910,10 @@ static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
1881{ 1910{
1882 int i; 1911 int i;
1883 1912
1884 for (i = 0; i < a->samples_nr; i++) { 1913 for (i = 0; i < a->data_nr; i++) {
1885 if (a->samples[i].percent_sum == b->samples[i].percent_sum) 1914 if (a->data[i].percent_sum == b->data[i].percent_sum)
1886 continue; 1915 continue;
1887 return a->samples[i].percent_sum > b->samples[i].percent_sum; 1916 return a->data[i].percent_sum > b->data[i].percent_sum;
1888 } 1917 }
1889 1918
1890 return 0; 1919 return 0;
@@ -1949,8 +1978,8 @@ static void print_summary(struct rb_root *root, const char *filename)
1949 int i; 1978 int i;
1950 1979
1951 al = rb_entry(node, struct annotation_line, rb_node); 1980 al = rb_entry(node, struct annotation_line, rb_node);
1952 for (i = 0; i < al->samples_nr; i++) { 1981 for (i = 0; i < al->data_nr; i++) {
1953 percent = al->samples[i].percent_sum; 1982 percent = al->data[i].percent_sum;
1954 color = get_percent_color(percent); 1983 color = get_percent_color(percent);
1955 color_fprintf(stdout, color, " %7.2f", percent); 1984 color_fprintf(stdout, color, " %7.2f", percent);
1956 1985
@@ -2029,10 +2058,12 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
2029 evsel_name = buf; 2058 evsel_name = buf;
2030 } 2059 }
2031 2060
2032 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 2061 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples, "
2062 "percent: %s)\n",
2033 width, width, symbol_conf.show_total_period ? "Period" : 2063 width, width, symbol_conf.show_total_period ? "Period" :
2034 symbol_conf.show_nr_samples ? "Samples" : "Percent", 2064 symbol_conf.show_nr_samples ? "Samples" : "Percent",
2035 d_filename, evsel_name, h->nr_samples); 2065 d_filename, evsel_name, h->nr_samples,
2066 percent_type_str(opts->percent_type));
2036 2067
2037 printf("%-*.*s----\n", 2068 printf("%-*.*s----\n",
2038 graph_dotted_len, graph_dotted_len, graph_dotted_line); 2069 graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -2052,7 +2083,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
2052 2083
2053 err = annotation_line__print(pos, sym, start, evsel, len, 2084 err = annotation_line__print(pos, sym, start, evsel, len,
2054 opts->min_pcnt, printed, opts->max_lines, 2085 opts->min_pcnt, printed, opts->max_lines,
2055 queue, addr_fmt_width); 2086 queue, addr_fmt_width, opts->percent_type);
2056 2087
2057 switch (err) { 2088 switch (err) {
2058 case 0: 2089 case 0:
@@ -2129,10 +2160,11 @@ static void FILE__write_graph(void *fp, int graph)
2129 fputs(s, fp); 2160 fputs(s, fp);
2130} 2161}
2131 2162
2132int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp) 2163static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
2164 struct annotation_options *opts)
2133{ 2165{
2134 struct annotation *notes = symbol__annotation(sym); 2166 struct annotation *notes = symbol__annotation(sym);
2135 struct annotation_write_ops ops = { 2167 struct annotation_write_ops wops = {
2136 .first_line = true, 2168 .first_line = true,
2137 .obj = fp, 2169 .obj = fp,
2138 .set_color = FILE__set_color, 2170 .set_color = FILE__set_color,
@@ -2146,15 +2178,16 @@ int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
2146 list_for_each_entry(al, &notes->src->source, node) { 2178 list_for_each_entry(al, &notes->src->source, node) {
2147 if (annotation_line__filter(al, notes)) 2179 if (annotation_line__filter(al, notes))
2148 continue; 2180 continue;
2149 annotation_line__write(al, notes, &ops); 2181 annotation_line__write(al, notes, &wops, opts);
2150 fputc('\n', fp); 2182 fputc('\n', fp);
2151 ops.first_line = false; 2183 wops.first_line = false;
2152 } 2184 }
2153 2185
2154 return 0; 2186 return 0;
2155} 2187}
2156 2188
2157int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel) 2189int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
2190 struct annotation_options *opts)
2158{ 2191{
2159 const char *ev_name = perf_evsel__name(evsel); 2192 const char *ev_name = perf_evsel__name(evsel);
2160 char buf[1024]; 2193 char buf[1024];
@@ -2176,7 +2209,7 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
2176 2209
2177 fprintf(fp, "%s() %s\nEvent: %s\n\n", 2210 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2178 ms->sym->name, ms->map->dso->long_name, ev_name); 2211 ms->sym->name, ms->map->dso->long_name, ev_name);
2179 symbol__annotate_fprintf2(ms->sym, fp); 2212 symbol__annotate_fprintf2(ms->sym, fp, opts);
2180 2213
2181 fclose(fp); 2214 fclose(fp);
2182 err = 0; 2215 err = 0;
@@ -2346,7 +2379,8 @@ void annotation__update_column_widths(struct annotation *notes)
2346} 2379}
2347 2380
2348static void annotation__calc_lines(struct annotation *notes, struct map *map, 2381static void annotation__calc_lines(struct annotation *notes, struct map *map,
2349 struct rb_root *root) 2382 struct rb_root *root,
2383 struct annotation_options *opts)
2350{ 2384{
2351 struct annotation_line *al; 2385 struct annotation_line *al;
2352 struct rb_root tmp_root = RB_ROOT; 2386 struct rb_root tmp_root = RB_ROOT;
@@ -2355,13 +2389,14 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
2355 double percent_max = 0.0; 2389 double percent_max = 0.0;
2356 int i; 2390 int i;
2357 2391
2358 for (i = 0; i < al->samples_nr; i++) { 2392 for (i = 0; i < al->data_nr; i++) {
2359 struct annotation_data *sample; 2393 double percent;
2360 2394
2361 sample = &al->samples[i]; 2395 percent = annotation_data__percent(&al->data[i],
2396 opts->percent_type);
2362 2397
2363 if (sample->percent > percent_max) 2398 if (percent > percent_max)
2364 percent_max = sample->percent; 2399 percent_max = percent;
2365 } 2400 }
2366 2401
2367 if (percent_max <= 0.5) 2402 if (percent_max <= 0.5)
@@ -2369,18 +2404,19 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
2369 2404
2370 al->path = get_srcline(map->dso, notes->start + al->offset, NULL, 2405 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
2371 false, true, notes->start + al->offset); 2406 false, true, notes->start + al->offset);
2372 insert_source_line(&tmp_root, al); 2407 insert_source_line(&tmp_root, al, opts);
2373 } 2408 }
2374 2409
2375 resort_source_line(root, &tmp_root); 2410 resort_source_line(root, &tmp_root);
2376} 2411}
2377 2412
2378static void symbol__calc_lines(struct symbol *sym, struct map *map, 2413static void symbol__calc_lines(struct symbol *sym, struct map *map,
2379 struct rb_root *root) 2414 struct rb_root *root,
2415 struct annotation_options *opts)
2380{ 2416{
2381 struct annotation *notes = symbol__annotation(sym); 2417 struct annotation *notes = symbol__annotation(sym);
2382 2418
2383 annotation__calc_lines(notes, map, root); 2419 annotation__calc_lines(notes, map, root, opts);
2384} 2420}
2385 2421
2386int symbol__tty_annotate2(struct symbol *sym, struct map *map, 2422int symbol__tty_annotate2(struct symbol *sym, struct map *map,
@@ -2389,7 +2425,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2389{ 2425{
2390 struct dso *dso = map->dso; 2426 struct dso *dso = map->dso;
2391 struct rb_root source_line = RB_ROOT; 2427 struct rb_root source_line = RB_ROOT;
2392 struct annotation *notes = symbol__annotation(sym); 2428 struct hists *hists = evsel__hists(evsel);
2393 char buf[1024]; 2429 char buf[1024];
2394 2430
2395 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0) 2431 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
@@ -2397,13 +2433,14 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2397 2433
2398 if (opts->print_lines) { 2434 if (opts->print_lines) {
2399 srcline_full_filename = opts->full_path; 2435 srcline_full_filename = opts->full_path;
2400 symbol__calc_lines(sym, map, &source_line); 2436 symbol__calc_lines(sym, map, &source_line, opts);
2401 print_summary(&source_line, dso->long_name); 2437 print_summary(&source_line, dso->long_name);
2402 } 2438 }
2403 2439
2404 annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel); 2440 hists__scnprintf_title(hists, buf, sizeof(buf));
2405 fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name); 2441 fprintf(stdout, "%s, [percent: %s]\n%s() %s\n",
2406 symbol__annotate_fprintf2(sym, stdout); 2442 buf, percent_type_str(opts->percent_type), sym->name, dso->long_name);
2443 symbol__annotate_fprintf2(sym, stdout, opts);
2407 2444
2408 annotated_source__purge(symbol__annotation(sym)->src); 2445 annotated_source__purge(symbol__annotation(sym)->src);
2409 2446
@@ -2424,7 +2461,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
2424 2461
2425 if (opts->print_lines) { 2462 if (opts->print_lines) {
2426 srcline_full_filename = opts->full_path; 2463 srcline_full_filename = opts->full_path;
2427 symbol__calc_lines(sym, map, &source_line); 2464 symbol__calc_lines(sym, map, &source_line, opts);
2428 print_summary(&source_line, dso->long_name); 2465 print_summary(&source_line, dso->long_name);
2429 } 2466 }
2430 2467
@@ -2441,14 +2478,21 @@ bool ui__has_annotation(void)
2441} 2478}
2442 2479
2443 2480
2444double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes) 2481static double annotation_line__max_percent(struct annotation_line *al,
2482 struct annotation *notes,
2483 unsigned int percent_type)
2445{ 2484{
2446 double percent_max = 0.0; 2485 double percent_max = 0.0;
2447 int i; 2486 int i;
2448 2487
2449 for (i = 0; i < notes->nr_events; i++) { 2488 for (i = 0; i < notes->nr_events; i++) {
2450 if (al->samples[i].percent > percent_max) 2489 double percent;
2451 percent_max = al->samples[i].percent; 2490
2491 percent = annotation_data__percent(&al->data[i],
2492 percent_type);
2493
2494 if (percent > percent_max)
2495 percent_max = percent;
2452 } 2496 }
2453 2497
2454 return percent_max; 2498 return percent_max;
@@ -2487,7 +2531,7 @@ call_like:
2487 2531
2488static void __annotation_line__write(struct annotation_line *al, struct annotation *notes, 2532static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2489 bool first_line, bool current_entry, bool change_color, int width, 2533 bool first_line, bool current_entry, bool change_color, int width,
2490 void *obj, 2534 void *obj, unsigned int percent_type,
2491 int (*obj__set_color)(void *obj, int color), 2535 int (*obj__set_color)(void *obj, int color),
2492 void (*obj__set_percent_color)(void *obj, double percent, bool current), 2536 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2493 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current), 2537 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
@@ -2495,7 +2539,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
2495 void (*obj__write_graph)(void *obj, int graph)) 2539 void (*obj__write_graph)(void *obj, int graph))
2496 2540
2497{ 2541{
2498 double percent_max = annotation_line__max_percent(al, notes); 2542 double percent_max = annotation_line__max_percent(al, notes, percent_type);
2499 int pcnt_width = annotation__pcnt_width(notes), 2543 int pcnt_width = annotation__pcnt_width(notes),
2500 cycles_width = annotation__cycles_width(notes); 2544 cycles_width = annotation__cycles_width(notes);
2501 bool show_title = false; 2545 bool show_title = false;
@@ -2514,15 +2558,18 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
2514 int i; 2558 int i;
2515 2559
2516 for (i = 0; i < notes->nr_events; i++) { 2560 for (i = 0; i < notes->nr_events; i++) {
2517 obj__set_percent_color(obj, al->samples[i].percent, current_entry); 2561 double percent;
2562
2563 percent = annotation_data__percent(&al->data[i], percent_type);
2564
2565 obj__set_percent_color(obj, percent, current_entry);
2518 if (notes->options->show_total_period) { 2566 if (notes->options->show_total_period) {
2519 obj__printf(obj, "%11" PRIu64 " ", al->samples[i].he.period); 2567 obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
2520 } else if (notes->options->show_nr_samples) { 2568 } else if (notes->options->show_nr_samples) {
2521 obj__printf(obj, "%6" PRIu64 " ", 2569 obj__printf(obj, "%6" PRIu64 " ",
2522 al->samples[i].he.nr_samples); 2570 al->data[i].he.nr_samples);
2523 } else { 2571 } else {
2524 obj__printf(obj, "%6.2f ", 2572 obj__printf(obj, "%6.2f ", percent);
2525 al->samples[i].percent);
2526 } 2573 }
2527 } 2574 }
2528 } else { 2575 } else {
@@ -2640,13 +2687,15 @@ print_addr:
2640} 2687}
2641 2688
2642void annotation_line__write(struct annotation_line *al, struct annotation *notes, 2689void annotation_line__write(struct annotation_line *al, struct annotation *notes,
2643 struct annotation_write_ops *ops) 2690 struct annotation_write_ops *wops,
2691 struct annotation_options *opts)
2644{ 2692{
2645 __annotation_line__write(al, notes, ops->first_line, ops->current_entry, 2693 __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
2646 ops->change_color, ops->width, ops->obj, 2694 wops->change_color, wops->width, wops->obj,
2647 ops->set_color, ops->set_percent_color, 2695 opts->percent_type,
2648 ops->set_jumps_percent_color, ops->printf, 2696 wops->set_color, wops->set_percent_color,
2649 ops->write_graph); 2697 wops->set_jumps_percent_color, wops->printf,
2698 wops->write_graph);
2650} 2699}
2651 2700
2652int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel, 2701int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
@@ -2688,46 +2737,6 @@ out_free_offsets:
2688 return -1; 2737 return -1;
2689} 2738}
2690 2739
2691int __annotation__scnprintf_samples_period(struct annotation *notes,
2692 char *bf, size_t size,
2693 struct perf_evsel *evsel,
2694 bool show_freq)
2695{
2696 const char *ev_name = perf_evsel__name(evsel);
2697 char buf[1024], ref[30] = " show reference callgraph, ";
2698 char sample_freq_str[64] = "";
2699 unsigned long nr_samples = 0;
2700 int nr_members = 1;
2701 bool enable_ref = false;
2702 u64 nr_events = 0;
2703 char unit;
2704 int i;
2705
2706 if (perf_evsel__is_group_event(evsel)) {
2707 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2708 ev_name = buf;
2709 nr_members = evsel->nr_members;
2710 }
2711
2712 for (i = 0; i < nr_members; i++) {
2713 struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i);
2714
2715 nr_samples += ah->nr_samples;
2716 nr_events += ah->period;
2717 }
2718
2719 if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no"))
2720 enable_ref = true;
2721
2722 if (show_freq)
2723 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2724
2725 nr_samples = convert_unit(nr_samples, &unit);
2726 return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2727 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2728 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2729}
2730
2731#define ANNOTATION__CFG(n) \ 2740#define ANNOTATION__CFG(n) \
2732 { .name = #n, .value = &annotation__default_options.n, } 2741 { .name = #n, .value = &annotation__default_options.n, }
2733 2742
@@ -2792,3 +2801,55 @@ void annotation_config__init(void)
2792 annotation__default_options.show_total_period = symbol_conf.show_total_period; 2801 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2793 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples; 2802 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2794} 2803}
2804
2805static unsigned int parse_percent_type(char *str1, char *str2)
2806{
2807 unsigned int type = (unsigned int) -1;
2808
2809 if (!strcmp("period", str1)) {
2810 if (!strcmp("local", str2))
2811 type = PERCENT_PERIOD_LOCAL;
2812 else if (!strcmp("global", str2))
2813 type = PERCENT_PERIOD_GLOBAL;
2814 }
2815
2816 if (!strcmp("hits", str1)) {
2817 if (!strcmp("local", str2))
2818 type = PERCENT_HITS_LOCAL;
2819 else if (!strcmp("global", str2))
2820 type = PERCENT_HITS_GLOBAL;
2821 }
2822
2823 return type;
2824}
2825
2826int annotate_parse_percent_type(const struct option *opt, const char *_str,
2827 int unset __maybe_unused)
2828{
2829 struct annotation_options *opts = opt->value;
2830 unsigned int type;
2831 char *str1, *str2;
2832 int err = -1;
2833
2834 str1 = strdup(_str);
2835 if (!str1)
2836 return -ENOMEM;
2837
2838 str2 = strchr(str1, '-');
2839 if (!str2)
2840 goto out;
2841
2842 *str2++ = 0;
2843
2844 type = parse_percent_type(str1, str2);
2845 if (type == (unsigned int) -1)
2846 type = parse_percent_type(str2, str1);
2847 if (type != (unsigned int) -1) {
2848 opts->percent_type = type;
2849 err = 0;
2850 }
2851
2852out:
2853 free(str1);
2854 return err;
2855}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index a4c0d91907e6..005a5fe8a8c6 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -11,6 +11,7 @@
11#include <linux/list.h> 11#include <linux/list.h>
12#include <linux/rbtree.h> 12#include <linux/rbtree.h>
13#include <pthread.h> 13#include <pthread.h>
14#include <asm/bug.h>
14 15
15struct ins_ops; 16struct ins_ops;
16 17
@@ -82,6 +83,7 @@ struct annotation_options {
82 int context; 83 int context;
83 const char *objdump_path; 84 const char *objdump_path;
84 const char *disassembler_style; 85 const char *disassembler_style;
86 unsigned int percent_type;
85}; 87};
86 88
87enum { 89enum {
@@ -101,8 +103,16 @@ struct sym_hist_entry {
101 u64 period; 103 u64 period;
102}; 104};
103 105
106enum {
107 PERCENT_HITS_LOCAL,
108 PERCENT_HITS_GLOBAL,
109 PERCENT_PERIOD_LOCAL,
110 PERCENT_PERIOD_GLOBAL,
111 PERCENT_MAX,
112};
113
104struct annotation_data { 114struct annotation_data {
105 double percent; 115 double percent[PERCENT_MAX];
106 double percent_sum; 116 double percent_sum;
107 struct sym_hist_entry he; 117 struct sym_hist_entry he;
108}; 118};
@@ -122,8 +132,8 @@ struct annotation_line {
122 char *path; 132 char *path;
123 u32 idx; 133 u32 idx;
124 int idx_asm; 134 int idx_asm;
125 int samples_nr; 135 int data_nr;
126 struct annotation_data samples[0]; 136 struct annotation_data data[0];
127}; 137};
128 138
129struct disasm_line { 139struct disasm_line {
@@ -134,6 +144,27 @@ struct disasm_line {
134 struct annotation_line al; 144 struct annotation_line al;
135}; 145};
136 146
147static inline double annotation_data__percent(struct annotation_data *data,
148 unsigned int which)
149{
150 return which < PERCENT_MAX ? data->percent[which] : -1;
151}
152
153static inline const char *percent_type_str(unsigned int type)
154{
155 static const char *str[PERCENT_MAX] = {
156 "local hits",
157 "global hits",
158 "local period",
159 "global period",
160 };
161
162 if (WARN_ON(type >= PERCENT_MAX))
163 return "N/A";
164
165 return str[type];
166}
167
137static inline struct disasm_line *disasm_line(struct annotation_line *al) 168static inline struct disasm_line *disasm_line(struct annotation_line *al)
138{ 169{
139 return al ? container_of(al, struct disasm_line, al) : NULL; 170 return al ? container_of(al, struct disasm_line, al) : NULL;
@@ -169,22 +200,15 @@ struct annotation_write_ops {
169 void (*write_graph)(void *obj, int graph); 200 void (*write_graph)(void *obj, int graph);
170}; 201};
171 202
172double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes);
173void annotation_line__write(struct annotation_line *al, struct annotation *notes, 203void annotation_line__write(struct annotation_line *al, struct annotation *notes,
174 struct annotation_write_ops *ops); 204 struct annotation_write_ops *ops,
205 struct annotation_options *opts);
175 206
176int __annotation__scnprintf_samples_period(struct annotation *notes, 207int __annotation__scnprintf_samples_period(struct annotation *notes,
177 char *bf, size_t size, 208 char *bf, size_t size,
178 struct perf_evsel *evsel, 209 struct perf_evsel *evsel,
179 bool show_freq); 210 bool show_freq);
180 211
181static inline int annotation__scnprintf_samples_period(struct annotation *notes,
182 char *bf, size_t size,
183 struct perf_evsel *evsel)
184{
185 return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true);
186}
187
188int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 212int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
189size_t disasm__fprintf(struct list_head *head, FILE *fp); 213size_t disasm__fprintf(struct list_head *head, FILE *fp);
190void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); 214void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
@@ -340,12 +364,12 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
340int symbol__annotate_printf(struct symbol *sym, struct map *map, 364int symbol__annotate_printf(struct symbol *sym, struct map *map,
341 struct perf_evsel *evsel, 365 struct perf_evsel *evsel,
342 struct annotation_options *options); 366 struct annotation_options *options);
343int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
344void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 367void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
345void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 368void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
346void annotated_source__purge(struct annotated_source *as); 369void annotated_source__purge(struct annotated_source *as);
347 370
348int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel); 371int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
372 struct annotation_options *opts);
349 373
350bool ui__has_annotation(void); 374bool ui__has_annotation(void);
351 375
@@ -373,4 +397,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
373 397
374void annotation_config__init(void); 398void annotation_config__init(void);
375 399
400int annotate_parse_percent_type(const struct option *opt, const char *_str,
401 int unset);
376#endif /* __PERF_ANNOTATE_H */ 402#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index d056447520a2..db1511359c5e 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -56,6 +56,7 @@
56#include "intel-pt.h" 56#include "intel-pt.h"
57#include "intel-bts.h" 57#include "intel-bts.h"
58#include "arm-spe.h" 58#include "arm-spe.h"
59#include "s390-cpumsf.h"
59 60
60#include "sane_ctype.h" 61#include "sane_ctype.h"
61#include "symbol/kallsyms.h" 62#include "symbol/kallsyms.h"
@@ -202,6 +203,9 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues,
202 for (i = 0; i < queues->nr_queues; i++) { 203 for (i = 0; i < queues->nr_queues; i++) {
203 list_splice_tail(&queues->queue_array[i].head, 204 list_splice_tail(&queues->queue_array[i].head,
204 &queue_array[i].head); 205 &queue_array[i].head);
206 queue_array[i].tid = queues->queue_array[i].tid;
207 queue_array[i].cpu = queues->queue_array[i].cpu;
208 queue_array[i].set = queues->queue_array[i].set;
205 queue_array[i].priv = queues->queue_array[i].priv; 209 queue_array[i].priv = queues->queue_array[i].priv;
206 } 210 }
207 211
@@ -920,6 +924,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
920 return arm_spe_process_auxtrace_info(event, session); 924 return arm_spe_process_auxtrace_info(event, session);
921 case PERF_AUXTRACE_CS_ETM: 925 case PERF_AUXTRACE_CS_ETM:
922 return cs_etm__process_auxtrace_info(event, session); 926 return cs_etm__process_auxtrace_info(event, session);
927 case PERF_AUXTRACE_S390_CPUMSF:
928 return s390_cpumsf_process_auxtrace_info(event, session);
923 case PERF_AUXTRACE_UNKNOWN: 929 case PERF_AUXTRACE_UNKNOWN:
924 default: 930 default:
925 return -EINVAL; 931 return -EINVAL;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index e731f55da072..71fc3bd74299 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -44,6 +44,7 @@ enum auxtrace_type {
44 PERF_AUXTRACE_INTEL_BTS, 44 PERF_AUXTRACE_INTEL_BTS,
45 PERF_AUXTRACE_CS_ETM, 45 PERF_AUXTRACE_CS_ETM,
46 PERF_AUXTRACE_ARM_SPE, 46 PERF_AUXTRACE_ARM_SPE,
47 PERF_AUXTRACE_S390_CPUMSF,
47}; 48};
48 49
49enum itrace_period_type { 50enum itrace_period_type {
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 3d02ae38ec56..47aac41349a2 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -1529,13 +1529,13 @@ int bpf__apply_obj_config(void)
1529 bpf_object__for_each_safe(obj, objtmp) \ 1529 bpf_object__for_each_safe(obj, objtmp) \
1530 bpf_map__for_each(pos, obj) 1530 bpf_map__for_each(pos, obj)
1531 1531
1532#define bpf__for_each_stdout_map(pos, obj, objtmp) \ 1532#define bpf__for_each_map_named(pos, obj, objtmp, name) \
1533 bpf__for_each_map(pos, obj, objtmp) \ 1533 bpf__for_each_map(pos, obj, objtmp) \
1534 if (bpf_map__name(pos) && \ 1534 if (bpf_map__name(pos) && \
1535 (strcmp("__bpf_stdout__", \ 1535 (strcmp(name, \
1536 bpf_map__name(pos)) == 0)) 1536 bpf_map__name(pos)) == 0))
1537 1537
1538int bpf__setup_stdout(struct perf_evlist *evlist) 1538struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name)
1539{ 1539{
1540 struct bpf_map_priv *tmpl_priv = NULL; 1540 struct bpf_map_priv *tmpl_priv = NULL;
1541 struct bpf_object *obj, *tmp; 1541 struct bpf_object *obj, *tmp;
@@ -1544,11 +1544,11 @@ int bpf__setup_stdout(struct perf_evlist *evlist)
1544 int err; 1544 int err;
1545 bool need_init = false; 1545 bool need_init = false;
1546 1546
1547 bpf__for_each_stdout_map(map, obj, tmp) { 1547 bpf__for_each_map_named(map, obj, tmp, name) {
1548 struct bpf_map_priv *priv = bpf_map__priv(map); 1548 struct bpf_map_priv *priv = bpf_map__priv(map);
1549 1549
1550 if (IS_ERR(priv)) 1550 if (IS_ERR(priv))
1551 return -BPF_LOADER_ERRNO__INTERNAL; 1551 return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL);
1552 1552
1553 /* 1553 /*
1554 * No need to check map type: type should have been 1554 * No need to check map type: type should have been
@@ -1561,49 +1561,61 @@ int bpf__setup_stdout(struct perf_evlist *evlist)
1561 } 1561 }
1562 1562
1563 if (!need_init) 1563 if (!need_init)
1564 return 0; 1564 return NULL;
1565 1565
1566 if (!tmpl_priv) { 1566 if (!tmpl_priv) {
1567 err = parse_events(evlist, "bpf-output/no-inherit=1,name=__bpf_stdout__/", 1567 char *event_definition = NULL;
1568 NULL); 1568
1569 if (asprintf(&event_definition, "bpf-output/no-inherit=1,name=%s/", name) < 0)
1570 return ERR_PTR(-ENOMEM);
1571
1572 err = parse_events(evlist, event_definition, NULL);
1573 free(event_definition);
1574
1569 if (err) { 1575 if (err) {
1570 pr_debug("ERROR: failed to create bpf-output event\n"); 1576 pr_debug("ERROR: failed to create the \"%s\" bpf-output event\n", name);
1571 return -err; 1577 return ERR_PTR(-err);
1572 } 1578 }
1573 1579
1574 evsel = perf_evlist__last(evlist); 1580 evsel = perf_evlist__last(evlist);
1575 } 1581 }
1576 1582
1577 bpf__for_each_stdout_map(map, obj, tmp) { 1583 bpf__for_each_map_named(map, obj, tmp, name) {
1578 struct bpf_map_priv *priv = bpf_map__priv(map); 1584 struct bpf_map_priv *priv = bpf_map__priv(map);
1579 1585
1580 if (IS_ERR(priv)) 1586 if (IS_ERR(priv))
1581 return -BPF_LOADER_ERRNO__INTERNAL; 1587 return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL);
1582 if (priv) 1588 if (priv)
1583 continue; 1589 continue;
1584 1590
1585 if (tmpl_priv) { 1591 if (tmpl_priv) {
1586 priv = bpf_map_priv__clone(tmpl_priv); 1592 priv = bpf_map_priv__clone(tmpl_priv);
1587 if (!priv) 1593 if (!priv)
1588 return -ENOMEM; 1594 return ERR_PTR(-ENOMEM);
1589 1595
1590 err = bpf_map__set_priv(map, priv, bpf_map_priv__clear); 1596 err = bpf_map__set_priv(map, priv, bpf_map_priv__clear);
1591 if (err) { 1597 if (err) {
1592 bpf_map_priv__clear(map, priv); 1598 bpf_map_priv__clear(map, priv);
1593 return err; 1599 return ERR_PTR(err);
1594 } 1600 }
1595 } else if (evsel) { 1601 } else if (evsel) {
1596 struct bpf_map_op *op; 1602 struct bpf_map_op *op;
1597 1603
1598 op = bpf_map__add_newop(map, NULL); 1604 op = bpf_map__add_newop(map, NULL);
1599 if (IS_ERR(op)) 1605 if (IS_ERR(op))
1600 return PTR_ERR(op); 1606 return ERR_PTR(PTR_ERR(op));
1601 op->op_type = BPF_MAP_OP_SET_EVSEL; 1607 op->op_type = BPF_MAP_OP_SET_EVSEL;
1602 op->v.evsel = evsel; 1608 op->v.evsel = evsel;
1603 } 1609 }
1604 } 1610 }
1605 1611
1606 return 0; 1612 return evsel;
1613}
1614
1615int bpf__setup_stdout(struct perf_evlist *evlist)
1616{
1617 struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
1618 return IS_ERR(evsel) ? PTR_ERR(evsel) : 0;
1607} 1619}
1608 1620
1609#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) 1621#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
@@ -1780,8 +1792,8 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
1780 return 0; 1792 return 0;
1781} 1793}
1782 1794
1783int bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused, 1795int bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
1784 int err, char *buf, size_t size) 1796 int err, char *buf, size_t size)
1785{ 1797{
1786 bpf__strerror_head(err, buf, size); 1798 bpf__strerror_head(err, buf, size);
1787 bpf__strerror_end(buf, size); 1799 bpf__strerror_end(buf, size);
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 5d3aefd6fae7..62d245a90e1d 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -43,6 +43,7 @@ enum bpf_loader_errno {
43 __BPF_LOADER_ERRNO__END, 43 __BPF_LOADER_ERRNO__END,
44}; 44};
45 45
46struct perf_evsel;
46struct bpf_object; 47struct bpf_object;
47struct parse_events_term; 48struct parse_events_term;
48#define PERF_BPF_PROBE_GROUP "perf_bpf_probe" 49#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
@@ -82,9 +83,8 @@ int bpf__apply_obj_config(void);
82int bpf__strerror_apply_obj_config(int err, char *buf, size_t size); 83int bpf__strerror_apply_obj_config(int err, char *buf, size_t size);
83 84
84int bpf__setup_stdout(struct perf_evlist *evlist); 85int bpf__setup_stdout(struct perf_evlist *evlist);
85int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err, 86struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name);
86 char *buf, size_t size); 87int bpf__strerror_setup_output_event(struct perf_evlist *evlist, int err, char *buf, size_t size);
87
88#else 88#else
89#include <errno.h> 89#include <errno.h>
90 90
@@ -138,6 +138,12 @@ bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
138 return 0; 138 return 0;
139} 139}
140 140
141static inline struct perf_evsel *
142bpf__setup_output_event(struct perf_evlist *evlist __maybe_unused, const char *name __maybe_unused)
143{
144 return NULL;
145}
146
141static inline int 147static inline int
142__bpf_strerror(char *buf, size_t size) 148__bpf_strerror(char *buf, size_t size)
143{ 149{
@@ -193,11 +199,16 @@ bpf__strerror_apply_obj_config(int err __maybe_unused,
193} 199}
194 200
195static inline int 201static inline int
196bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused, 202bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
197 int err __maybe_unused, char *buf, 203 int err __maybe_unused, char *buf, size_t size)
198 size_t size)
199{ 204{
200 return __bpf_strerror(buf, size); 205 return __bpf_strerror(buf, size);
201} 206}
207
202#endif 208#endif
209
210static inline int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err, char *buf, size_t size)
211{
212 return bpf__strerror_setup_output_event(evlist, err, buf, size);
213}
203#endif 214#endif
diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
index ecca688a25fb..892e92e7e7fc 100644
--- a/tools/perf/util/compress.h
+++ b/tools/perf/util/compress.h
@@ -4,10 +4,12 @@
4 4
5#ifdef HAVE_ZLIB_SUPPORT 5#ifdef HAVE_ZLIB_SUPPORT
6int gzip_decompress_to_file(const char *input, int output_fd); 6int gzip_decompress_to_file(const char *input, int output_fd);
7bool gzip_is_compressed(const char *input);
7#endif 8#endif
8 9
9#ifdef HAVE_LZMA_SUPPORT 10#ifdef HAVE_LZMA_SUPPORT
10int lzma_decompress_to_file(const char *input, int output_fd); 11int lzma_decompress_to_file(const char *input, int output_fd);
12bool lzma_is_compressed(const char *input);
11#endif 13#endif
12 14
13#endif /* PERF_COMPRESS_H */ 15#endif /* PERF_COMPRESS_H */
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 5744c12641a5..abd38abf1d91 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -310,8 +310,8 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
310 if (flags & FIELD_IS_DYNAMIC) { 310 if (flags & FIELD_IS_DYNAMIC) {
311 unsigned long long tmp_val; 311 unsigned long long tmp_val;
312 312
313 tmp_val = pevent_read_number(fmtf->event->pevent, 313 tmp_val = tep_read_number(fmtf->event->pevent,
314 data + offset, len); 314 data + offset, len);
315 offset = tmp_val; 315 offset = tmp_val;
316 len = offset >> 16; 316 len = offset >> 16;
317 offset &= 0xffff; 317 offset &= 0xffff;
@@ -353,7 +353,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
353 else { 353 else {
354 unsigned long long value_int; 354 unsigned long long value_int;
355 355
356 value_int = pevent_read_number( 356 value_int = tep_read_number(
357 fmtf->event->pevent, 357 fmtf->event->pevent,
358 data + offset + i * len, len); 358 data + offset + i * len, len);
359 359
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 51cf82cf1882..bbed90e5d9bb 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -189,28 +189,34 @@ int dso__read_binary_type_filename(const struct dso *dso,
189 return ret; 189 return ret;
190} 190}
191 191
192enum {
193 COMP_ID__NONE = 0,
194};
195
192static const struct { 196static const struct {
193 const char *fmt; 197 const char *fmt;
194 int (*decompress)(const char *input, int output); 198 int (*decompress)(const char *input, int output);
199 bool (*is_compressed)(const char *input);
195} compressions[] = { 200} compressions[] = {
201 [COMP_ID__NONE] = { .fmt = NULL, },
196#ifdef HAVE_ZLIB_SUPPORT 202#ifdef HAVE_ZLIB_SUPPORT
197 { "gz", gzip_decompress_to_file }, 203 { "gz", gzip_decompress_to_file, gzip_is_compressed },
198#endif 204#endif
199#ifdef HAVE_LZMA_SUPPORT 205#ifdef HAVE_LZMA_SUPPORT
200 { "xz", lzma_decompress_to_file }, 206 { "xz", lzma_decompress_to_file, lzma_is_compressed },
201#endif 207#endif
202 { NULL, NULL }, 208 { NULL, NULL, NULL },
203}; 209};
204 210
205bool is_supported_compression(const char *ext) 211static int is_supported_compression(const char *ext)
206{ 212{
207 unsigned i; 213 unsigned i;
208 214
209 for (i = 0; compressions[i].fmt; i++) { 215 for (i = 1; compressions[i].fmt; i++) {
210 if (!strcmp(ext, compressions[i].fmt)) 216 if (!strcmp(ext, compressions[i].fmt))
211 return true; 217 return i;
212 } 218 }
213 return false; 219 return COMP_ID__NONE;
214} 220}
215 221
216bool is_kernel_module(const char *pathname, int cpumode) 222bool is_kernel_module(const char *pathname, int cpumode)
@@ -239,80 +245,73 @@ bool is_kernel_module(const char *pathname, int cpumode)
239 return m.kmod; 245 return m.kmod;
240} 246}
241 247
242bool decompress_to_file(const char *ext, const char *filename, int output_fd)
243{
244 unsigned i;
245
246 for (i = 0; compressions[i].fmt; i++) {
247 if (!strcmp(ext, compressions[i].fmt))
248 return !compressions[i].decompress(filename,
249 output_fd);
250 }
251 return false;
252}
253
254bool dso__needs_decompress(struct dso *dso) 248bool dso__needs_decompress(struct dso *dso)
255{ 249{
256 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || 250 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
257 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; 251 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
258} 252}
259 253
260static int decompress_kmodule(struct dso *dso, const char *name, char *tmpbuf) 254static int decompress_kmodule(struct dso *dso, const char *name,
255 char *pathname, size_t len)
261{ 256{
257 char tmpbuf[] = KMOD_DECOMP_NAME;
262 int fd = -1; 258 int fd = -1;
263 struct kmod_path m;
264 259
265 if (!dso__needs_decompress(dso)) 260 if (!dso__needs_decompress(dso))
266 return -1; 261 return -1;
267 262
268 if (kmod_path__parse_ext(&m, dso->long_name)) 263 if (dso->comp == COMP_ID__NONE)
269 return -1; 264 return -1;
270 265
271 if (!m.comp) 266 /*
272 goto out; 267 * We have proper compression id for DSO and yet the file
268 * behind the 'name' can still be plain uncompressed object.
269 *
270 * The reason is behind the logic we open the DSO object files,
271 * when we try all possible 'debug' objects until we find the
272 * data. So even if the DSO is represented by 'krava.xz' module,
273 * we can end up here opening ~/.debug/....23432432/debug' file
274 * which is not compressed.
275 *
276 * To keep this transparent, we detect this and return the file
277 * descriptor to the uncompressed file.
278 */
279 if (!compressions[dso->comp].is_compressed(name))
280 return open(name, O_RDONLY);
273 281
274 fd = mkstemp(tmpbuf); 282 fd = mkstemp(tmpbuf);
275 if (fd < 0) { 283 if (fd < 0) {
276 dso->load_errno = errno; 284 dso->load_errno = errno;
277 goto out; 285 return -1;
278 } 286 }
279 287
280 if (!decompress_to_file(m.ext, name, fd)) { 288 if (compressions[dso->comp].decompress(name, fd)) {
281 dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE; 289 dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
282 close(fd); 290 close(fd);
283 fd = -1; 291 fd = -1;
284 } 292 }
285 293
286out: 294 if (!pathname || (fd < 0))
287 free(m.ext); 295 unlink(tmpbuf);
296
297 if (pathname && (fd >= 0))
298 strncpy(pathname, tmpbuf, len);
299
288 return fd; 300 return fd;
289} 301}
290 302
291int dso__decompress_kmodule_fd(struct dso *dso, const char *name) 303int dso__decompress_kmodule_fd(struct dso *dso, const char *name)
292{ 304{
293 char tmpbuf[] = KMOD_DECOMP_NAME; 305 return decompress_kmodule(dso, name, NULL, 0);
294 int fd;
295
296 fd = decompress_kmodule(dso, name, tmpbuf);
297 unlink(tmpbuf);
298 return fd;
299} 306}
300 307
301int dso__decompress_kmodule_path(struct dso *dso, const char *name, 308int dso__decompress_kmodule_path(struct dso *dso, const char *name,
302 char *pathname, size_t len) 309 char *pathname, size_t len)
303{ 310{
304 char tmpbuf[] = KMOD_DECOMP_NAME; 311 int fd = decompress_kmodule(dso, name, pathname, len);
305 int fd;
306 312
307 fd = decompress_kmodule(dso, name, tmpbuf);
308 if (fd < 0) {
309 unlink(tmpbuf);
310 return -1;
311 }
312
313 strncpy(pathname, tmpbuf, len);
314 close(fd); 313 close(fd);
315 return 0; 314 return fd >= 0 ? 0 : -1;
316} 315}
317 316
318/* 317/*
@@ -332,7 +331,7 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name,
332 * Returns 0 if there's no strdup error, -ENOMEM otherwise. 331 * Returns 0 if there's no strdup error, -ENOMEM otherwise.
333 */ 332 */
334int __kmod_path__parse(struct kmod_path *m, const char *path, 333int __kmod_path__parse(struct kmod_path *m, const char *path,
335 bool alloc_name, bool alloc_ext) 334 bool alloc_name)
336{ 335{
337 const char *name = strrchr(path, '/'); 336 const char *name = strrchr(path, '/');
338 const char *ext = strrchr(path, '.'); 337 const char *ext = strrchr(path, '.');
@@ -372,10 +371,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
372 return 0; 371 return 0;
373 } 372 }
374 373
375 if (is_supported_compression(ext + 1)) { 374 m->comp = is_supported_compression(ext + 1);
376 m->comp = true; 375 if (m->comp > COMP_ID__NONE)
377 ext -= 3; 376 ext -= 3;
378 }
379 377
380 /* Check .ko extension only if there's enough name left. */ 378 /* Check .ko extension only if there's enough name left. */
381 if (ext > name) 379 if (ext > name)
@@ -393,14 +391,6 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
393 strxfrchar(m->name, '-', '_'); 391 strxfrchar(m->name, '-', '_');
394 } 392 }
395 393
396 if (alloc_ext && m->comp) {
397 m->ext = strdup(ext + 4);
398 if (!m->ext) {
399 free((void *) m->name);
400 return -ENOMEM;
401 }
402 }
403
404 return 0; 394 return 0;
405} 395}
406 396
@@ -413,8 +403,10 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m,
413 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; 403 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
414 404
415 /* _KMODULE_COMP should be next to _KMODULE */ 405 /* _KMODULE_COMP should be next to _KMODULE */
416 if (m->kmod && m->comp) 406 if (m->kmod && m->comp) {
417 dso->symtab_type++; 407 dso->symtab_type++;
408 dso->comp = m->comp;
409 }
418 410
419 dso__set_short_name(dso, strdup(m->name), true); 411 dso__set_short_name(dso, strdup(m->name), true);
420} 412}
@@ -468,6 +460,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
468 int fd = -EINVAL; 460 int fd = -EINVAL;
469 char *root_dir = (char *)""; 461 char *root_dir = (char *)"";
470 char *name = malloc(PATH_MAX); 462 char *name = malloc(PATH_MAX);
463 bool decomp = false;
471 464
472 if (!name) 465 if (!name)
473 return -ENOMEM; 466 return -ENOMEM;
@@ -491,12 +484,13 @@ static int __open_dso(struct dso *dso, struct machine *machine)
491 goto out; 484 goto out;
492 } 485 }
493 486
487 decomp = true;
494 strcpy(name, newpath); 488 strcpy(name, newpath);
495 } 489 }
496 490
497 fd = do_open(name); 491 fd = do_open(name);
498 492
499 if (dso__needs_decompress(dso)) 493 if (decomp)
500 unlink(name); 494 unlink(name);
501 495
502out: 496out:
@@ -1218,6 +1212,7 @@ struct dso *dso__new(const char *name)
1218 dso->a2l_fails = 1; 1212 dso->a2l_fails = 1;
1219 dso->kernel = DSO_TYPE_USER; 1213 dso->kernel = DSO_TYPE_USER;
1220 dso->needs_swap = DSO_SWAP__UNSET; 1214 dso->needs_swap = DSO_SWAP__UNSET;
1215 dso->comp = COMP_ID__NONE;
1221 RB_CLEAR_NODE(&dso->rb_node); 1216 RB_CLEAR_NODE(&dso->rb_node);
1222 dso->root = NULL; 1217 dso->root = NULL;
1223 INIT_LIST_HEAD(&dso->node); 1218 INIT_LIST_HEAD(&dso->node);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ef69de2e69ea..c5380500bed4 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -175,6 +175,7 @@ struct dso {
175 u16 short_name_len; 175 u16 short_name_len;
176 void *dwfl; /* DWARF debug info */ 176 void *dwfl; /* DWARF debug info */
177 struct auxtrace_cache *auxtrace_cache; 177 struct auxtrace_cache *auxtrace_cache;
178 int comp;
178 179
179 /* dso data file */ 180 /* dso data file */
180 struct { 181 struct {
@@ -250,9 +251,7 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
250char dso__symtab_origin(const struct dso *dso); 251char dso__symtab_origin(const struct dso *dso);
251int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 252int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
252 char *root_dir, char *filename, size_t size); 253 char *root_dir, char *filename, size_t size);
253bool is_supported_compression(const char *ext);
254bool is_kernel_module(const char *pathname, int cpumode); 254bool is_kernel_module(const char *pathname, int cpumode);
255bool decompress_to_file(const char *ext, const char *filename, int output_fd);
256bool dso__needs_decompress(struct dso *dso); 255bool dso__needs_decompress(struct dso *dso);
257int dso__decompress_kmodule_fd(struct dso *dso, const char *name); 256int dso__decompress_kmodule_fd(struct dso *dso, const char *name);
258int dso__decompress_kmodule_path(struct dso *dso, const char *name, 257int dso__decompress_kmodule_path(struct dso *dso, const char *name,
@@ -263,17 +262,15 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name,
263 262
264struct kmod_path { 263struct kmod_path {
265 char *name; 264 char *name;
266 char *ext; 265 int comp;
267 bool comp;
268 bool kmod; 266 bool kmod;
269}; 267};
270 268
271int __kmod_path__parse(struct kmod_path *m, const char *path, 269int __kmod_path__parse(struct kmod_path *m, const char *path,
272 bool alloc_name, bool alloc_ext); 270 bool alloc_name);
273 271
274#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false) 272#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false)
275#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) 273#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true)
276#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
277 274
278void dso__set_module_info(struct dso *dso, struct kmod_path *m, 275void dso__set_module_info(struct dso *dso, struct kmod_path *m,
279 struct machine *machine); 276 struct machine *machine);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 0c8ecf0c78a4..0cd42150f712 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -541,10 +541,17 @@ static int __event__synthesize_thread(union perf_event *comm_event,
541 tgid, process, machine) < 0) 541 tgid, process, machine) < 0)
542 return -1; 542 return -1;
543 543
544 /*
545 * send mmap only for thread group leader
546 * see thread__init_map_groups
547 */
548 if (pid == tgid &&
549 perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
550 process, machine, mmap_data,
551 proc_map_timeout))
552 return -1;
544 553
545 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 554 return 0;
546 process, machine, mmap_data,
547 proc_map_timeout);
548 } 555 }
549 556
550 if (machine__is_default_guest(machine)) 557 if (machine__is_default_guest(machine))
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e7a4b31a84fb..be440df29615 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -803,7 +803,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
803 if (*output == -1) { 803 if (*output == -1) {
804 *output = fd; 804 *output = fd;
805 805
806 if (perf_mmap__mmap(&maps[idx], mp, *output) < 0) 806 if (perf_mmap__mmap(&maps[idx], mp, *output, evlist_cpu) < 0)
807 return -1; 807 return -1;
808 } else { 808 } else {
809 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 809 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ddf84b941abf..c980bbff6353 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2683,7 +2683,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
2683 2683
2684struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) 2684struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
2685{ 2685{
2686 return pevent_find_field(evsel->tp_format, name); 2686 return tep_find_field(evsel->tp_format, name);
2687} 2687}
2688 2688
2689void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, 2689void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 973c03167947..163c960614d3 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -452,11 +452,18 @@ static inline int perf_evsel__group_idx(struct perf_evsel *evsel)
452 return evsel->idx - evsel->leader->idx; 452 return evsel->idx - evsel->leader->idx;
453} 453}
454 454
455/* Iterates group WITHOUT the leader. */
455#define for_each_group_member(_evsel, _leader) \ 456#define for_each_group_member(_evsel, _leader) \
456for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \ 457for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
457 (_evsel) && (_evsel)->leader == (_leader); \ 458 (_evsel) && (_evsel)->leader == (_leader); \
458 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) 459 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
459 460
461/* Iterates group WITH the leader. */
462#define for_each_group_evsel(_evsel, _leader) \
463for ((_evsel) = _leader; \
464 (_evsel) && (_evsel)->leader == (_leader); \
465 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
466
460static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel) 467static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel)
461{ 468{
462 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; 469 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 5af58aac91ad..3cadc252dd89 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -279,8 +279,6 @@ static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize)
279 if (!set) 279 if (!set)
280 return -ENOMEM; 280 return -ENOMEM;
281 281
282 bitmap_zero(set, size);
283
284 p = (u64 *) set; 282 p = (u64 *) set;
285 283
286 for (i = 0; (u64) i < BITS_TO_U64(size); i++) { 284 for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
@@ -1285,7 +1283,6 @@ static int memory_node__read(struct memory_node *n, unsigned long idx)
1285 return -ENOMEM; 1283 return -ENOMEM;
1286 } 1284 }
1287 1285
1288 bitmap_zero(n->set, size);
1289 n->node = idx; 1286 n->node = idx;
1290 n->size = size; 1287 n->size = size;
1291 1288
@@ -3207,7 +3204,7 @@ static int read_attr(int fd, struct perf_header *ph,
3207} 3204}
3208 3205
3209static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, 3206static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3210 struct pevent *pevent) 3207 struct tep_handle *pevent)
3211{ 3208{
3212 struct event_format *event; 3209 struct event_format *event;
3213 char bf[128]; 3210 char bf[128];
@@ -3221,7 +3218,7 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3221 return -1; 3218 return -1;
3222 } 3219 }
3223 3220
3224 event = pevent_find_event(pevent, evsel->attr.config); 3221 event = tep_find_event(pevent, evsel->attr.config);
3225 if (event == NULL) { 3222 if (event == NULL) {
3226 pr_debug("cannot find event format for %d\n", (int)evsel->attr.config); 3223 pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
3227 return -1; 3224 return -1;
@@ -3239,7 +3236,7 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3239} 3236}
3240 3237
3241static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, 3238static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
3242 struct pevent *pevent) 3239 struct tep_handle *pevent)
3243{ 3240{
3244 struct perf_evsel *pos; 3241 struct perf_evsel *pos;
3245 3242
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 5e94857dfca2..19262f98cd4e 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -22,12 +22,14 @@
22 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \ 22 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_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 -O2 -o -" 25 "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
26 26
27struct llvm_param llvm_param = { 27struct llvm_param llvm_param = {
28 .clang_path = "clang", 28 .clang_path = "clang",
29 .llc_path = "llc",
29 .clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE, 30 .clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE,
30 .clang_opt = NULL, 31 .clang_opt = NULL,
32 .opts = NULL,
31 .kbuild_dir = NULL, 33 .kbuild_dir = NULL,
32 .kbuild_opts = NULL, 34 .kbuild_opts = NULL,
33 .user_set_param = false, 35 .user_set_param = false,
@@ -51,6 +53,8 @@ int perf_llvm_config(const char *var, const char *value)
51 llvm_param.kbuild_opts = strdup(value); 53 llvm_param.kbuild_opts = strdup(value);
52 else if (!strcmp(var, "dump-obj")) 54 else if (!strcmp(var, "dump-obj"))
53 llvm_param.dump_obj = !!perf_config_bool(var, value); 55 llvm_param.dump_obj = !!perf_config_bool(var, value);
56 else if (!strcmp(var, "opts"))
57 llvm_param.opts = strdup(value);
54 else { 58 else {
55 pr_debug("Invalid LLVM config option: %s\n", value); 59 pr_debug("Invalid LLVM config option: %s\n", value);
56 return -1; 60 return -1;
@@ -430,11 +434,13 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
430 unsigned int kernel_version; 434 unsigned int kernel_version;
431 char linux_version_code_str[64]; 435 char linux_version_code_str[64];
432 const char *clang_opt = llvm_param.clang_opt; 436 const char *clang_opt = llvm_param.clang_opt;
433 char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64]; 437 char clang_path[PATH_MAX], llc_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
434 char serr[STRERR_BUFSIZE]; 438 char serr[STRERR_BUFSIZE];
435 char *kbuild_dir = NULL, *kbuild_include_opts = NULL, 439 char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
436 *perf_bpf_include_opts = NULL; 440 *perf_bpf_include_opts = NULL;
437 const char *template = llvm_param.clang_bpf_cmd_template; 441 const char *template = llvm_param.clang_bpf_cmd_template;
442 char *pipe_template = NULL;
443 const char *opts = llvm_param.opts;
438 char *command_echo = NULL, *command_out; 444 char *command_echo = NULL, *command_out;
439 char *perf_include_dir = system_path(PERF_INCLUDE_DIR); 445 char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
440 446
@@ -484,6 +490,26 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
484 force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts); 490 force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
485 force_set_env("WORKING_DIR", kbuild_dir ? : "."); 491 force_set_env("WORKING_DIR", kbuild_dir ? : ".");
486 492
493 if (opts) {
494 err = search_program(llvm_param.llc_path, "llc", llc_path);
495 if (err) {
496 pr_err("ERROR:\tunable to find llc.\n"
497 "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
498 " \tand 'llc-path' option in [llvm] section of ~/.perfconfig.\n");
499 version_notice();
500 goto errout;
501 }
502
503 if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
504 template, llc_path, opts) < 0) {
505 pr_err("ERROR:\tnot enough memory to setup command line\n");
506 goto errout;
507 }
508
509 template = pipe_template;
510
511 }
512
487 /* 513 /*
488 * Since we may reset clang's working dir, path of source file 514 * Since we may reset clang's working dir, path of source file
489 * should be transferred into absolute path, except we want 515 * should be transferred into absolute path, except we want
@@ -535,6 +561,7 @@ errout:
535 free(obj_buf); 561 free(obj_buf);
536 free(perf_bpf_include_opts); 562 free(perf_bpf_include_opts);
537 free(perf_include_dir); 563 free(perf_include_dir);
564 free(pipe_template);
538 if (p_obj_buf) 565 if (p_obj_buf)
539 *p_obj_buf = NULL; 566 *p_obj_buf = NULL;
540 if (p_obj_buf_sz) 567 if (p_obj_buf_sz)
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index d3ad8deb5db4..bf3f3f4c4fe2 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -11,6 +11,8 @@
11struct llvm_param { 11struct llvm_param {
12 /* Path of clang executable */ 12 /* Path of clang executable */
13 const char *clang_path; 13 const char *clang_path;
14 /* Path of llc executable */
15 const char *llc_path;
14 /* 16 /*
15 * Template of clang bpf compiling. 5 env variables 17 * Template of clang bpf compiling. 5 env variables
16 * can be used: 18 * can be used:
@@ -23,6 +25,13 @@ struct llvm_param {
23 const char *clang_bpf_cmd_template; 25 const char *clang_bpf_cmd_template;
24 /* Will be filled in $CLANG_OPTIONS */ 26 /* Will be filled in $CLANG_OPTIONS */
25 const char *clang_opt; 27 const char *clang_opt;
28 /*
29 * If present it'll add -emit-llvm to $CLANG_OPTIONS to pipe
30 * the clang output to llc, useful for new llvm options not
31 * yet selectable via 'clang -mllvm option', such as -mattr=dwarfris
32 * in clang 6.0/llvm 7
33 */
34 const char *opts;
26 /* Where to find kbuild system */ 35 /* Where to find kbuild system */
27 const char *kbuild_dir; 36 const char *kbuild_dir;
28 /* 37 /*
diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c
index 07498eaddc08..b1dd29a9d915 100644
--- a/tools/perf/util/lzma.c
+++ b/tools/perf/util/lzma.c
@@ -3,9 +3,13 @@
3#include <lzma.h> 3#include <lzma.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
6#include "compress.h" 9#include "compress.h"
7#include "util.h" 10#include "util.h"
8#include "debug.h" 11#include "debug.h"
12#include <unistd.h>
9 13
10#define BUFSIZE 8192 14#define BUFSIZE 8192
11 15
@@ -99,3 +103,19 @@ err_fclose:
99 fclose(infile); 103 fclose(infile);
100 return err; 104 return err;
101} 105}
106
107bool lzma_is_compressed(const char *input)
108{
109 int fd = open(input, O_RDONLY);
110 const uint8_t magic[6] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
111 char buf[6] = { 0 };
112 ssize_t rc;
113
114 if (fd < 0)
115 return -1;
116
117 rc = read(fd, buf, sizeof(buf));
118 close(fd);
119 return rc == sizeof(buf) ?
120 memcmp(buf, magic, sizeof(buf)) == 0 : false;
121}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b300a3973448..c4acd2001db0 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1212,8 +1212,10 @@ static int map_groups__set_module_path(struct map_groups *mg, const char *path,
1212 * Full name could reveal us kmod compression, so 1212 * Full name could reveal us kmod compression, so
1213 * we need to update the symtab_type if needed. 1213 * we need to update the symtab_type if needed.
1214 */ 1214 */
1215 if (m->comp && is_kmod_dso(map->dso)) 1215 if (m->comp && is_kmod_dso(map->dso)) {
1216 map->dso->symtab_type++; 1216 map->dso->symtab_type++;
1217 map->dso->comp = m->comp;
1218 }
1217 1219
1218 return 0; 1220 return 0;
1219} 1221}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 1de7660d93e9..d856b85862e2 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -265,7 +265,7 @@ pid_t machine__get_current_tid(struct machine *machine, int cpu);
265int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid, 265int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
266 pid_t tid); 266 pid_t tid);
267/* 267/*
268 * For use with libtraceevent's pevent_set_function_resolver() 268 * For use with libtraceevent's tep_set_function_resolver()
269 */ 269 */
270char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp); 270char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp);
271 271
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 89ac5b5dc218..36d0763311ef 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -381,20 +381,6 @@ struct map *map__clone(struct map *from)
381 return map; 381 return map;
382} 382}
383 383
384int map__overlap(struct map *l, struct map *r)
385{
386 if (l->start > r->start) {
387 struct map *t = l;
388 l = r;
389 r = t;
390 }
391
392 if (l->end > r->start)
393 return 1;
394
395 return 0;
396}
397
398size_t map__fprintf(struct map *map, FILE *fp) 384size_t map__fprintf(struct map *map, FILE *fp)
399{ 385{
400 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n", 386 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
@@ -675,20 +661,42 @@ static void __map_groups__insert(struct map_groups *mg, struct map *map)
675static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 661static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
676{ 662{
677 struct rb_root *root; 663 struct rb_root *root;
678 struct rb_node *next; 664 struct rb_node *next, *first;
679 int err = 0; 665 int err = 0;
680 666
681 down_write(&maps->lock); 667 down_write(&maps->lock);
682 668
683 root = &maps->entries; 669 root = &maps->entries;
684 next = rb_first(root);
685 670
671 /*
672 * Find first map where end > map->start.
673 * Same as find_vma() in kernel.
674 */
675 next = root->rb_node;
676 first = NULL;
677 while (next) {
678 struct map *pos = rb_entry(next, struct map, rb_node);
679
680 if (pos->end > map->start) {
681 first = next;
682 if (pos->start <= map->start)
683 break;
684 next = next->rb_left;
685 } else
686 next = next->rb_right;
687 }
688
689 next = first;
686 while (next) { 690 while (next) {
687 struct map *pos = rb_entry(next, struct map, rb_node); 691 struct map *pos = rb_entry(next, struct map, rb_node);
688 next = rb_next(&pos->rb_node); 692 next = rb_next(&pos->rb_node);
689 693
690 if (!map__overlap(pos, map)) 694 /*
691 continue; 695 * Stop if current map starts after map->end.
696 * Maps are ordered by start: next will not overlap for sure.
697 */
698 if (pos->start >= map->end)
699 break;
692 700
693 if (verbose >= 2) { 701 if (verbose >= 2) {
694 702
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 4cb90f242bed..e0f327b51e66 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -166,7 +166,6 @@ static inline void __map__zput(struct map **map)
166 166
167#define map__zput(map) __map__zput(&map) 167#define map__zput(map) __map__zput(&map)
168 168
169int map__overlap(struct map *l, struct map *r);
170size_t map__fprintf(struct map *map, FILE *fp); 169size_t map__fprintf(struct map *map, FILE *fp);
171size_t map__fprintf_dsoname(struct map *map, FILE *fp); 170size_t map__fprintf_dsoname(struct map *map, FILE *fp);
172char *map__srcline(struct map *map, u64 addr, struct symbol *sym); 171char *map__srcline(struct map *map, u64 addr, struct symbol *sym);
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index fc832676a798..215f69f41672 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -164,7 +164,7 @@ void perf_mmap__munmap(struct perf_mmap *map)
164 auxtrace_mmap__munmap(&map->auxtrace_mmap); 164 auxtrace_mmap__munmap(&map->auxtrace_mmap);
165} 165}
166 166
167int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd) 167int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int cpu)
168{ 168{
169 /* 169 /*
170 * The last one will be done at perf_mmap__consume(), so that we 170 * The last one will be done at perf_mmap__consume(), so that we
@@ -191,6 +191,7 @@ int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
191 return -1; 191 return -1;
192 } 192 }
193 map->fd = fd; 193 map->fd = fd;
194 map->cpu = cpu;
194 195
195 if (auxtrace_mmap__mmap(&map->auxtrace_mmap, 196 if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
196 &mp->auxtrace_mp, map->base, fd)) 197 &mp->auxtrace_mp, map->base, fd))
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index d82294db1295..05a6d47c7956 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -18,6 +18,7 @@ struct perf_mmap {
18 void *base; 18 void *base;
19 int mask; 19 int mask;
20 int fd; 20 int fd;
21 int cpu;
21 refcount_t refcnt; 22 refcount_t refcnt;
22 u64 prev; 23 u64 prev;
23 u64 start; 24 u64 start;
@@ -60,7 +61,7 @@ struct mmap_params {
60 struct auxtrace_mmap_params auxtrace_mp; 61 struct auxtrace_mmap_params auxtrace_mp;
61}; 62};
62 63
63int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd); 64int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int cpu);
64void perf_mmap__munmap(struct perf_mmap *map); 65void perf_mmap__munmap(struct perf_mmap *map);
65 66
66void perf_mmap__get(struct perf_mmap *map); 67void perf_mmap__get(struct perf_mmap *map);
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index 5be021701f34..cf8bd123cf73 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -139,6 +139,9 @@ struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
139{ 139{
140 struct nsinfo *nnsi; 140 struct nsinfo *nnsi;
141 141
142 if (nsi == NULL)
143 return NULL;
144
142 nnsi = calloc(1, sizeof(*nnsi)); 145 nnsi = calloc(1, sizeof(*nnsi));
143 if (nnsi != NULL) { 146 if (nnsi != NULL) {
144 nnsi->pid = nsi->pid; 147 nnsi->pid = nsi->pid;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 15eec49e71a1..f8cd3e7c9186 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1991,8 +1991,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
1991 int nr_addr_filters = 0; 1991 int nr_addr_filters = 0;
1992 struct perf_pmu *pmu = NULL; 1992 struct perf_pmu *pmu = NULL;
1993 1993
1994 if (evsel == NULL) 1994 if (evsel == NULL) {
1995 goto err; 1995 fprintf(stderr,
1996 "--filter option should follow a -e tracepoint or HW tracer option\n");
1997 return -1;
1998 }
1996 1999
1997 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { 2000 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
1998 if (perf_evsel__append_tp_filter(evsel, str) < 0) { 2001 if (perf_evsel__append_tp_filter(evsel, str) < 0) {
@@ -2014,8 +2017,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
2014 perf_pmu__scan_file(pmu, "nr_addr_filters", 2017 perf_pmu__scan_file(pmu, "nr_addr_filters",
2015 "%d", &nr_addr_filters); 2018 "%d", &nr_addr_filters);
2016 2019
2017 if (!nr_addr_filters) 2020 if (!nr_addr_filters) {
2018 goto err; 2021 fprintf(stderr,
2022 "This CPU does not support address filtering\n");
2023 return -1;
2024 }
2019 2025
2020 if (perf_evsel__append_addr_filter(evsel, str) < 0) { 2026 if (perf_evsel__append_addr_filter(evsel, str) < 0) {
2021 fprintf(stderr, 2027 fprintf(stderr,
@@ -2024,12 +2030,6 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
2024 } 2030 }
2025 2031
2026 return 0; 2032 return 0;
2027
2028err:
2029 fprintf(stderr,
2030 "--filter option should follow a -e tracepoint or HW tracer option\n");
2031
2032 return -1;
2033} 2033}
2034 2034
2035int parse_filter(const struct option *opt, const char *str, 2035int parse_filter(const struct option *opt, const char *str,
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 863b61478edd..ce501ba14b08 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -11,6 +11,7 @@
11#include "cpumap.h" 11#include "cpumap.h"
12#include "print_binary.h" 12#include "print_binary.h"
13#include "thread_map.h" 13#include "thread_map.h"
14#include "mmap.h"
14 15
15#if PY_MAJOR_VERSION < 3 16#if PY_MAJOR_VERSION < 3
16#define _PyUnicode_FromString(arg) \ 17#define _PyUnicode_FromString(arg) \
@@ -341,7 +342,7 @@ static bool is_tracepoint(struct pyrf_event *pevent)
341static PyObject* 342static PyObject*
342tracepoint_field(struct pyrf_event *pe, struct format_field *field) 343tracepoint_field(struct pyrf_event *pe, struct format_field *field)
343{ 344{
344 struct pevent *pevent = field->event->pevent; 345 struct tep_handle *pevent = field->event->pevent;
345 void *data = pe->sample.raw_data; 346 void *data = pe->sample.raw_data;
346 PyObject *ret = NULL; 347 PyObject *ret = NULL;
347 unsigned long long val; 348 unsigned long long val;
@@ -351,7 +352,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
351 offset = field->offset; 352 offset = field->offset;
352 len = field->size; 353 len = field->size;
353 if (field->flags & FIELD_IS_DYNAMIC) { 354 if (field->flags & FIELD_IS_DYNAMIC) {
354 val = pevent_read_number(pevent, data + offset, len); 355 val = tep_read_number(pevent, data + offset, len);
355 offset = val; 356 offset = val;
356 len = offset >> 16; 357 len = offset >> 16;
357 offset &= 0xffff; 358 offset &= 0xffff;
@@ -364,8 +365,8 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
364 field->flags &= ~FIELD_IS_STRING; 365 field->flags &= ~FIELD_IS_STRING;
365 } 366 }
366 } else { 367 } else {
367 val = pevent_read_number(pevent, data + field->offset, 368 val = tep_read_number(pevent, data + field->offset,
368 field->size); 369 field->size);
369 if (field->flags & FIELD_IS_POINTER) 370 if (field->flags & FIELD_IS_POINTER)
370 ret = PyLong_FromUnsignedLong((unsigned long) val); 371 ret = PyLong_FromUnsignedLong((unsigned long) val);
371 else if (field->flags & FIELD_IS_SIGNED) 372 else if (field->flags & FIELD_IS_SIGNED)
@@ -394,7 +395,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
394 evsel->tp_format = tp_format; 395 evsel->tp_format = tp_format;
395 } 396 }
396 397
397 field = pevent_find_any_field(evsel->tp_format, str); 398 field = tep_find_any_field(evsel->tp_format, str);
398 if (!field) 399 if (!field)
399 return NULL; 400 return NULL;
400 401
@@ -976,6 +977,20 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
976 return Py_BuildValue("i", evlist->nr_entries); 977 return Py_BuildValue("i", evlist->nr_entries);
977} 978}
978 979
980static struct perf_mmap *get_md(struct perf_evlist *evlist, int cpu)
981{
982 int i;
983
984 for (i = 0; i < evlist->nr_mmaps; i++) {
985 struct perf_mmap *md = &evlist->mmap[i];
986
987 if (md->cpu == cpu)
988 return md;
989 }
990
991 return NULL;
992}
993
979static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, 994static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
980 PyObject *args, PyObject *kwargs) 995 PyObject *args, PyObject *kwargs)
981{ 996{
@@ -990,7 +1005,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
990 &cpu, &sample_id_all)) 1005 &cpu, &sample_id_all))
991 return NULL; 1006 return NULL;
992 1007
993 md = &evlist->mmap[cpu]; 1008 md = get_md(evlist, cpu);
1009 if (!md)
1010 return NULL;
1011
994 if (perf_mmap__read_init(md) < 0) 1012 if (perf_mmap__read_init(md) < 0)
995 goto end; 1013 goto end;
996 1014
diff --git a/tools/perf/util/s390-cpumsf-kernel.h b/tools/perf/util/s390-cpumsf-kernel.h
new file mode 100644
index 000000000000..de8c7ad0eca8
--- /dev/null
+++ b/tools/perf/util/s390-cpumsf-kernel.h
@@ -0,0 +1,71 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Auxtrace support for s390 CPU measurement sampling facility
4 *
5 * Copyright IBM Corp. 2018
6 * Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
7 * Thomas Richter <tmricht@linux.ibm.com>
8 */
9#ifndef S390_CPUMSF_KERNEL_H
10#define S390_CPUMSF_KERNEL_H
11
12#define S390_CPUMSF_PAGESZ 4096 /* Size of sample block units */
13#define S390_CPUMSF_DIAG_DEF_FIRST 0x8001 /* Diagnostic entry lowest id */
14
15struct hws_basic_entry {
16 unsigned int def:16; /* 0-15 Data Entry Format */
17 unsigned int R:4; /* 16-19 reserved */
18 unsigned int U:4; /* 20-23 Number of unique instruct. */
19 unsigned int z:2; /* zeros */
20 unsigned int T:1; /* 26 PSW DAT mode */
21 unsigned int W:1; /* 27 PSW wait state */
22 unsigned int P:1; /* 28 PSW Problem state */
23 unsigned int AS:2; /* 29-30 PSW address-space control */
24 unsigned int I:1; /* 31 entry valid or invalid */
25 unsigned int CL:2; /* 32-33 Configuration Level */
26 unsigned int:14;
27 unsigned int prim_asn:16; /* primary ASN */
28 unsigned long long ia; /* Instruction Address */
29 unsigned long long gpp; /* Guest Program Parameter */
30 unsigned long long hpp; /* Host Program Parameter */
31};
32
33struct hws_diag_entry {
34 unsigned int def:16; /* 0-15 Data Entry Format */
35 unsigned int R:15; /* 16-19 and 20-30 reserved */
36 unsigned int I:1; /* 31 entry valid or invalid */
37 u8 data[]; /* Machine-dependent sample data */
38};
39
40struct hws_combined_entry {
41 struct hws_basic_entry basic; /* Basic-sampling data entry */
42 struct hws_diag_entry diag; /* Diagnostic-sampling data entry */
43};
44
45struct hws_trailer_entry {
46 union {
47 struct {
48 unsigned int f:1; /* 0 - Block Full Indicator */
49 unsigned int a:1; /* 1 - Alert request control */
50 unsigned int t:1; /* 2 - Timestamp format */
51 unsigned int:29; /* 3 - 31: Reserved */
52 unsigned int bsdes:16; /* 32-47: size of basic SDE */
53 unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */
54 };
55 unsigned long long flags; /* 0 - 64: All indicators */
56 };
57 unsigned long long overflow; /* 64 - sample Overflow count */
58 unsigned char timestamp[16]; /* 16 - 31 timestamp */
59 unsigned long long reserved1; /* 32 -Reserved */
60 unsigned long long reserved2; /* */
61 union { /* 48 - reserved for programming use */
62 struct {
63 unsigned long long clock_base:1; /* in progusage2 */
64 unsigned long long progusage1:63;
65 unsigned long long progusage2;
66 };
67 unsigned long long progusage[2];
68 };
69};
70
71#endif
diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c
new file mode 100644
index 000000000000..d2c78ffd9fee
--- /dev/null
+++ b/tools/perf/util/s390-cpumsf.c
@@ -0,0 +1,945 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright IBM Corp. 2018
4 * Auxtrace support for s390 CPU-Measurement Sampling Facility
5 *
6 * Author(s): Thomas Richter <tmricht@linux.ibm.com>
7 *
8 * Auxiliary traces are collected during 'perf record' using rbd000 event.
9 * Several PERF_RECORD_XXX are generated during recording:
10 *
11 * PERF_RECORD_AUX:
12 * Records that new data landed in the AUX buffer part.
13 * PERF_RECORD_AUXTRACE:
14 * Defines auxtrace data. Followed by the actual data. The contents of
15 * the auxtrace data is dependent on the event and the CPU.
16 * This record is generated by perf record command. For details
17 * see Documentation/perf.data-file-format.txt.
18 * PERF_RECORD_AUXTRACE_INFO:
19 * Defines a table of contains for PERF_RECORD_AUXTRACE records. This
20 * record is generated during 'perf record' command. Each record contains up
21 * to 256 entries describing offset and size of the AUXTRACE data in the
22 * perf.data file.
23 * PERF_RECORD_AUXTRACE_ERROR:
24 * Indicates an error during AUXTRACE collection such as buffer overflow.
25 * PERF_RECORD_FINISHED_ROUND:
26 * Perf events are not necessarily in time stamp order, as they can be
27 * collected in parallel on different CPUs. If the events should be
28 * processed in time order they need to be sorted first.
29 * Perf report guarantees that there is no reordering over a
30 * PERF_RECORD_FINISHED_ROUND boundary event. All perf records with a
31 * time stamp lower than this record are processed (and displayed) before
32 * the succeeding perf record are processed.
33 *
34 * These records are evaluated during perf report command.
35 *
36 * 1. PERF_RECORD_AUXTRACE_INFO is used to set up the infrastructure for
37 * auxiliary trace data processing. See s390_cpumsf_process_auxtrace_info()
38 * below.
39 * Auxiliary trace data is collected per CPU. To merge the data into the report
40 * an auxtrace_queue is created for each CPU. It is assumed that the auxtrace
41 * data is in ascending order.
42 *
43 * Each queue has a double linked list of auxtrace_buffers. This list contains
44 * the offset and size of a CPU's auxtrace data. During auxtrace processing
45 * the data portion is mmap()'ed.
46 *
47 * To sort the queues in chronological order, all queue access is controlled
48 * by the auxtrace_heap. This is basicly a stack, each stack element has two
49 * entries, the queue number and a time stamp. However the stack is sorted by
50 * the time stamps. The highest time stamp is at the bottom the lowest
51 * (nearest) time stamp is at the top. That sort order is maintained at all
52 * times!
53 *
54 * After the auxtrace infrastructure has been setup, the auxtrace queues are
55 * filled with data (offset/size pairs) and the auxtrace_heap is populated.
56 *
57 * 2. PERF_RECORD_XXX processing triggers access to the auxtrace_queues.
58 * Each record is handled by s390_cpumsf_process_event(). The time stamp of
59 * the perf record is compared with the time stamp located on the auxtrace_heap
60 * top element. If that time stamp is lower than the time stamp from the
61 * record sample, the auxtrace queues will be processed. As auxtrace queues
62 * control many auxtrace_buffers and each buffer can be quite large, the
63 * auxtrace buffer might be processed only partially. In this case the
64 * position in the auxtrace_buffer of that queue is remembered and the time
65 * stamp of the last processed entry of the auxtrace_buffer replaces the
66 * current auxtrace_heap top.
67 *
68 * 3. Auxtrace_queues might run of out data and are feeded by the
69 * PERF_RECORD_AUXTRACE handling, see s390_cpumsf_process_auxtrace_event().
70 *
71 * Event Generation
72 * Each sampling-data entry in the auxilary trace data generates a perf sample.
73 * This sample is filled
74 * with data from the auxtrace such as PID/TID, instruction address, CPU state,
75 * etc. This sample is processed with perf_session__deliver_synth_event() to
76 * be included into the GUI.
77 *
78 * 4. PERF_RECORD_FINISHED_ROUND event is used to process all the remaining
79 * auxiliary traces entries until the time stamp of this record is reached
80 * auxtrace_heap top. This is triggered by ordered_event->deliver().
81 *
82 *
83 * Perf event processing.
84 * Event processing of PERF_RECORD_XXX entries relies on time stamp entries.
85 * This is the function call sequence:
86 *
87 * __cmd_report()
88 * |
89 * perf_session__process_events()
90 * |
91 * __perf_session__process_events()
92 * |
93 * perf_session__process_event()
94 * | This functions splits the PERF_RECORD_XXX records.
95 * | - Those generated by perf record command (type number equal or higher
96 * | than PERF_RECORD_USER_TYPE_START) are handled by
97 * | perf_session__process_user_event(see below)
98 * | - Those generated by the kernel are handled by
99 * | perf_evlist__parse_sample_timestamp()
100 * |
101 * perf_evlist__parse_sample_timestamp()
102 * | Extract time stamp from sample data.
103 * |
104 * perf_session__queue_event()
105 * | If timestamp is positive the sample is entered into an ordered_event
106 * | list, sort order is the timestamp. The event processing is deferred until
107 * | later (see perf_session__process_user_event()).
108 * | Other timestamps (0 or -1) are handled immediately by
109 * | perf_session__deliver_event(). These are events generated at start up
110 * | of command perf record. They create PERF_RECORD_COMM and PERF_RECORD_MMAP*
111 * | records. They are needed to create a list of running processes and its
112 * | memory mappings and layout. They are needed at the beginning to enable
113 * | command perf report to create process trees and memory mappings.
114 * |
115 * perf_session__deliver_event()
116 * | Delivers a PERF_RECORD_XXX entry for handling.
117 * |
118 * auxtrace__process_event()
119 * | The timestamp of the PERF_RECORD_XXX entry is taken to correlate with
120 * | time stamps from the auxiliary trace buffers. This enables
121 * | synchronization between auxiliary trace data and the events on the
122 * | perf.data file.
123 * |
124 * machine__deliver_event()
125 * | Handles the PERF_RECORD_XXX event. This depends on the record type.
126 * It might update the process tree, update a process memory map or enter
127 * a sample with IP and call back chain data into GUI data pool.
128 *
129 *
130 * Deferred processing determined by perf_session__process_user_event() is
131 * finally processed when a PERF_RECORD_FINISHED_ROUND is encountered. These
132 * are generated during command perf record.
133 * The timestamp of PERF_RECORD_FINISHED_ROUND event is taken to process all
134 * PERF_RECORD_XXX entries stored in the ordered_event list. This list was
135 * built up while reading the perf.data file.
136 * Each event is now processed by calling perf_session__deliver_event().
137 * This enables time synchronization between the data in the perf.data file and
138 * the data in the auxiliary trace buffers.
139 */
140
141#include <endian.h>
142#include <errno.h>
143#include <byteswap.h>
144#include <inttypes.h>
145#include <linux/kernel.h>
146#include <linux/types.h>
147#include <linux/bitops.h>
148#include <linux/log2.h>
149
150#include "cpumap.h"
151#include "color.h"
152#include "evsel.h"
153#include "evlist.h"
154#include "machine.h"
155#include "session.h"
156#include "util.h"
157#include "thread.h"
158#include "debug.h"
159#include "auxtrace.h"
160#include "s390-cpumsf.h"
161#include "s390-cpumsf-kernel.h"
162
163struct s390_cpumsf {
164 struct auxtrace auxtrace;
165 struct auxtrace_queues queues;
166 struct auxtrace_heap heap;
167 struct perf_session *session;
168 struct machine *machine;
169 u32 auxtrace_type;
170 u32 pmu_type;
171 u16 machine_type;
172 bool data_queued;
173};
174
175struct s390_cpumsf_queue {
176 struct s390_cpumsf *sf;
177 unsigned int queue_nr;
178 struct auxtrace_buffer *buffer;
179 int cpu;
180};
181
182/* Display s390 CPU measurement facility basic-sampling data entry */
183static bool s390_cpumsf_basic_show(const char *color, size_t pos,
184 struct hws_basic_entry *basic)
185{
186 if (basic->def != 1) {
187 pr_err("Invalid AUX trace basic entry [%#08zx]\n", pos);
188 return false;
189 }
190 color_fprintf(stdout, color, " [%#08zx] Basic Def:%04x Inst:%#04x"
191 " %c%c%c%c AS:%d ASN:%#04x IA:%#018llx\n"
192 "\t\tCL:%d HPP:%#018llx GPP:%#018llx\n",
193 pos, basic->def, basic->U,
194 basic->T ? 'T' : ' ',
195 basic->W ? 'W' : ' ',
196 basic->P ? 'P' : ' ',
197 basic->I ? 'I' : ' ',
198 basic->AS, basic->prim_asn, basic->ia, basic->CL,
199 basic->hpp, basic->gpp);
200 return true;
201}
202
203/* Display s390 CPU measurement facility diagnostic-sampling data entry */
204static bool s390_cpumsf_diag_show(const char *color, size_t pos,
205 struct hws_diag_entry *diag)
206{
207 if (diag->def < S390_CPUMSF_DIAG_DEF_FIRST) {
208 pr_err("Invalid AUX trace diagnostic entry [%#08zx]\n", pos);
209 return false;
210 }
211 color_fprintf(stdout, color, " [%#08zx] Diag Def:%04x %c\n",
212 pos, diag->def, diag->I ? 'I' : ' ');
213 return true;
214}
215
216/* Return TOD timestamp contained in an trailer entry */
217static unsigned long long trailer_timestamp(struct hws_trailer_entry *te)
218{
219 /* te->t set: TOD in STCKE format, bytes 8-15
220 * to->t not set: TOD in STCK format, bytes 0-7
221 */
222 unsigned long long ts;
223
224 memcpy(&ts, &te->timestamp[te->t], sizeof(ts));
225 return ts;
226}
227
228/* Display s390 CPU measurement facility trailer entry */
229static bool s390_cpumsf_trailer_show(const char *color, size_t pos,
230 struct hws_trailer_entry *te)
231{
232 if (te->bsdes != sizeof(struct hws_basic_entry)) {
233 pr_err("Invalid AUX trace trailer entry [%#08zx]\n", pos);
234 return false;
235 }
236 color_fprintf(stdout, color, " [%#08zx] Trailer %c%c%c bsdes:%d"
237 " dsdes:%d Overflow:%lld Time:%#llx\n"
238 "\t\tC:%d TOD:%#lx 1:%#llx 2:%#llx\n",
239 pos,
240 te->f ? 'F' : ' ',
241 te->a ? 'A' : ' ',
242 te->t ? 'T' : ' ',
243 te->bsdes, te->dsdes, te->overflow,
244 trailer_timestamp(te), te->clock_base, te->progusage2,
245 te->progusage[0], te->progusage[1]);
246 return true;
247}
248
249/* Test a sample data block. It must be 4KB or a multiple thereof in size and
250 * 4KB page aligned. Each sample data page has a trailer entry at the
251 * end which contains the sample entry data sizes.
252 *
253 * Return true if the sample data block passes the checks and set the
254 * basic set entry size and diagnostic set entry size.
255 *
256 * Return false on failure.
257 *
258 * Note: Old hardware does not set the basic or diagnostic entry sizes
259 * in the trailer entry. Use the type number instead.
260 */
261static bool s390_cpumsf_validate(int machine_type,
262 unsigned char *buf, size_t len,
263 unsigned short *bsdes,
264 unsigned short *dsdes)
265{
266 struct hws_basic_entry *basic = (struct hws_basic_entry *)buf;
267 struct hws_trailer_entry *te;
268
269 *dsdes = *bsdes = 0;
270 if (len & (S390_CPUMSF_PAGESZ - 1)) /* Illegal size */
271 return false;
272 if (basic->def != 1) /* No basic set entry, must be first */
273 return false;
274 /* Check for trailer entry at end of SDB */
275 te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ
276 - sizeof(*te));
277 *bsdes = te->bsdes;
278 *dsdes = te->dsdes;
279 if (!te->bsdes && !te->dsdes) {
280 /* Very old hardware, use CPUID */
281 switch (machine_type) {
282 case 2097:
283 case 2098:
284 *dsdes = 64;
285 *bsdes = 32;
286 break;
287 case 2817:
288 case 2818:
289 *dsdes = 74;
290 *bsdes = 32;
291 break;
292 case 2827:
293 case 2828:
294 *dsdes = 85;
295 *bsdes = 32;
296 break;
297 default:
298 /* Illegal trailer entry */
299 return false;
300 }
301 }
302 return true;
303}
304
305/* Return true if there is room for another entry */
306static bool s390_cpumsf_reached_trailer(size_t entry_sz, size_t pos)
307{
308 size_t payload = S390_CPUMSF_PAGESZ - sizeof(struct hws_trailer_entry);
309
310 if (payload - (pos & (S390_CPUMSF_PAGESZ - 1)) < entry_sz)
311 return false;
312 return true;
313}
314
315/* Dump an auxiliary buffer. These buffers are multiple of
316 * 4KB SDB pages.
317 */
318static void s390_cpumsf_dump(struct s390_cpumsf *sf,
319 unsigned char *buf, size_t len)
320{
321 const char *color = PERF_COLOR_BLUE;
322 struct hws_basic_entry *basic;
323 struct hws_diag_entry *diag;
324 unsigned short bsdes, dsdes;
325 size_t pos = 0;
326
327 color_fprintf(stdout, color,
328 ". ... s390 AUX data: size %zu bytes\n",
329 len);
330
331 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
332 &dsdes)) {
333 pr_err("Invalid AUX trace data block size:%zu"
334 " (type:%d bsdes:%hd dsdes:%hd)\n",
335 len, sf->machine_type, bsdes, dsdes);
336 return;
337 }
338
339 /* s390 kernel always returns 4KB blocks fully occupied,
340 * no partially filled SDBs.
341 */
342 while (pos < len) {
343 /* Handle Basic entry */
344 basic = (struct hws_basic_entry *)(buf + pos);
345 if (s390_cpumsf_basic_show(color, pos, basic))
346 pos += bsdes;
347 else
348 return;
349
350 /* Handle Diagnostic entry */
351 diag = (struct hws_diag_entry *)(buf + pos);
352 if (s390_cpumsf_diag_show(color, pos, diag))
353 pos += dsdes;
354 else
355 return;
356
357 /* Check for trailer entry */
358 if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) {
359 /* Show trailer entry */
360 struct hws_trailer_entry te;
361
362 pos = (pos + S390_CPUMSF_PAGESZ)
363 & ~(S390_CPUMSF_PAGESZ - 1);
364 pos -= sizeof(te);
365 memcpy(&te, buf + pos, sizeof(te));
366 /* Set descriptor sizes in case of old hardware
367 * where these values are not set.
368 */
369 te.bsdes = bsdes;
370 te.dsdes = dsdes;
371 if (s390_cpumsf_trailer_show(color, pos, &te))
372 pos += sizeof(te);
373 else
374 return;
375 }
376 }
377}
378
379static void s390_cpumsf_dump_event(struct s390_cpumsf *sf, unsigned char *buf,
380 size_t len)
381{
382 printf(".\n");
383 s390_cpumsf_dump(sf, buf, len);
384}
385
386#define S390_LPP_PID_MASK 0xffffffff
387
388static bool s390_cpumsf_make_event(size_t pos,
389 struct hws_basic_entry *basic,
390 struct s390_cpumsf_queue *sfq)
391{
392 struct perf_sample sample = {
393 .ip = basic->ia,
394 .pid = basic->hpp & S390_LPP_PID_MASK,
395 .tid = basic->hpp & S390_LPP_PID_MASK,
396 .cpumode = PERF_RECORD_MISC_CPUMODE_UNKNOWN,
397 .cpu = sfq->cpu,
398 .period = 1
399 };
400 union perf_event event;
401
402 memset(&event, 0, sizeof(event));
403 if (basic->CL == 1) /* Native LPAR mode */
404 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
405 : PERF_RECORD_MISC_KERNEL;
406 else if (basic->CL == 2) /* Guest kernel/user space */
407 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
408 : PERF_RECORD_MISC_GUEST_KERNEL;
409 else if (basic->gpp || basic->prim_asn != 0xffff)
410 /* Use heuristics on old hardware */
411 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
412 : PERF_RECORD_MISC_GUEST_KERNEL;
413 else
414 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
415 : PERF_RECORD_MISC_KERNEL;
416
417 event.sample.header.type = PERF_RECORD_SAMPLE;
418 event.sample.header.misc = sample.cpumode;
419 event.sample.header.size = sizeof(struct perf_event_header);
420
421 pr_debug4("%s pos:%#zx ip:%#" PRIx64 " P:%d CL:%d pid:%d.%d cpumode:%d cpu:%d\n",
422 __func__, pos, sample.ip, basic->P, basic->CL, sample.pid,
423 sample.tid, sample.cpumode, sample.cpu);
424 if (perf_session__deliver_synth_event(sfq->sf->session, &event,
425 &sample)) {
426 pr_err("s390 Auxiliary Trace: failed to deliver event\n");
427 return false;
428 }
429 return true;
430}
431
432static unsigned long long get_trailer_time(const unsigned char *buf)
433{
434 struct hws_trailer_entry *te;
435 unsigned long long aux_time;
436
437 te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ
438 - sizeof(*te));
439
440 if (!te->clock_base) /* TOD_CLOCK_BASE value missing */
441 return 0;
442
443 /* Correct calculation to convert time stamp in trailer entry to
444 * nano seconds (taken from arch/s390 function tod_to_ns()).
445 * TOD_CLOCK_BASE is stored in trailer entry member progusage2.
446 */
447 aux_time = trailer_timestamp(te) - te->progusage2;
448 aux_time = (aux_time >> 9) * 125 + (((aux_time & 0x1ff) * 125) >> 9);
449 return aux_time;
450}
451
452/* Process the data samples of a single queue. The first parameter is a
453 * pointer to the queue, the second parameter is the time stamp. This
454 * is the time stamp:
455 * - of the event that triggered this processing.
456 * - or the time stamp when the last proccesing of this queue stopped.
457 * In this case it stopped at a 4KB page boundary and record the
458 * position on where to continue processing on the next invocation
459 * (see buffer->use_data and buffer->use_size).
460 *
461 * When this function returns the second parameter is updated to
462 * reflect the time stamp of the last processed auxiliary data entry
463 * (taken from the trailer entry of that page). The caller uses this
464 * returned time stamp to record the last processed entry in this
465 * queue.
466 *
467 * The function returns:
468 * 0: Processing successful. The second parameter returns the
469 * time stamp from the trailer entry until which position
470 * processing took place. Subsequent calls resume from this
471 * position.
472 * <0: An error occurred during processing. The second parameter
473 * returns the maximum time stamp.
474 * >0: Done on this queue. The second parameter returns the
475 * maximum time stamp.
476 */
477static int s390_cpumsf_samples(struct s390_cpumsf_queue *sfq, u64 *ts)
478{
479 struct s390_cpumsf *sf = sfq->sf;
480 unsigned char *buf = sfq->buffer->use_data;
481 size_t len = sfq->buffer->use_size;
482 struct hws_basic_entry *basic;
483 unsigned short bsdes, dsdes;
484 size_t pos = 0;
485 int err = 1;
486 u64 aux_ts;
487
488 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
489 &dsdes)) {
490 *ts = ~0ULL;
491 return -1;
492 }
493
494 /* Get trailer entry time stamp and check if entries in
495 * this auxiliary page are ready for processing. If the
496 * time stamp of the first entry is too high, whole buffer
497 * can be skipped. In this case return time stamp.
498 */
499 aux_ts = get_trailer_time(buf);
500 if (!aux_ts) {
501 pr_err("[%#08" PRIx64 "] Invalid AUX trailer entry TOD clock base\n",
502 sfq->buffer->data_offset);
503 aux_ts = ~0ULL;
504 goto out;
505 }
506 if (aux_ts > *ts) {
507 *ts = aux_ts;
508 return 0;
509 }
510
511 while (pos < len) {
512 /* Handle Basic entry */
513 basic = (struct hws_basic_entry *)(buf + pos);
514 if (s390_cpumsf_make_event(pos, basic, sfq))
515 pos += bsdes;
516 else {
517 err = -EBADF;
518 goto out;
519 }
520
521 pos += dsdes; /* Skip diagnositic entry */
522
523 /* Check for trailer entry */
524 if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) {
525 pos = (pos + S390_CPUMSF_PAGESZ)
526 & ~(S390_CPUMSF_PAGESZ - 1);
527 /* Check existence of next page */
528 if (pos >= len)
529 break;
530 aux_ts = get_trailer_time(buf + pos);
531 if (!aux_ts) {
532 aux_ts = ~0ULL;
533 goto out;
534 }
535 if (aux_ts > *ts) {
536 *ts = aux_ts;
537 sfq->buffer->use_data += pos;
538 sfq->buffer->use_size -= pos;
539 return 0;
540 }
541 }
542 }
543out:
544 *ts = aux_ts;
545 sfq->buffer->use_size = 0;
546 sfq->buffer->use_data = NULL;
547 return err; /* Buffer completely scanned or error */
548}
549
550/* Run the s390 auxiliary trace decoder.
551 * Select the queue buffer to operate on, the caller already selected
552 * the proper queue, depending on second parameter 'ts'.
553 * This is the time stamp until which the auxiliary entries should
554 * be processed. This value is updated by called functions and
555 * returned to the caller.
556 *
557 * Resume processing in the current buffer. If there is no buffer
558 * get a new buffer from the queue and setup start position for
559 * processing.
560 * When a buffer is completely processed remove it from the queue
561 * before returning.
562 *
563 * This function returns
564 * 1: When the queue is empty. Second parameter will be set to
565 * maximum time stamp.
566 * 0: Normal processing done.
567 * <0: Error during queue buffer setup. This causes the caller
568 * to stop processing completely.
569 */
570static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
571 u64 *ts)
572{
573
574 struct auxtrace_buffer *buffer;
575 struct auxtrace_queue *queue;
576 int err;
577
578 queue = &sfq->sf->queues.queue_array[sfq->queue_nr];
579
580 /* Get buffer and last position in buffer to resume
581 * decoding the auxiliary entries. One buffer might be large
582 * and decoding might stop in between. This depends on the time
583 * stamp of the trailer entry in each page of the auxiliary
584 * data and the time stamp of the event triggering the decoding.
585 */
586 if (sfq->buffer == NULL) {
587 sfq->buffer = buffer = auxtrace_buffer__next(queue,
588 sfq->buffer);
589 if (!buffer) {
590 *ts = ~0ULL;
591 return 1; /* Processing done on this queue */
592 }
593 /* Start with a new buffer on this queue */
594 if (buffer->data) {
595 buffer->use_size = buffer->size;
596 buffer->use_data = buffer->data;
597 }
598 } else
599 buffer = sfq->buffer;
600
601 if (!buffer->data) {
602 int fd = perf_data__fd(sfq->sf->session->data);
603
604 buffer->data = auxtrace_buffer__get_data(buffer, fd);
605 if (!buffer->data)
606 return -ENOMEM;
607 buffer->use_size = buffer->size;
608 buffer->use_data = buffer->data;
609 }
610 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,
612 buffer->size, buffer->use_size);
613 err = s390_cpumsf_samples(sfq, ts);
614
615 /* If non-zero, there is either an error (err < 0) or the buffer is
616 * completely done (err > 0). The error is unrecoverable, usually
617 * some descriptors could not be read successfully, so continue with
618 * the next buffer.
619 * In both cases the parameter 'ts' has been updated.
620 */
621 if (err) {
622 sfq->buffer = NULL;
623 list_del(&buffer->list);
624 auxtrace_buffer__free(buffer);
625 if (err > 0) /* Buffer done, no error */
626 err = 0;
627 }
628 return err;
629}
630
631static struct s390_cpumsf_queue *
632s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr)
633{
634 struct s390_cpumsf_queue *sfq;
635
636 sfq = zalloc(sizeof(struct s390_cpumsf_queue));
637 if (sfq == NULL)
638 return NULL;
639
640 sfq->sf = sf;
641 sfq->queue_nr = queue_nr;
642 sfq->cpu = -1;
643 return sfq;
644}
645
646static int s390_cpumsf_setup_queue(struct s390_cpumsf *sf,
647 struct auxtrace_queue *queue,
648 unsigned int queue_nr, u64 ts)
649{
650 struct s390_cpumsf_queue *sfq = queue->priv;
651
652 if (list_empty(&queue->head))
653 return 0;
654
655 if (sfq == NULL) {
656 sfq = s390_cpumsf_alloc_queue(sf, queue_nr);
657 if (!sfq)
658 return -ENOMEM;
659 queue->priv = sfq;
660
661 if (queue->cpu != -1)
662 sfq->cpu = queue->cpu;
663 }
664 return auxtrace_heap__add(&sf->heap, queue_nr, ts);
665}
666
667static int s390_cpumsf_setup_queues(struct s390_cpumsf *sf, u64 ts)
668{
669 unsigned int i;
670 int ret = 0;
671
672 for (i = 0; i < sf->queues.nr_queues; i++) {
673 ret = s390_cpumsf_setup_queue(sf, &sf->queues.queue_array[i],
674 i, ts);
675 if (ret)
676 break;
677 }
678 return ret;
679}
680
681static int s390_cpumsf_update_queues(struct s390_cpumsf *sf, u64 ts)
682{
683 if (!sf->queues.new_data)
684 return 0;
685
686 sf->queues.new_data = false;
687 return s390_cpumsf_setup_queues(sf, ts);
688}
689
690static int s390_cpumsf_process_queues(struct s390_cpumsf *sf, u64 timestamp)
691{
692 unsigned int queue_nr;
693 u64 ts;
694 int ret;
695
696 while (1) {
697 struct auxtrace_queue *queue;
698 struct s390_cpumsf_queue *sfq;
699
700 if (!sf->heap.heap_cnt)
701 return 0;
702
703 if (sf->heap.heap_array[0].ordinal >= timestamp)
704 return 0;
705
706 queue_nr = sf->heap.heap_array[0].queue_nr;
707 queue = &sf->queues.queue_array[queue_nr];
708 sfq = queue->priv;
709
710 auxtrace_heap__pop(&sf->heap);
711 if (sf->heap.heap_cnt) {
712 ts = sf->heap.heap_array[0].ordinal + 1;
713 if (ts > timestamp)
714 ts = timestamp;
715 } else {
716 ts = timestamp;
717 }
718
719 ret = s390_cpumsf_run_decoder(sfq, &ts);
720 if (ret < 0) {
721 auxtrace_heap__add(&sf->heap, queue_nr, ts);
722 return ret;
723 }
724 if (!ret) {
725 ret = auxtrace_heap__add(&sf->heap, queue_nr, ts);
726 if (ret < 0)
727 return ret;
728 }
729 }
730 return 0;
731}
732
733static int s390_cpumsf_synth_error(struct s390_cpumsf *sf, int code, int cpu,
734 pid_t pid, pid_t tid, u64 ip)
735{
736 char msg[MAX_AUXTRACE_ERROR_MSG];
737 union perf_event event;
738 int err;
739
740 strncpy(msg, "Lost Auxiliary Trace Buffer", sizeof(msg) - 1);
741 auxtrace_synth_error(&event.auxtrace_error, PERF_AUXTRACE_ERROR_ITRACE,
742 code, cpu, pid, tid, ip, msg);
743
744 err = perf_session__deliver_synth_event(sf->session, &event, NULL);
745 if (err)
746 pr_err("s390 Auxiliary Trace: failed to deliver error event,"
747 "error %d\n", err);
748 return err;
749}
750
751static int s390_cpumsf_lost(struct s390_cpumsf *sf, struct perf_sample *sample)
752{
753 return s390_cpumsf_synth_error(sf, 1, sample->cpu,
754 sample->pid, sample->tid, 0);
755}
756
757static int
758s390_cpumsf_process_event(struct perf_session *session __maybe_unused,
759 union perf_event *event,
760 struct perf_sample *sample,
761 struct perf_tool *tool)
762{
763 struct s390_cpumsf *sf = container_of(session->auxtrace,
764 struct s390_cpumsf,
765 auxtrace);
766 u64 timestamp = sample->time;
767 int err = 0;
768
769 if (dump_trace)
770 return 0;
771
772 if (!tool->ordered_events) {
773 pr_err("s390 Auxiliary Trace requires ordered events\n");
774 return -EINVAL;
775 }
776
777 if (event->header.type == PERF_RECORD_AUX &&
778 event->aux.flags & PERF_AUX_FLAG_TRUNCATED)
779 return s390_cpumsf_lost(sf, sample);
780
781 if (timestamp) {
782 err = s390_cpumsf_update_queues(sf, timestamp);
783 if (!err)
784 err = s390_cpumsf_process_queues(sf, timestamp);
785 }
786 return err;
787}
788
789struct s390_cpumsf_synth {
790 struct perf_tool cpumsf_tool;
791 struct perf_session *session;
792};
793
794static int
795s390_cpumsf_process_auxtrace_event(struct perf_session *session,
796 union perf_event *event __maybe_unused,
797 struct perf_tool *tool __maybe_unused)
798{
799 struct s390_cpumsf *sf = container_of(session->auxtrace,
800 struct s390_cpumsf,
801 auxtrace);
802
803 int fd = perf_data__fd(session->data);
804 struct auxtrace_buffer *buffer;
805 off_t data_offset;
806 int err;
807
808 if (sf->data_queued)
809 return 0;
810
811 if (perf_data__is_pipe(session->data)) {
812 data_offset = 0;
813 } else {
814 data_offset = lseek(fd, 0, SEEK_CUR);
815 if (data_offset == -1)
816 return -errno;
817 }
818
819 err = auxtrace_queues__add_event(&sf->queues, session, event,
820 data_offset, &buffer);
821 if (err)
822 return err;
823
824 /* Dump here after copying piped trace out of the pipe */
825 if (dump_trace) {
826 if (auxtrace_buffer__get_data(buffer, fd)) {
827 s390_cpumsf_dump_event(sf, buffer->data,
828 buffer->size);
829 auxtrace_buffer__put_data(buffer);
830 }
831 }
832 return 0;
833}
834
835static void s390_cpumsf_free_events(struct perf_session *session __maybe_unused)
836{
837}
838
839static int s390_cpumsf_flush(struct perf_session *session __maybe_unused,
840 struct perf_tool *tool __maybe_unused)
841{
842 return 0;
843}
844
845static void s390_cpumsf_free_queues(struct perf_session *session)
846{
847 struct s390_cpumsf *sf = container_of(session->auxtrace,
848 struct s390_cpumsf,
849 auxtrace);
850 struct auxtrace_queues *queues = &sf->queues;
851 unsigned int i;
852
853 for (i = 0; i < queues->nr_queues; i++)
854 zfree(&queues->queue_array[i].priv);
855 auxtrace_queues__free(queues);
856}
857
858static void s390_cpumsf_free(struct perf_session *session)
859{
860 struct s390_cpumsf *sf = container_of(session->auxtrace,
861 struct s390_cpumsf,
862 auxtrace);
863
864 auxtrace_heap__free(&sf->heap);
865 s390_cpumsf_free_queues(session);
866 session->auxtrace = NULL;
867 free(sf);
868}
869
870static int s390_cpumsf_get_type(const char *cpuid)
871{
872 int ret, family = 0;
873
874 ret = sscanf(cpuid, "%*[^,],%u", &family);
875 return (ret == 1) ? family : 0;
876}
877
878/* Check itrace options set on perf report command.
879 * Return true, if none are set or all options specified can be
880 * handled on s390.
881 * Return false otherwise.
882 */
883static bool check_auxtrace_itrace(struct itrace_synth_opts *itops)
884{
885 if (!itops || !itops->set)
886 return true;
887 pr_err("No --itrace options supported\n");
888 return false;
889}
890
891int s390_cpumsf_process_auxtrace_info(union perf_event *event,
892 struct perf_session *session)
893{
894 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
895 struct s390_cpumsf *sf;
896 int err;
897
898 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event))
899 return -EINVAL;
900
901 sf = zalloc(sizeof(struct s390_cpumsf));
902 if (sf == NULL)
903 return -ENOMEM;
904
905 if (!check_auxtrace_itrace(session->itrace_synth_opts)) {
906 err = -EINVAL;
907 goto err_free;
908 }
909
910 err = auxtrace_queues__init(&sf->queues);
911 if (err)
912 goto err_free;
913
914 sf->session = session;
915 sf->machine = &session->machines.host; /* No kvm support */
916 sf->auxtrace_type = auxtrace_info->type;
917 sf->pmu_type = PERF_TYPE_RAW;
918 sf->machine_type = s390_cpumsf_get_type(session->evlist->env->cpuid);
919
920 sf->auxtrace.process_event = s390_cpumsf_process_event;
921 sf->auxtrace.process_auxtrace_event = s390_cpumsf_process_auxtrace_event;
922 sf->auxtrace.flush_events = s390_cpumsf_flush;
923 sf->auxtrace.free_events = s390_cpumsf_free_events;
924 sf->auxtrace.free = s390_cpumsf_free;
925 session->auxtrace = &sf->auxtrace;
926
927 if (dump_trace)
928 return 0;
929
930 err = auxtrace_queues__process_index(&sf->queues, session);
931 if (err)
932 goto err_free_queues;
933
934 if (sf->queues.populated)
935 sf->data_queued = true;
936
937 return 0;
938
939err_free_queues:
940 auxtrace_queues__free(&sf->queues);
941 session->auxtrace = NULL;
942err_free:
943 free(sf);
944 return err;
945}
diff --git a/tools/perf/util/s390-cpumsf.h b/tools/perf/util/s390-cpumsf.h
new file mode 100644
index 000000000000..fb64d100555c
--- /dev/null
+++ b/tools/perf/util/s390-cpumsf.h
@@ -0,0 +1,21 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright IBM Corp. 2018
4 * Auxtrace support for s390 CPU-Measurement Sampling Facility
5 *
6 * Author(s): Thomas Richter <tmricht@linux.ibm.com>
7 */
8
9#ifndef INCLUDE__PERF_S390_CPUMSF_H
10#define INCLUDE__PERF_S390_CPUMSF_H
11
12union perf_event;
13struct perf_session;
14struct perf_pmu;
15
16struct auxtrace_record *
17s390_cpumsf_recording_init(int *err, struct perf_pmu *s390_cpumsf_pmu);
18
19int s390_cpumsf_process_auxtrace_info(union perf_event *event,
20 struct perf_session *session);
21#endif
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 7b79c413486b..45484f0f7292 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -535,7 +535,7 @@ static int perl_stop_script(void)
535 return 0; 535 return 0;
536} 536}
537 537
538static int perl_generate_script(struct pevent *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 event_format *event = NULL;
541 struct format_field *f; 541 struct format_field *f;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index bc32e57d17be..dfc6093f118c 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -871,8 +871,8 @@ static void python_process_tracepoint(struct perf_sample *sample,
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 & FIELD_IS_DYNAMIC) {
874 val = pevent_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;
@@ -1588,7 +1588,7 @@ static int python_stop_script(void)
1588 return 0; 1588 return 0;
1589} 1589}
1590 1590
1591static int python_generate_script(struct pevent *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 event_format *event = NULL;
1594 struct format_field *f; 1594 struct format_field *f;
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 001be4f9d3b9..97efbcad076e 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -1,12 +1,20 @@
1#!/usr/bin/python 1#!/usr/bin/python
2 2
3from os import getenv 3from os import getenv
4from subprocess import Popen, PIPE
5from re import sub
6
7def clang_has_option(option):
8 return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if "unknown argument" in o] == [ ]
4 9
5cc = getenv("CC") 10cc = getenv("CC")
6if cc == "clang": 11if cc == "clang":
7 from _sysconfigdata import build_time_vars 12 from _sysconfigdata import build_time_vars
8 from re import sub
9 build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"]) 13 build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"])
14 if not clang_has_option("-mcet"):
15 build_time_vars["CFLAGS"] = sub("-mcet", "", build_time_vars["CFLAGS"])
16 if not clang_has_option("-fcf-protection"):
17 build_time_vars["CFLAGS"] = sub("-fcf-protection", "", build_time_vars["CFLAGS"])
10 18
11from distutils.core import setup, Extension 19from distutils.core import setup, Extension
12 20
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index fed2952ab45a..b284276ec963 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -601,7 +601,7 @@ static char *get_trace_output(struct hist_entry *he)
601{ 601{
602 struct trace_seq seq; 602 struct trace_seq seq;
603 struct perf_evsel *evsel; 603 struct perf_evsel *evsel;
604 struct pevent_record rec = { 604 struct tep_record rec = {
605 .data = he->raw_data, 605 .data = he->raw_data,
606 .size = he->raw_size, 606 .size = he->raw_size,
607 }; 607 };
@@ -610,10 +610,10 @@ static char *get_trace_output(struct hist_entry *he)
610 610
611 trace_seq_init(&seq); 611 trace_seq_init(&seq);
612 if (symbol_conf.raw_trace) { 612 if (symbol_conf.raw_trace) {
613 pevent_print_fields(&seq, he->raw_data, he->raw_size, 613 tep_print_fields(&seq, he->raw_data, he->raw_size,
614 evsel->tp_format); 614 evsel->tp_format);
615 } else { 615 } else {
616 pevent_event_info(&seq, evsel->tp_format, &rec); 616 tep_event_info(&seq, evsel->tp_format, &rec);
617 } 617 }
618 /* 618 /*
619 * Trim the buffer, it starts at 4KB and we're not going to 619 * Trim the buffer, it starts at 4KB and we're not going to
@@ -2047,7 +2047,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
2047 struct trace_seq seq; 2047 struct trace_seq seq;
2048raw_field: 2048raw_field:
2049 trace_seq_init(&seq); 2049 trace_seq_init(&seq);
2050 pevent_print_field(&seq, he->raw_data, hde->field); 2050 tep_print_field(&seq, he->raw_data, hde->field);
2051 str = seq.buffer; 2051 str = seq.buffer;
2052 } 2052 }
2053 2053
@@ -2074,7 +2074,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
2074 if (field->flags & FIELD_IS_DYNAMIC) { 2074 if (field->flags & FIELD_IS_DYNAMIC) {
2075 unsigned long long dyn; 2075 unsigned long long dyn;
2076 2076
2077 pevent_read_number_field(field, a->raw_data, &dyn); 2077 tep_read_number_field(field, a->raw_data, &dyn);
2078 offset = dyn & 0xffff; 2078 offset = dyn & 0xffff;
2079 size = (dyn >> 16) & 0xffff; 2079 size = (dyn >> 16) & 0xffff;
2080 2080
@@ -2311,7 +2311,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
2311 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 2311 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
2312 continue; 2312 continue;
2313 2313
2314 field = pevent_find_any_field(evsel->tp_format, field_name); 2314 field = tep_find_any_field(evsel->tp_format, field_name);
2315 if (field == NULL) 2315 if (field == NULL)
2316 continue; 2316 continue;
2317 2317
@@ -2378,7 +2378,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
2378 if (!strcmp(field_name, "*")) { 2378 if (!strcmp(field_name, "*")) {
2379 ret = add_evsel_fields(evsel, raw_trace, level); 2379 ret = add_evsel_fields(evsel, raw_trace, level);
2380 } else { 2380 } else {
2381 field = pevent_find_any_field(evsel->tp_format, field_name); 2381 field = tep_find_any_field(evsel->tp_format, field_name);
2382 if (field == NULL) { 2382 if (field == NULL) {
2383 pr_debug("Cannot find event field for %s.%s\n", 2383 pr_debug("Cannot find event field for %s.%s\n",
2384 event_name, field_name); 2384 event_name, field_name);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 8bf302cafcec..a97cf8e6be86 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -276,7 +276,7 @@ extern struct sort_entry sort_thread;
276extern struct list_head hist_entry__sort_list; 276extern struct list_head hist_entry__sort_list;
277 277
278struct perf_evlist; 278struct perf_evlist;
279struct pevent; 279struct tep_handle;
280int setup_sorting(struct perf_evlist *evlist); 280int setup_sorting(struct perf_evlist *evlist);
281int setup_output_field(void); 281int setup_output_field(void);
282void reset_output_field(void); 282void reset_output_field(void);
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index e0a6e9a6a053..920b1d58a068 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -32,7 +32,7 @@
32static int get_common_field(struct scripting_context *context, 32static 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 pevent *pevent = context->pevent; 35 struct tep_handle *pevent = context->pevent;
36 struct event_format *event; 36 struct event_format *event;
37 struct format_field *field; 37 struct format_field *field;
38 38
@@ -41,14 +41,14 @@ static int get_common_field(struct scripting_context *context,
41 return 0; 41 return 0;
42 42
43 event = pevent->events[0]; 43 event = pevent->events[0];
44 field = pevent_find_common_field(event, type); 44 field = tep_find_common_field(event, type);
45 if (!field) 45 if (!field)
46 return 0; 46 return 0;
47 *offset = field->offset; 47 *offset = field->offset;
48 *size = field->size; 48 *size = field->size;
49 } 49 }
50 50
51 return pevent_read_number(pevent, context->event_data + *offset, *size); 51 return tep_read_number(pevent, context->event_data + *offset, *size);
52} 52}
53 53
54int common_lock_depth(struct scripting_context *context) 54int common_lock_depth(struct scripting_context *context)
@@ -99,24 +99,24 @@ raw_field_value(struct event_format *event, const char *name, void *data)
99 struct format_field *field; 99 struct format_field *field;
100 unsigned long long val; 100 unsigned long long val;
101 101
102 field = pevent_find_any_field(event, name); 102 field = tep_find_any_field(event, name);
103 if (!field) 103 if (!field)
104 return 0ULL; 104 return 0ULL;
105 105
106 pevent_read_number_field(field, data, &val); 106 tep_read_number_field(field, data, &val);
107 107
108 return val; 108 return val;
109} 109}
110 110
111unsigned long long read_size(struct event_format *event, void *ptr, int size) 111unsigned long long read_size(struct event_format *event, void *ptr, int size)
112{ 112{
113 return pevent_read_number(event->pevent, ptr, size); 113 return tep_read_number(event->pevent, ptr, size);
114} 114}
115 115
116void event_format__fprintf(struct event_format *event, 116void event_format__fprintf(struct event_format *event,
117 int cpu, void *data, int size, FILE *fp) 117 int cpu, void *data, int size, FILE *fp)
118{ 118{
119 struct pevent_record record; 119 struct tep_record record;
120 struct trace_seq s; 120 struct trace_seq s;
121 121
122 memset(&record, 0, sizeof(record)); 122 memset(&record, 0, sizeof(record));
@@ -125,7 +125,7 @@ void event_format__fprintf(struct event_format *event,
125 record.data = data; 125 record.data = data;
126 126
127 trace_seq_init(&s); 127 trace_seq_init(&s);
128 pevent_event_info(&s, event, &record); 128 tep_event_info(&s, event, &record);
129 trace_seq_do_fprintf(&s, fp); 129 trace_seq_do_fprintf(&s, fp);
130 trace_seq_destroy(&s); 130 trace_seq_destroy(&s);
131} 131}
@@ -136,7 +136,7 @@ void event_format__print(struct event_format *event,
136 return event_format__fprintf(event, cpu, data, size, stdout); 136 return event_format__fprintf(event, cpu, data, size, stdout);
137} 137}
138 138
139void parse_ftrace_printk(struct pevent *pevent, 139void parse_ftrace_printk(struct tep_handle *pevent,
140 char *file, unsigned int size __maybe_unused) 140 char *file, unsigned int size __maybe_unused)
141{ 141{
142 unsigned long long addr; 142 unsigned long long addr;
@@ -157,11 +157,11 @@ void parse_ftrace_printk(struct pevent *pevent,
157 /* fmt still has a space, skip it */ 157 /* fmt still has a space, skip it */
158 printk = strdup(fmt+1); 158 printk = strdup(fmt+1);
159 line = strtok_r(NULL, "\n", &next); 159 line = strtok_r(NULL, "\n", &next);
160 pevent_register_print_string(pevent, printk, addr); 160 tep_register_print_string(pevent, printk, addr);
161 } 161 }
162} 162}
163 163
164void parse_saved_cmdline(struct pevent *pevent, 164void parse_saved_cmdline(struct tep_handle *pevent,
165 char *file, unsigned int size __maybe_unused) 165 char *file, unsigned int size __maybe_unused)
166{ 166{
167 char *comm; 167 char *comm;
@@ -172,24 +172,24 @@ void parse_saved_cmdline(struct pevent *pevent,
172 line = strtok_r(file, "\n", &next); 172 line = strtok_r(file, "\n", &next);
173 while (line) { 173 while (line) {
174 sscanf(line, "%d %ms", &pid, &comm); 174 sscanf(line, "%d %ms", &pid, &comm);
175 pevent_register_comm(pevent, comm, pid); 175 tep_register_comm(pevent, comm, pid);
176 free(comm); 176 free(comm);
177 line = strtok_r(NULL, "\n", &next); 177 line = strtok_r(NULL, "\n", &next);
178 } 178 }
179} 179}
180 180
181int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size) 181int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size)
182{ 182{
183 return pevent_parse_event(pevent, buf, size, "ftrace"); 183 return tep_parse_event(pevent, buf, size, "ftrace");
184} 184}
185 185
186int parse_event_file(struct pevent *pevent, 186int parse_event_file(struct tep_handle *pevent,
187 char *buf, unsigned long size, char *sys) 187 char *buf, unsigned long size, char *sys)
188{ 188{
189 return pevent_parse_event(pevent, buf, size, sys); 189 return tep_parse_event(pevent, buf, size, sys);
190} 190}
191 191
192struct event_format *trace_find_next_event(struct pevent *pevent, 192struct event_format *trace_find_next_event(struct tep_handle *pevent,
193 struct event_format *event) 193 struct event_format *event)
194{ 194{
195 static int idx; 195 static int idx;
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 40b425949aa3..3dfc1db6b25b 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -96,7 +96,7 @@ static void skip(int size)
96 }; 96 };
97} 97}
98 98
99static unsigned int read4(struct pevent *pevent) 99static unsigned int read4(struct tep_handle *pevent)
100{ 100{
101 unsigned int data; 101 unsigned int data;
102 102
@@ -105,7 +105,7 @@ static unsigned int read4(struct pevent *pevent)
105 return __data2host4(pevent, data); 105 return __data2host4(pevent, data);
106} 106}
107 107
108static unsigned long long read8(struct pevent *pevent) 108static unsigned long long read8(struct tep_handle *pevent)
109{ 109{
110 unsigned long long data; 110 unsigned long long data;
111 111
@@ -158,7 +158,7 @@ out:
158 return str; 158 return str;
159} 159}
160 160
161static int read_proc_kallsyms(struct pevent *pevent) 161static int read_proc_kallsyms(struct tep_handle *pevent)
162{ 162{
163 unsigned int size; 163 unsigned int size;
164 164
@@ -181,7 +181,7 @@ static int read_proc_kallsyms(struct pevent *pevent)
181 return 0; 181 return 0;
182} 182}
183 183
184static int read_ftrace_printk(struct pevent *pevent) 184static int read_ftrace_printk(struct tep_handle *pevent)
185{ 185{
186 unsigned int size; 186 unsigned int size;
187 char *buf; 187 char *buf;
@@ -208,7 +208,7 @@ static int read_ftrace_printk(struct pevent *pevent)
208 return 0; 208 return 0;
209} 209}
210 210
211static int read_header_files(struct pevent *pevent) 211static int read_header_files(struct tep_handle *pevent)
212{ 212{
213 unsigned long long size; 213 unsigned long long size;
214 char *header_page; 214 char *header_page;
@@ -235,13 +235,13 @@ static int read_header_files(struct pevent *pevent)
235 return -1; 235 return -1;
236 } 236 }
237 237
238 if (!pevent_parse_header_page(pevent, header_page, size, 238 if (!tep_parse_header_page(pevent, header_page, size,
239 pevent_get_long_size(pevent))) { 239 tep_get_long_size(pevent))) {
240 /* 240 /*
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 pevent_set_long_size(pevent, pevent->header_page_size_size); 244 tep_set_long_size(pevent, pevent->header_page_size_size);
245 } 245 }
246 free(header_page); 246 free(header_page);
247 247
@@ -259,7 +259,7 @@ static int read_header_files(struct pevent *pevent)
259 return ret; 259 return ret;
260} 260}
261 261
262static int read_ftrace_file(struct pevent *pevent, unsigned long long size) 262static int read_ftrace_file(struct tep_handle *pevent, unsigned long long size)
263{ 263{
264 int ret; 264 int ret;
265 char *buf; 265 char *buf;
@@ -284,8 +284,8 @@ out:
284 return ret; 284 return ret;
285} 285}
286 286
287static int read_event_file(struct pevent *pevent, char *sys, 287static int read_event_file(struct tep_handle *pevent, char *sys,
288 unsigned long long size) 288 unsigned long long size)
289{ 289{
290 int ret; 290 int ret;
291 char *buf; 291 char *buf;
@@ -310,7 +310,7 @@ out:
310 return ret; 310 return ret;
311} 311}
312 312
313static int read_ftrace_files(struct pevent *pevent) 313static int read_ftrace_files(struct tep_handle *pevent)
314{ 314{
315 unsigned long long size; 315 unsigned long long size;
316 int count; 316 int count;
@@ -328,7 +328,7 @@ static int read_ftrace_files(struct pevent *pevent)
328 return 0; 328 return 0;
329} 329}
330 330
331static int read_event_files(struct pevent *pevent) 331static int read_event_files(struct tep_handle *pevent)
332{ 332{
333 unsigned long long size; 333 unsigned long long size;
334 char *sys; 334 char *sys;
@@ -356,7 +356,7 @@ static int read_event_files(struct pevent *pevent)
356 return 0; 356 return 0;
357} 357}
358 358
359static int read_saved_cmdline(struct pevent *pevent) 359static int read_saved_cmdline(struct tep_handle *pevent)
360{ 360{
361 unsigned long long size; 361 unsigned long long size;
362 char *buf; 362 char *buf;
@@ -399,7 +399,7 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
399 int host_bigendian; 399 int host_bigendian;
400 int file_long_size; 400 int file_long_size;
401 int file_page_size; 401 int file_page_size;
402 struct pevent *pevent = NULL; 402 struct tep_handle *pevent = NULL;
403 int err; 403 int err;
404 404
405 repipe = __repipe; 405 repipe = __repipe;
@@ -439,9 +439,9 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
439 439
440 pevent = tevent->pevent; 440 pevent = tevent->pevent;
441 441
442 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); 442 tep_set_flag(pevent, TEP_NSEC_OUTPUT);
443 pevent_set_file_bigendian(pevent, file_bigendian); 443 tep_set_file_bigendian(pevent, file_bigendian);
444 pevent_set_host_bigendian(pevent, host_bigendian); 444 tep_set_host_bigendian(pevent, host_bigendian);
445 445
446 if (do_read(buf, 1) < 0) 446 if (do_read(buf, 1) < 0)
447 goto out; 447 goto out;
@@ -451,8 +451,8 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
451 if (!file_page_size) 451 if (!file_page_size)
452 goto out; 452 goto out;
453 453
454 pevent_set_long_size(pevent, file_long_size); 454 tep_set_long_size(pevent, file_long_size);
455 pevent_set_page_size(pevent, file_page_size); 455 tep_set_page_size(pevent, file_page_size);
456 456
457 err = read_header_files(pevent); 457 err = read_header_files(pevent);
458 if (err) 458 if (err)
@@ -479,9 +479,9 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
479 repipe = false; 479 repipe = false;
480 480
481 if (show_funcs) { 481 if (show_funcs) {
482 pevent_print_funcs(pevent); 482 tep_print_funcs(pevent);
483 } else if (show_printk) { 483 } else if (show_printk) {
484 pevent_print_printk(pevent); 484 tep_print_printk(pevent);
485 } 485 }
486 486
487 pevent = NULL; 487 pevent = NULL;
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index b1e5c3a2b8e3..b749f812ac70 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -66,7 +66,7 @@ static int python_start_script_unsupported(const char *script __maybe_unused,
66 return -1; 66 return -1;
67} 67}
68 68
69static int python_generate_script_unsupported(struct pevent *pevent 69static int python_generate_script_unsupported(struct tep_handle *pevent
70 __maybe_unused, 70 __maybe_unused,
71 const char *outfile 71 const char *outfile
72 __maybe_unused) 72 __maybe_unused)
@@ -130,7 +130,7 @@ static int perl_start_script_unsupported(const char *script __maybe_unused,
130 return -1; 130 return -1;
131} 131}
132 132
133static int perl_generate_script_unsupported(struct pevent *pevent 133static int perl_generate_script_unsupported(struct tep_handle *pevent
134 __maybe_unused, 134 __maybe_unused,
135 const char *outfile __maybe_unused) 135 const char *outfile __maybe_unused)
136{ 136{
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 1aa368603268..58bb72f266f3 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -28,10 +28,10 @@ static bool tevent_initialized;
28 28
29int trace_event__init(struct trace_event *t) 29int trace_event__init(struct trace_event *t)
30{ 30{
31 struct pevent *pevent = pevent_alloc(); 31 struct tep_handle *pevent = tep_alloc();
32 32
33 if (pevent) { 33 if (pevent) {
34 t->plugin_list = traceevent_load_plugins(pevent); 34 t->plugin_list = tep_load_plugins(pevent);
35 t->pevent = pevent; 35 t->pevent = pevent;
36 } 36 }
37 37
@@ -40,33 +40,33 @@ int trace_event__init(struct trace_event *t)
40 40
41static int trace_event__init2(void) 41static int trace_event__init2(void)
42{ 42{
43 int be = traceevent_host_bigendian(); 43 int be = tep_host_bigendian();
44 struct pevent *pevent; 44 struct tep_handle *pevent;
45 45
46 if (trace_event__init(&tevent)) 46 if (trace_event__init(&tevent))
47 return -1; 47 return -1;
48 48
49 pevent = tevent.pevent; 49 pevent = tevent.pevent;
50 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); 50 tep_set_flag(pevent, TEP_NSEC_OUTPUT);
51 pevent_set_file_bigendian(pevent, be); 51 tep_set_file_bigendian(pevent, be);
52 pevent_set_host_bigendian(pevent, be); 52 tep_set_host_bigendian(pevent, be);
53 tevent_initialized = true; 53 tevent_initialized = true;
54 return 0; 54 return 0;
55} 55}
56 56
57int trace_event__register_resolver(struct machine *machine, 57int trace_event__register_resolver(struct machine *machine,
58 pevent_func_resolver_t *func) 58 tep_func_resolver_t *func)
59{ 59{
60 if (!tevent_initialized && trace_event__init2()) 60 if (!tevent_initialized && trace_event__init2())
61 return -1; 61 return -1;
62 62
63 return pevent_set_function_resolver(tevent.pevent, func, machine); 63 return tep_set_function_resolver(tevent.pevent, func, machine);
64} 64}
65 65
66void trace_event__cleanup(struct trace_event *t) 66void trace_event__cleanup(struct trace_event *t)
67{ 67{
68 traceevent_unload_plugins(t->plugin_list, t->pevent); 68 tep_unload_plugins(t->plugin_list, t->pevent);
69 pevent_free(t->pevent); 69 tep_free(t->pevent);
70} 70}
71 71
72/* 72/*
@@ -76,7 +76,7 @@ static struct 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 pevent *pevent = tevent.pevent; 79 struct tep_handle *pevent = tevent.pevent;
80 struct event_format *event = NULL; 80 struct event_format *event = NULL;
81 char path[PATH_MAX]; 81 char path[PATH_MAX];
82 size_t size; 82 size_t size;
@@ -93,7 +93,7 @@ tp_format(const char *sys, const char *name)
93 if (err) 93 if (err)
94 return ERR_PTR(err); 94 return ERR_PTR(err);
95 95
96 pevent_parse_format(pevent, &event, data, size, sys); 96 tep_parse_format(pevent, &event, data, size, sys);
97 97
98 free(data); 98 free(data);
99 return event; 99 return event;
@@ -116,5 +116,5 @@ struct event_format *trace_event__tp_format_id(int id)
116 if (!tevent_initialized && trace_event__init2()) 116 if (!tevent_initialized && trace_event__init2())
117 return ERR_PTR(-ENOMEM); 117 return ERR_PTR(-ENOMEM);
118 118
119 return pevent_find_event(tevent.pevent, id); 119 return tep_find_event(tevent.pevent, id);
120} 120}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index dcbdb53dc702..40204ec3a7a2 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -13,14 +13,14 @@ struct thread;
13struct plugin_list; 13struct plugin_list;
14 14
15struct trace_event { 15struct trace_event {
16 struct pevent *pevent; 16 struct tep_handle *pevent;
17 struct plugin_list *plugin_list; 17 struct plugin_list *plugin_list;
18}; 18};
19 19
20int trace_event__init(struct trace_event *t); 20int trace_event__init(struct trace_event *t);
21void trace_event__cleanup(struct trace_event *t); 21void trace_event__cleanup(struct trace_event *t);
22int trace_event__register_resolver(struct machine *machine, 22int trace_event__register_resolver(struct machine *machine,
23 pevent_func_resolver_t *func); 23 tep_func_resolver_t *func);
24struct event_format* 24struct event_format*
25trace_event__tp_format(const char *sys, const char *name); 25trace_event__tp_format(const char *sys, const char *name);
26 26
@@ -34,20 +34,20 @@ void event_format__fprintf(struct event_format *event,
34void event_format__print(struct event_format *event, 34void event_format__print(struct event_format *event,
35 int cpu, void *data, int size); 35 int cpu, void *data, int size);
36 36
37int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size); 37int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size);
38int parse_event_file(struct pevent *pevent, 38int parse_event_file(struct tep_handle *pevent,
39 char *buf, unsigned long size, char *sys); 39 char *buf, unsigned long size, char *sys);
40 40
41unsigned long long 41unsigned long long
42raw_field_value(struct event_format *event, const char *name, void *data); 42raw_field_value(struct event_format *event, const char *name, void *data);
43 43
44void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 44void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size);
45void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 45void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size);
46void parse_saved_cmdline(struct pevent *pevent, char *file, unsigned int size); 46void parse_saved_cmdline(struct tep_handle *pevent, char *file, unsigned int size);
47 47
48ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); 48ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
49 49
50struct event_format *trace_find_next_event(struct pevent *pevent, 50struct event_format *trace_find_next_event(struct tep_handle *pevent,
51 struct event_format *event); 51 struct event_format *event);
52unsigned long long read_size(struct event_format *event, void *ptr, int size); 52unsigned long long read_size(struct event_format *event, void *ptr, int size);
53unsigned long long eval_flag(const char *flag); 53unsigned long long eval_flag(const char *flag);
@@ -83,7 +83,7 @@ struct scripting_ops {
83 void (*process_stat)(struct perf_stat_config *config, 83 void (*process_stat)(struct perf_stat_config *config,
84 struct perf_evsel *evsel, u64 tstamp); 84 struct perf_evsel *evsel, u64 tstamp);
85 void (*process_stat_interval)(u64 tstamp); 85 void (*process_stat_interval)(u64 tstamp);
86 int (*generate_script) (struct pevent *pevent, const char *outfile); 86 int (*generate_script) (struct tep_handle *pevent, const char *outfile);
87}; 87};
88 88
89extern unsigned int scripting_max_stack; 89extern unsigned int scripting_max_stack;
@@ -94,7 +94,7 @@ void setup_perl_scripting(void);
94void setup_python_scripting(void); 94void setup_python_scripting(void);
95 95
96struct scripting_context { 96struct scripting_context {
97 struct pevent *pevent; 97 struct tep_handle *pevent;
98 void *event_data; 98 void *event_data;
99}; 99};
100 100
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
index a725b958cf31..902ce6384f57 100644
--- a/tools/perf/util/zlib.c
+++ b/tools/perf/util/zlib.c
@@ -5,6 +5,8 @@
5#include <sys/stat.h> 5#include <sys/stat.h>
6#include <sys/mman.h> 6#include <sys/mman.h>
7#include <zlib.h> 7#include <zlib.h>
8#include <linux/compiler.h>
9#include <unistd.h>
8 10
9#include "util/compress.h" 11#include "util/compress.h"
10#include "util/util.h" 12#include "util/util.h"
@@ -79,3 +81,19 @@ out_close:
79 81
80 return ret == Z_STREAM_END ? 0 : -1; 82 return ret == Z_STREAM_END ? 0 : -1;
81} 83}
84
85bool gzip_is_compressed(const char *input)
86{
87 int fd = open(input, O_RDONLY);
88 const uint8_t magic[2] = { 0x1f, 0x8b };
89 char buf[2] = { 0 };
90 ssize_t rc;
91
92 if (fd < 0)
93 return -1;
94
95 rc = read(fd, buf, sizeof(buf));
96 close(fd);
97 return rc == sizeof(buf) ?
98 memcmp(buf, magic, sizeof(buf)) == 0 : false;
99}