aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-annotate.txt11
-rw-r--r--tools/perf/Documentation/perf-c2c.txt2
-rw-r--r--tools/perf/Documentation/perf-data.txt2
-rw-r--r--tools/perf/Documentation/perf-ftrace.txt2
-rw-r--r--tools/perf/Documentation/perf-kallsyms.txt4
-rw-r--r--tools/perf/Documentation/perf-kmem.txt6
-rw-r--r--tools/perf/Documentation/perf-list.txt8
-rw-r--r--tools/perf/Documentation/perf-mem.txt4
-rw-r--r--tools/perf/Documentation/perf-record.txt15
-rw-r--r--tools/perf/Documentation/perf-report.txt8
-rw-r--r--tools/perf/Documentation/perf-sched.txt2
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt3
-rw-r--r--tools/perf/Documentation/perf-stat.txt33
-rw-r--r--tools/perf/Documentation/perf-top.txt7
-rw-r--r--tools/perf/Documentation/perf-trace.txt25
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt7
-rw-r--r--tools/perf/Makefile.config27
-rw-r--r--tools/perf/Makefile.perf16
-rw-r--r--tools/perf/arch/arm/util/auxtrace.c2
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c51
-rw-r--r--tools/perf/arch/arm64/include/arch-tests.h12
-rw-r--r--tools/perf/arch/arm64/tests/Build2
-rw-r--r--tools/perf/arch/arm64/tests/arch-tests.c16
-rw-r--r--tools/perf/arch/arm64/util/Build1
-rw-r--r--tools/perf/arch/arm64/util/unwind-libdw.c60
-rw-r--r--tools/perf/arch/powerpc/Makefile25
-rwxr-xr-xtools/perf/arch/powerpc/entry/syscalls/mksyscalltbl37
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c144
-rw-r--r--tools/perf/arch/s390/util/header.c148
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c10
-rw-r--r--tools/perf/arch/x86/util/auxtrace.c14
-rw-r--r--tools/perf/builtin-annotate.c109
-rw-r--r--tools/perf/builtin-c2c.c247
-rw-r--r--tools/perf/builtin-ftrace.c18
-rw-r--r--tools/perf/builtin-kvm.c16
-rw-r--r--tools/perf/builtin-record.c91
-rw-r--r--tools/perf/builtin-report.c65
-rw-r--r--tools/perf/builtin-sched.c133
-rw-r--r--tools/perf/builtin-script.c39
-rw-r--r--tools/perf/builtin-stat.c118
-rw-r--r--tools/perf/builtin-top.c21
-rw-r--r--tools/perf/builtin-trace.c60
-rwxr-xr-xtools/perf/check-headers.sh2
-rw-r--r--tools/perf/perf-sys.h4
-rw-r--r--tools/perf/perf.h4
-rw-r--r--tools/perf/pmu-events/Build2
-rw-r--r--tools/perf/pmu-events/README15
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json (renamed from tools/perf/pmu-events/arch/arm64/cortex-a53/branch.json)14
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json8
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json27
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json (renamed from tools/perf/pmu-events/arch/arm64/cortex-a53/memory.json)14
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json28
-rw-r--r--tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json (renamed from tools/perf/pmu-events/arch/arm64/cortex-a53/pipeline.json)20
-rw-r--r--tools/perf/pmu-events/arch/arm64/armv8-recommended.json452
-rw-r--r--tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json62
-rw-r--r--tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json32
-rw-r--r--tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json22
-rw-r--r--tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json27
-rw-r--r--tools/perf/pmu-events/arch/arm64/cortex-a53/other.json32
-rw-r--r--tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json122
-rw-r--r--tools/perf/pmu-events/arch/arm64/mapfile.csv6
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/cache.json25
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/frontend.json10
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/marked.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/memory.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/other.json241
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pipeline.json50
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/pmc.json5
-rw-r--r--tools/perf/pmu-events/arch/powerpc/power9/translation.json10
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z10/extended.json110
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z13/extended.json338
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/basic.json50
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z14/extended.json320
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_z196/extended.json146
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/basic.json74
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json98
-rw-r--r--tools/perf/pmu-events/arch/s390/cf_zec12/extended.json212
-rw-r--r--tools/perf/pmu-events/arch/s390/mapfile.csv6
-rw-r--r--tools/perf/pmu-events/jevents.c291
-rwxr-xr-xtools/perf/python/twatch.py8
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c34
-rw-r--r--tools/perf/tests/Build2
-rw-r--r--tools/perf/tests/attr.c4
-rw-r--r--tools/perf/tests/backward-ring-buffer.c5
-rw-r--r--tools/perf/tests/bp_account.c193
-rw-r--r--tools/perf/tests/bpf.c8
-rw-r--r--tools/perf/tests/builtin-test.c8
-rw-r--r--tools/perf/tests/code-reading.c43
-rw-r--r--tools/perf/tests/dwarf-unwind.c46
-rw-r--r--tools/perf/tests/keep-tracking.c9
-rw-r--r--tools/perf/tests/mem.c2
-rw-r--r--tools/perf/tests/mem2node.c75
-rw-r--r--tools/perf/tests/mmap-basic.c11
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c10
-rw-r--r--tools/perf/tests/perf-record.c10
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/shell/lib/probe_vfs_getname.sh2
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh (renamed from tools/perf/tests/shell/trace+probe_libc_inet_pton.sh)33
-rw-r--r--tools/perf/tests/sw-clock.c11
-rw-r--r--tools/perf/tests/switch-tracking.c10
-rw-r--r--tools/perf/tests/task-exit.c11
-rw-r--r--tools/perf/tests/tests.h2
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c4
-rw-r--r--tools/perf/ui/browser.c9
-rw-r--r--tools/perf/ui/browser.h3
-rw-r--r--tools/perf/ui/browsers/annotate.c725
-rw-r--r--tools/perf/ui/browsers/hists.c11
-rw-r--r--tools/perf/ui/stdio/hist.c6
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c739
-rw-r--r--tools/perf/util/annotate.h103
-rw-r--r--tools/perf/util/auxtrace.c52
-rw-r--r--tools/perf/util/auxtrace.h2
-rw-r--r--tools/perf/util/build-id.c10
-rw-r--r--tools/perf/util/cgroup.c128
-rw-r--r--tools/perf/util/cgroup.h13
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.c74
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.h2
-rw-r--r--tools/perf/util/cs-etm.c478
-rw-r--r--tools/perf/util/debug.c1
-rw-r--r--tools/perf/util/env.c4
-rw-r--r--tools/perf/util/env.h9
-rw-r--r--tools/perf/util/event.c16
-rw-r--r--tools/perf/util/evlist.c54
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c26
-rw-r--r--tools/perf/util/evsel.h6
-rw-r--r--tools/perf/util/header.c323
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/hist.c8
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c64
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h2
-rw-r--r--tools/perf/util/intel-pt.c110
-rw-r--r--tools/perf/util/llvm-utils.c14
-rw-r--r--tools/perf/util/machine.c139
-rw-r--r--tools/perf/util/machine.h6
-rw-r--r--tools/perf/util/mem2node.c134
-rw-r--r--tools/perf/util/mem2node.h19
-rw-r--r--tools/perf/util/mmap.c114
-rw-r--r--tools/perf/util/mmap.h16
-rw-r--r--tools/perf/util/parse-events.c25
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/parse-events.y18
-rw-r--r--tools/perf/util/pmu.c49
-rw-r--r--tools/perf/util/probe-finder.c13
-rw-r--r--tools/perf/util/python.c110
-rw-r--r--tools/perf/util/record.c51
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c147
-rw-r--r--tools/perf/util/setup.py8
-rw-r--r--tools/perf/util/sort.c7
-rw-r--r--tools/perf/util/stat.c2
-rw-r--r--tools/perf/util/stat.h4
-rw-r--r--tools/perf/util/symbol.c35
-rw-r--r--tools/perf/util/symbol.h19
-rw-r--r--tools/perf/util/syscalltbl.c8
-rw-r--r--tools/perf/util/thread.h1
-rw-r--r--tools/perf/util/thread_map.c5
-rw-r--r--tools/perf/util/thread_map.h3
-rw-r--r--tools/perf/util/trigger.h9
-rw-r--r--tools/perf/util/unwind-libdw.c5
170 files changed, 7703 insertions, 1917 deletions
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index c635eab6af54..749cc6055dac 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -21,7 +21,7 @@ If there is no debug info in the object, then annotated assembly is displayed.
21OPTIONS 21OPTIONS
22------- 22-------
23-i:: 23-i::
24--input=:: 24--input=<file>::
25 Input file name. (default: perf.data unless stdin is a fifo) 25 Input file name. (default: perf.data unless stdin is a fifo)
26 26
27-d:: 27-d::
@@ -55,6 +55,9 @@ OPTIONS
55--vmlinux=<file>:: 55--vmlinux=<file>::
56 vmlinux pathname. 56 vmlinux pathname.
57 57
58--ignore-vmlinux::
59 Ignore vmlinux files.
60
58-m:: 61-m::
59--modules:: 62--modules::
60 Load module symbols. WARNING: use only with -k and LIVE kernel. 63 Load module symbols. WARNING: use only with -k and LIVE kernel.
@@ -69,7 +72,9 @@ OPTIONS
69 72
70--stdio:: Use the stdio interface. 73--stdio:: Use the stdio interface.
71 74
72--stdio-color:: 75--stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting.
76
77--stdio-color=<mode>::
73 'always', 'never' or 'auto', allowing configuring color output 78 'always', 'never' or 'auto', allowing configuring color output
74 via the command line, in addition to via "color.ui" .perfconfig. 79 via the command line, in addition to via "color.ui" .perfconfig.
75 Use '--stdio-color always' to generate color even when redirecting 80 Use '--stdio-color always' to generate color even when redirecting
@@ -84,7 +89,7 @@ OPTIONS
84--gtk:: Use the GTK interface. 89--gtk:: Use the GTK interface.
85 90
86-C:: 91-C::
87--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 92--cpu=<cpu>:: Only report samples for the list of CPUs provided. Multiple CPUs can
88 be provided as a comma-separated list with no space: 0,1. Ranges of 93 be provided as a comma-separated list with no space: 0,1. Ranges of
89 CPUs are specified with -: 0-2. Default is to report samples on all 94 CPUs are specified with -: 0-2. Default is to report samples on all
90 CPUs. 95 CPUs.
diff --git a/tools/perf/Documentation/perf-c2c.txt b/tools/perf/Documentation/perf-c2c.txt
index 822414235170..095aebdc5bb7 100644
--- a/tools/perf/Documentation/perf-c2c.txt
+++ b/tools/perf/Documentation/perf-c2c.txt
@@ -116,7 +116,7 @@ and calls standard perf record command.
116Following perf record options are configured by default: 116Following perf record options are configured by default:
117(check perf record man page for details) 117(check perf record man page for details)
118 118
119 -W,-d,--sample-cpu 119 -W,-d,--phys-data,--sample-cpu
120 120
121Unless specified otherwise with '-e' option, following events are monitored by 121Unless specified otherwise with '-e' option, following events are monitored by
122default: 122default:
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt
index 90bb4aabe4f8..c87180764829 100644
--- a/tools/perf/Documentation/perf-data.txt
+++ b/tools/perf/Documentation/perf-data.txt
@@ -1,5 +1,5 @@
1perf-data(1) 1perf-data(1)
2============== 2============
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-ftrace.txt b/tools/perf/Documentation/perf-ftrace.txt
index 721a447f046e..b80c84307dc9 100644
--- a/tools/perf/Documentation/perf-ftrace.txt
+++ b/tools/perf/Documentation/perf-ftrace.txt
@@ -1,5 +1,5 @@
1perf-ftrace(1) 1perf-ftrace(1)
2============= 2==============
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-kallsyms.txt b/tools/perf/Documentation/perf-kallsyms.txt
index 954ea9e21236..f3c620951f6e 100644
--- a/tools/perf/Documentation/perf-kallsyms.txt
+++ b/tools/perf/Documentation/perf-kallsyms.txt
@@ -1,5 +1,5 @@
1perf-kallsyms(1) 1perf-kallsyms(1)
2============== 2================
3 3
4NAME 4NAME
5---- 5----
@@ -8,7 +8,7 @@ perf-kallsyms - Searches running kernel for symbols
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf kallsyms <options> symbol_name[,symbol_name...]' 11'perf kallsyms' [<options>] symbol_name[,symbol_name...]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index 479fc3261a50..85b8ac695c87 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -25,6 +25,10 @@ OPTIONS
25--input=<file>:: 25--input=<file>::
26 Select the input file (default: perf.data unless stdin is a fifo) 26 Select the input file (default: perf.data unless stdin is a fifo)
27 27
28-f::
29--force::
30 Don't do ownership validation
31
28-v:: 32-v::
29--verbose:: 33--verbose::
30 Be more verbose. (show symbol address, etc) 34 Be more verbose. (show symbol address, etc)
@@ -61,7 +65,7 @@ OPTIONS
61 default, but this option shows live (currently allocated) pages 65 default, but this option shows live (currently allocated) pages
62 instead. (This option works with --page option only) 66 instead. (This option works with --page option only)
63 67
64--time:: 68--time=<start>,<stop>::
65 Only analyze samples within given time window: <start>,<stop>. Times 69 Only analyze samples within given time window: <start>,<stop>. Times
66 have the format seconds.microseconds. If start is not given (i.e., time 70 have the format seconds.microseconds. If start is not given (i.e., time
67 string is ',x.y') then analysis starts at the beginning of the file. If 71 string is ',x.y') then analysis starts at the beginning of the file. If
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index e2a897ae3596..2549c34a7895 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -141,7 +141,13 @@ on the first memory controller on socket 0 of a Intel Xeon system
141 141
142Each memory controller has its own PMU. Measuring the complete system 142Each memory controller has its own PMU. Measuring the complete system
143bandwidth would require specifying all imc PMUs (see perf list output), 143bandwidth would require specifying all imc PMUs (see perf list output),
144and adding the values together. 144and adding the values together. To simplify creation of multiple events,
145prefix and glob matching is supported in the PMU name, and the prefix
146'uncore_' is also ignored when performing the match. So the command above
147can be expanded to all memory controllers by using the syntaxes:
148
149 perf stat -C 0 -a imc/cas_count_read/,imc/cas_count_write/ -I 1000 ...
150 perf stat -C 0 -a *imc*/cas_count_read/,*imc*/cas_count_write/ -I 1000 ...
145 151
146This example measures the combined core power every second 152This example measures the combined core power every second
147 153
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 4be08a1e3f8d..b0211410969b 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -28,6 +28,10 @@ OPTIONS
28<command>...:: 28<command>...::
29 Any command you can specify in a shell. 29 Any command you can specify in a shell.
30 30
31-f::
32--force::
33 Don't do ownership validation
34
31-t:: 35-t::
32--type=:: 36--type=::
33 Select the memory operation type: load or store (default: load,store) 37 Select the memory operation type: load or store (default: load,store)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 3eea6de35a38..cc37b3a4be76 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -191,9 +191,16 @@ OPTIONS
191-i:: 191-i::
192--no-inherit:: 192--no-inherit::
193 Child tasks do not inherit counters. 193 Child tasks do not inherit counters.
194
194-F:: 195-F::
195--freq=:: 196--freq=::
196 Profile at this frequency. 197 Profile at this frequency. Use 'max' to use the currently maximum
198 allowed frequency, i.e. the value in the kernel.perf_event_max_sample_rate
199 sysctl. Will throttle down to the currently maximum allowed frequency.
200 See --strict-freq.
201
202--strict-freq::
203 Fail if the specified frequency can't be used.
197 204
198-m:: 205-m::
199--mmap-pages=:: 206--mmap-pages=::
@@ -308,7 +315,11 @@ can be provided. Each cgroup is applied to the corresponding event, i.e., first
308to first event, second cgroup to second event and so on. It is possible to provide 315to first event, second cgroup to second event and so on. It is possible to provide
309an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have 316an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
310corresponding events, i.e., they always refer to events defined earlier on the command 317corresponding events, i.e., they always refer to events defined earlier on the command
311line. 318line. If the user wants to track multiple events for a specific cgroup, the user can
319use '-e e1 -e e2 -G foo,foo' or just use '-e e1 -e e2 -G foo'.
320
321If wanting to monitor, say, 'cycles' for a cgroup and also for system wide, this
322command line can be used: 'perf stat -e cycles -G cgroup_name -a -e cycles'.
312 323
313-b:: 324-b::
314--branch-any:: 325--branch-any::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 907e505b6309..e1a660e60849 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -296,6 +296,9 @@ OPTIONS
296--vmlinux=<file>:: 296--vmlinux=<file>::
297 vmlinux pathname 297 vmlinux pathname
298 298
299--ignore-vmlinux::
300 Ignore vmlinux files.
301
299--kallsyms=<file>:: 302--kallsyms=<file>::
300 kallsyms pathname 303 kallsyms pathname
301 304
@@ -354,7 +357,8 @@ OPTIONS
354 Path to objdump binary. 357 Path to objdump binary.
355 358
356--group:: 359--group::
357 Show event group information together. 360 Show event group information together. It forces group output also
361 if there are no groups defined in data file.
358 362
359--demangle:: 363--demangle::
360 Demangle symbol names to human readable form. It's enabled by default, 364 Demangle symbol names to human readable form. It's enabled by default,
@@ -367,7 +371,7 @@ OPTIONS
367 Use the data addresses of samples in addition to instruction addresses 371 Use the data addresses of samples in addition to instruction addresses
368 to build the histograms. To generate meaningful output, the perf.data 372 to build the histograms. To generate meaningful output, the perf.data
369 file must have been obtained using perf record -d -W and using a 373 file must have been obtained using perf record -d -W and using a
370 special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See 374 special event -e cpu/mem-loads/p or -e cpu/mem-stores/p. See
371 'perf mem' for simpler access. 375 'perf mem' for simpler access.
372 376
373--percent-limit:: 377--percent-limit::
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index c7e50f263887..bb33601a823b 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -1,5 +1,5 @@
1perf-sched(1) 1perf-sched(1)
2============== 2=============
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index 142606c0ec9c..5a1f68122f50 100644
--- a/tools/perf/Documentation/perf-script-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -1,5 +1,5 @@
1perf-script-perl(1) 1perf-script-perl(1)
2================== 2===================
3 3
4NAME 4NAME
5---- 5----
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 7730c1d2b5d3..36ec0257f8d3 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -303,6 +303,9 @@ OPTIONS
303--show-lost-events 303--show-lost-events
304 Display lost events i.e. events of type PERF_RECORD_LOST. 304 Display lost events i.e. events of type PERF_RECORD_LOST.
305 305
306--show-round-events
307 Display finished round events i.e. events of type PERF_RECORD_FINISHED_ROUND.
308
306--demangle:: 309--demangle::
307 Demangle symbol names to human readable form. It's enabled by default, 310 Demangle symbol names to human readable form. It's enabled by default,
308 disable with --no-demangle. 311 disable with --no-demangle.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 823fce7674bb..f15b306be183 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -49,6 +49,13 @@ report::
49 parameters are defined by corresponding entries in 49 parameters are defined by corresponding entries in
50 /sys/bus/event_source/devices/<pmu>/format/* 50 /sys/bus/event_source/devices/<pmu>/format/*
51 51
52 Note that the last two syntaxes support prefix and glob matching in
53 the PMU name to simplify creation of events accross multiple instances
54 of the same type of PMU in large systems (e.g. memory controller PMUs).
55 Multiple PMU instances are typical for uncore PMUs, so the prefix
56 'uncore_' is also ignored when performing this match.
57
58
52-i:: 59-i::
53--no-inherit:: 60--no-inherit::
54 child tasks do not inherit counters 61 child tasks do not inherit counters
@@ -118,7 +125,11 @@ can be provided. Each cgroup is applied to the corresponding event, i.e., first
118to first event, second cgroup to second event and so on. It is possible to provide 125to first event, second cgroup to second event and so on. It is possible to provide
119an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have 126an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
120corresponding events, i.e., they always refer to events defined earlier on the command 127corresponding events, i.e., they always refer to events defined earlier on the command
121line. 128line. If the user wants to track multiple events for a specific cgroup, the user can
129use '-e e1 -e e2 -G foo,foo' or just use '-e e1 -e e2 -G foo'.
130
131If wanting to monitor, say, 'cycles' for a cgroup and also for system wide, this
132command line can be used: 'perf stat -e cycles -G cgroup_name -a -e cycles'.
122 133
123-o file:: 134-o file::
124--output file:: 135--output file::
@@ -146,6 +157,16 @@ Print count deltas every N milliseconds (minimum: 10ms)
146The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution. 157The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution.
147 example: 'perf stat -I 1000 -e cycles -a sleep 5' 158 example: 'perf stat -I 1000 -e cycles -a sleep 5'
148 159
160--interval-count times::
161Print count deltas for fixed number of times.
162This option should be used together with "-I" option.
163 example: 'perf stat -I 1000 --interval-count 2 -e cycles -a'
164
165--timeout msecs::
166Stop the 'perf stat' session and print count deltas after N milliseconds (minimum: 10 ms).
167This option is not supported with the "-I" option.
168 example: 'perf stat --time 2000 -e cycles -a'
169
149--metric-only:: 170--metric-only::
150Only print computed metrics. Print them in a single line. 171Only print computed metrics. Print them in a single line.
151Don't show any raw values. Not supported with --per-thread. 172Don't show any raw values. Not supported with --per-thread.
@@ -246,6 +267,16 @@ taskset.
246--no-merge:: 267--no-merge::
247Do not merge results from same PMUs. 268Do not merge results from same PMUs.
248 269
270When multiple events are created from a single event specification,
271stat will, by default, aggregate the event counts and show the result
272in a single row. This option disables that behavior and shows
273the individual events and counts.
274
275Multiple events are created from a single event specification when:
2761. Prefix or glob matching is used for the PMU name.
2772. Aliases, which are listed immediately after the Kernel PMU events
278 by perf list, are used.
279
249--smi-cost:: 280--smi-cost::
250Measure SMI cost if msr/aperf/ and msr/smi/ events are supported. 281Measure SMI cost if msr/aperf/ and msr/smi/ events are supported.
251 282
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 8a32cc77bead..114fda12aa49 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -55,7 +55,9 @@ Default is to monitor all CPUS.
55 55
56-F <freq>:: 56-F <freq>::
57--freq=<freq>:: 57--freq=<freq>::
58 Profile at this frequency. 58 Profile at this frequency. Use 'max' to use the currently maximum
59 allowed frequency, i.e. the value in the kernel.perf_event_max_sample_rate
60 sysctl.
59 61
60-i:: 62-i::
61--inherit:: 63--inherit::
@@ -65,6 +67,9 @@ Default is to monitor all CPUS.
65--vmlinux=<path>:: 67--vmlinux=<path>::
66 Path to vmlinux. Required for annotation functionality. 68 Path to vmlinux. Required for annotation functionality.
67 69
70--ignore-vmlinux::
71 Ignore vmlinux files.
72
68-m <pages>:: 73-m <pages>::
69--mmap-pages=<pages>:: 74--mmap-pages=<pages>::
70 Number of mmap data pages (must be a power of two) or size 75 Number of mmap data pages (must be a power of two) or size
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 33a88e984e66..5a7035c5c523 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -63,6 +63,31 @@ filter out the startup phase of the program, which is often very different.
63--uid=:: 63--uid=::
64 Record events in threads owned by uid. Name or number. 64 Record events in threads owned by uid. Name or number.
65 65
66-G::
67--cgroup::
68 Record events in threads in a cgroup.
69
70 Look for cgroups to set at the /sys/fs/cgroup/perf_event directory, then
71 remove the /sys/fs/cgroup/perf_event/ part and try:
72
73 perf trace -G A -e sched:*switch
74
75 Will set all raw_syscalls:sys_{enter,exit}, pgfault, vfs_getname, etc
76 _and_ sched:sched_switch to the 'A' cgroup, while:
77
78 perf trace -e sched:*switch -G A
79
80 will only set the sched:sched_switch event to the 'A' cgroup, all the
81 other events (raw_syscalls:sys_{enter,exit}, etc are left "without"
82 a cgroup (on the root cgroup, sys wide, etc).
83
84 Multiple cgroups:
85
86 perf trace -G A -e sched:*switch -G B
87
88 the syscall ones go to the 'A' cgroup, the sched:sched_switch goes
89 to the 'B' cgroup.
90
66--filter-pids=:: 91--filter-pids=::
67 Filter out events for these pids and for 'trace' itself (comma separated list). 92 Filter out events for these pids and for 'trace' itself (comma separated list).
68 93
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index f7d85e89a98a..d00f0d51cab8 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -485,10 +485,5 @@ in pmu-tools parser. This allows to read perf.data from python and dump it.
485quipper 485quipper
486 486
487The quipper C++ parser is available at 487The quipper C++ parser is available at
488https://chromium.googlesource.com/chromiumos/platform2 488http://github.com/google/perf_data_converter/tree/master/src/quipper
489 489
490It is under the chromiumos-wide-profiling/ subdirectory. This library can
491convert a perf data file to a protobuf and vice versa.
492
493Unfortunately this parser tends to be many versions behind and may not be able
494to parse data files generated by recent perf.
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 0dfdaa9fa81e..98ff73648b51 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -27,6 +27,8 @@ NO_SYSCALL_TABLE := 1
27# Additional ARCH settings for ppc 27# Additional ARCH settings for ppc
28ifeq ($(SRCARCH),powerpc) 28ifeq ($(SRCARCH),powerpc)
29 NO_PERF_REGS := 0 29 NO_PERF_REGS := 0
30 NO_SYSCALL_TABLE := 0
31 CFLAGS += -I$(OUTPUT)arch/powerpc/include/generated
30 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64 32 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
31endif 33endif
32 34
@@ -73,7 +75,7 @@ endif
73# Disable it on all other architectures in case libdw unwind 75# Disable it on all other architectures in case libdw unwind
74# support is detected in system. Add supported architectures 76# support is detected in system. Add supported architectures
75# to the check. 77# to the check.
76ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm powerpc s390)) 78ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390))
77 NO_LIBDW_DWARF_UNWIND := 1 79 NO_LIBDW_DWARF_UNWIND := 1
78endif 80endif
79 81
@@ -666,25 +668,10 @@ else
666 ifneq ($(feature-libpython), 1) 668 ifneq ($(feature-libpython), 1)
667 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev) 669 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
668 else 670 else
669 ifneq ($(feature-libpython-version), 1) 671 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
670 $(warning Python 3 is not yet supported; please set) 672 EXTLIBS += $(PYTHON_EMBED_LIBADD)
671 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 673 LANG_BINDINGS += $(obj-perf)python/perf.so
672 $(warning If you also have Python 2 installed, then) 674 $(call detected,CONFIG_LIBPYTHON)
673 $(warning try something like:)
674 $(warning $(and ,))
675 $(warning $(and ,) make PYTHON=python2)
676 $(warning $(and ,))
677 $(warning Otherwise, disable Python support entirely:)
678 $(warning $(and ,))
679 $(warning $(and ,) make NO_LIBPYTHON=1)
680 $(warning $(and ,))
681 $(error $(and ,))
682 else
683 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
684 EXTLIBS += $(PYTHON_EMBED_LIBADD)
685 LANG_BINDINGS += $(obj-perf)python/perf.so
686 $(call detected,CONFIG_LIBPYTHON)
687 endif
688 endif 675 endif
689 endif 676 endif
690 endif 677 endif
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9b0351d3ce34..f7517e1b73f8 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -146,12 +146,6 @@ define allow-override
146 $(eval $(1) = $(2))) 146 $(eval $(1) = $(2)))
147endef 147endef
148 148
149# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
150$(call allow-override,CC,$(CROSS_COMPILE)gcc)
151$(call allow-override,AR,$(CROSS_COMPILE)ar)
152$(call allow-override,LD,$(CROSS_COMPILE)ld)
153$(call allow-override,CXX,$(CROSS_COMPILE)g++)
154
155LD += $(EXTRA_LDFLAGS) 149LD += $(EXTRA_LDFLAGS)
156 150
157HOSTCC ?= gcc 151HOSTCC ?= gcc
@@ -302,7 +296,7 @@ PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
302PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/ 296PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
303export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP 297export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
304 298
305python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 299python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so
306 300
307PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 301PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
308PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) 302PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
@@ -479,7 +473,7 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_D
479 $(PYTHON_WORD) util/setup.py \ 473 $(PYTHON_WORD) util/setup.py \
480 --quiet build_ext; \ 474 --quiet build_ext; \
481 mkdir -p $(OUTPUT)python && \ 475 mkdir -p $(OUTPUT)python && \
482 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ 476 cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/
483 477
484please_set_SHELL_PATH_to_a_more_modern_shell: 478please_set_SHELL_PATH_to_a_more_modern_shell:
485 $(Q)$$(:) 479 $(Q)$$(:)
@@ -714,15 +708,15 @@ TAG_FILES= ../../include/uapi/linux/perf_event.h
714 708
715TAGS: 709TAGS:
716 $(QUIET_GEN)$(RM) TAGS; \ 710 $(QUIET_GEN)$(RM) TAGS; \
717 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs etags -a $(TAG_FILES) 711 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs etags -a $(TAG_FILES)
718 712
719tags: 713tags:
720 $(QUIET_GEN)$(RM) tags; \ 714 $(QUIET_GEN)$(RM) tags; \
721 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs ctags -a $(TAG_FILES) 715 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs ctags -a $(TAG_FILES)
722 716
723cscope: 717cscope:
724 $(QUIET_GEN)$(RM) cscope*; \ 718 $(QUIET_GEN)$(RM) cscope*; \
725 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES) 719 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print -o -name '*.cpp' -print | xargs cscope -b $(TAG_FILES)
726 720
727### Testing rules 721### Testing rules
728 722
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
index 2323581b157d..fa639e3e52ac 100644
--- a/tools/perf/arch/arm/util/auxtrace.c
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -68,7 +68,7 @@ struct auxtrace_record
68 bool found_spe = false; 68 bool found_spe = false;
69 static struct perf_pmu **arm_spe_pmus = NULL; 69 static struct perf_pmu **arm_spe_pmus = NULL;
70 static int nr_spes = 0; 70 static int nr_spes = 0;
71 int i; 71 int i = 0;
72 72
73 if (!evlist) 73 if (!evlist)
74 return NULL; 74 return NULL;
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
index fbfc055d3f4d..5c655ad4621e 100644
--- a/tools/perf/arch/arm/util/cs-etm.c
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -298,12 +298,17 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
298{ 298{
299 int i; 299 int i;
300 int etmv3 = 0, etmv4 = 0; 300 int etmv3 = 0, etmv4 = 0;
301 const struct cpu_map *cpus = evlist->cpus; 301 struct cpu_map *event_cpus = evlist->cpus;
302 struct cpu_map *online_cpus = cpu_map__new(NULL);
302 303
303 /* cpu map is not empty, we have specific CPUs to work with */ 304 /* cpu map is not empty, we have specific CPUs to work with */
304 if (!cpu_map__empty(cpus)) { 305 if (!cpu_map__empty(event_cpus)) {
305 for (i = 0; i < cpu_map__nr(cpus); i++) { 306 for (i = 0; i < cpu__max_cpu(); i++) {
306 if (cs_etm_is_etmv4(itr, cpus->map[i])) 307 if (!cpu_map__has(event_cpus, i) ||
308 !cpu_map__has(online_cpus, i))
309 continue;
310
311 if (cs_etm_is_etmv4(itr, i))
307 etmv4++; 312 etmv4++;
308 else 313 else
309 etmv3++; 314 etmv3++;
@@ -311,6 +316,9 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
311 } else { 316 } else {
312 /* get configuration for all CPUs in the system */ 317 /* get configuration for all CPUs in the system */
313 for (i = 0; i < cpu__max_cpu(); i++) { 318 for (i = 0; i < cpu__max_cpu(); i++) {
319 if (!cpu_map__has(online_cpus, i))
320 continue;
321
314 if (cs_etm_is_etmv4(itr, i)) 322 if (cs_etm_is_etmv4(itr, i))
315 etmv4++; 323 etmv4++;
316 else 324 else
@@ -318,6 +326,8 @@ cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
318 } 326 }
319 } 327 }
320 328
329 cpu_map__put(online_cpus);
330
321 return (CS_ETM_HEADER_SIZE + 331 return (CS_ETM_HEADER_SIZE +
322 (etmv4 * CS_ETMV4_PRIV_SIZE) + 332 (etmv4 * CS_ETMV4_PRIV_SIZE) +
323 (etmv3 * CS_ETMV3_PRIV_SIZE)); 333 (etmv3 * CS_ETMV3_PRIV_SIZE));
@@ -447,7 +457,9 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
447 int i; 457 int i;
448 u32 offset; 458 u32 offset;
449 u64 nr_cpu, type; 459 u64 nr_cpu, type;
450 const struct cpu_map *cpus = session->evlist->cpus; 460 struct cpu_map *cpu_map;
461 struct cpu_map *event_cpus = session->evlist->cpus;
462 struct cpu_map *online_cpus = cpu_map__new(NULL);
451 struct cs_etm_recording *ptr = 463 struct cs_etm_recording *ptr =
452 container_of(itr, struct cs_etm_recording, itr); 464 container_of(itr, struct cs_etm_recording, itr);
453 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; 465 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
@@ -458,8 +470,21 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
458 if (!session->evlist->nr_mmaps) 470 if (!session->evlist->nr_mmaps)
459 return -EINVAL; 471 return -EINVAL;
460 472
461 /* If the cpu_map is empty all CPUs are involved */ 473 /* If the cpu_map is empty all online CPUs are involved */
462 nr_cpu = cpu_map__empty(cpus) ? cpu__max_cpu() : cpu_map__nr(cpus); 474 if (cpu_map__empty(event_cpus)) {
475 cpu_map = online_cpus;
476 } else {
477 /* Make sure all specified CPUs are online */
478 for (i = 0; i < cpu_map__nr(event_cpus); i++) {
479 if (cpu_map__has(event_cpus, i) &&
480 !cpu_map__has(online_cpus, i))
481 return -EINVAL;
482 }
483
484 cpu_map = event_cpus;
485 }
486
487 nr_cpu = cpu_map__nr(cpu_map);
463 /* Get PMU type as dynamically assigned by the core */ 488 /* Get PMU type as dynamically assigned by the core */
464 type = cs_etm_pmu->type; 489 type = cs_etm_pmu->type;
465 490
@@ -472,15 +497,11 @@ static int cs_etm_info_fill(struct auxtrace_record *itr,
472 497
473 offset = CS_ETM_SNAPSHOT + 1; 498 offset = CS_ETM_SNAPSHOT + 1;
474 499
475 /* cpu map is not empty, we have specific CPUs to work with */ 500 for (i = 0; i < cpu__max_cpu() && offset < priv_size; i++)
476 if (!cpu_map__empty(cpus)) { 501 if (cpu_map__has(cpu_map, i))
477 for (i = 0; i < cpu_map__nr(cpus) && offset < priv_size; i++)
478 cs_etm_get_metadata(cpus->map[i], &offset, itr, info);
479 } else {
480 /* get configuration for all CPUs in the system */
481 for (i = 0; i < cpu__max_cpu(); i++)
482 cs_etm_get_metadata(i, &offset, itr, info); 502 cs_etm_get_metadata(i, &offset, itr, info);
483 } 503
504 cpu_map__put(online_cpus);
484 505
485 return 0; 506 return 0;
486} 507}
diff --git a/tools/perf/arch/arm64/include/arch-tests.h b/tools/perf/arch/arm64/include/arch-tests.h
new file mode 100644
index 000000000000..90ec4c8cb880
--- /dev/null
+++ b/tools/perf/arch/arm64/include/arch-tests.h
@@ -0,0 +1,12 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef ARCH_TESTS_H
3#define ARCH_TESTS_H
4
5#ifdef HAVE_DWARF_UNWIND_SUPPORT
6struct thread;
7struct perf_sample;
8#endif
9
10extern struct test arch_tests[];
11
12#endif
diff --git a/tools/perf/arch/arm64/tests/Build b/tools/perf/arch/arm64/tests/Build
index b30eff9bcc83..883c57ff0c08 100644
--- a/tools/perf/arch/arm64/tests/Build
+++ b/tools/perf/arch/arm64/tests/Build
@@ -1,2 +1,4 @@
1libperf-y += regs_load.o 1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o 2libperf-y += dwarf-unwind.o
3
4libperf-y += arch-tests.o
diff --git a/tools/perf/arch/arm64/tests/arch-tests.c b/tools/perf/arch/arm64/tests/arch-tests.c
new file mode 100644
index 000000000000..5b1543c98022
--- /dev/null
+++ b/tools/perf/arch/arm64/tests/arch-tests.c
@@ -0,0 +1,16 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <string.h>
3#include "tests/tests.h"
4#include "arch-tests.h"
5
6struct test arch_tests[] = {
7#ifdef HAVE_DWARF_UNWIND_SUPPORT
8 {
9 .desc = "DWARF unwind",
10 .func = test__dwarf_unwind,
11 },
12#endif
13 {
14 .func = NULL,
15 },
16};
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index c0b8dfef98ba..68f8a8eb3ad0 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -2,6 +2,7 @@ libperf-y += header.o
2libperf-y += sym-handling.o 2libperf-y += sym-handling.o
3libperf-$(CONFIG_DWARF) += dwarf-regs.o 3libperf-$(CONFIG_DWARF) += dwarf-regs.o
4libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 4libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
5libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
5 6
6libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \ 7libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
7 ../../arm/util/auxtrace.o \ 8 ../../arm/util/auxtrace.o \
diff --git a/tools/perf/arch/arm64/util/unwind-libdw.c b/tools/perf/arch/arm64/util/unwind-libdw.c
new file mode 100644
index 000000000000..7623d85e77f3
--- /dev/null
+++ b/tools/perf/arch/arm64/util/unwind-libdw.c
@@ -0,0 +1,60 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <elfutils/libdwfl.h>
3#include "../../util/unwind-libdw.h"
4#include "../../util/perf_regs.h"
5#include "../../util/event.h"
6
7bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
8{
9 struct unwind_info *ui = arg;
10 struct regs_dump *user_regs = &ui->sample->user_regs;
11 Dwarf_Word dwarf_regs[PERF_REG_ARM64_MAX], dwarf_pc;
12
13#define REG(r) ({ \
14 Dwarf_Word val = 0; \
15 perf_reg_value(&val, user_regs, PERF_REG_ARM64_##r); \
16 val; \
17})
18
19 dwarf_regs[0] = REG(X0);
20 dwarf_regs[1] = REG(X1);
21 dwarf_regs[2] = REG(X2);
22 dwarf_regs[3] = REG(X3);
23 dwarf_regs[4] = REG(X4);
24 dwarf_regs[5] = REG(X5);
25 dwarf_regs[6] = REG(X6);
26 dwarf_regs[7] = REG(X7);
27 dwarf_regs[8] = REG(X8);
28 dwarf_regs[9] = REG(X9);
29 dwarf_regs[10] = REG(X10);
30 dwarf_regs[11] = REG(X11);
31 dwarf_regs[12] = REG(X12);
32 dwarf_regs[13] = REG(X13);
33 dwarf_regs[14] = REG(X14);
34 dwarf_regs[15] = REG(X15);
35 dwarf_regs[16] = REG(X16);
36 dwarf_regs[17] = REG(X17);
37 dwarf_regs[18] = REG(X18);
38 dwarf_regs[19] = REG(X19);
39 dwarf_regs[20] = REG(X20);
40 dwarf_regs[21] = REG(X21);
41 dwarf_regs[22] = REG(X22);
42 dwarf_regs[23] = REG(X23);
43 dwarf_regs[24] = REG(X24);
44 dwarf_regs[25] = REG(X25);
45 dwarf_regs[26] = REG(X26);
46 dwarf_regs[27] = REG(X27);
47 dwarf_regs[28] = REG(X28);
48 dwarf_regs[29] = REG(X29);
49 dwarf_regs[30] = REG(LR);
50 dwarf_regs[31] = REG(SP);
51
52 if (!dwfl_thread_state_registers(thread, 0, PERF_REG_ARM64_MAX,
53 dwarf_regs))
54 return false;
55
56 dwarf_pc = REG(PC);
57 dwfl_thread_state_register_pc(thread, dwarf_pc);
58
59 return true;
60}
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 42dab7c8f508..a111239df182 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -6,3 +6,28 @@ endif
6HAVE_KVM_STAT_SUPPORT := 1 6HAVE_KVM_STAT_SUPPORT := 1
7PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 7PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
8PERF_HAVE_JITDUMP := 1 8PERF_HAVE_JITDUMP := 1
9
10#
11# Syscall table generation for perf
12#
13
14out := $(OUTPUT)arch/powerpc/include/generated/asm
15header32 := $(out)/syscalls_32.c
16header64 := $(out)/syscalls_64.c
17sysdef := $(srctree)/tools/arch/powerpc/include/uapi/asm/unistd.h
18sysprf := $(srctree)/tools/perf/arch/powerpc/entry/syscalls/
19systbl := $(sysprf)/mksyscalltbl
20
21# Create output directory if not already present
22_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
23
24$(header64): $(sysdef) $(systbl)
25 $(Q)$(SHELL) '$(systbl)' '64' '$(CC)' $(sysdef) > $@
26
27$(header32): $(sysdef) $(systbl)
28 $(Q)$(SHELL) '$(systbl)' '32' '$(CC)' $(sysdef) > $@
29
30clean::
31 $(call QUIET_CLEAN, powerpc) $(RM) $(header32) $(header64)
32
33archheaders: $(header32) $(header64)
diff --git a/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl b/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl
new file mode 100755
index 000000000000..ef52e1dd694b
--- /dev/null
+++ b/tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl
@@ -0,0 +1,37 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# Generate system call table for perf. Derived from
5# s390 script.
6#
7# Copyright IBM Corp. 2017
8# Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
9# Changed by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
10
11wordsize=$1
12gcc=$2
13input=$3
14
15if ! test -r $input; then
16 echo "Could not read input file" >&2
17 exit 1
18fi
19
20create_table()
21{
22 local wordsize=$1
23 local max_nr
24
25 echo "static const char *syscalltbl_powerpc_${wordsize}[] = {"
26 while read sc nr; do
27 printf '\t[%d] = "%s",\n' $nr $sc
28 max_nr=$nr
29 done
30 echo '};'
31 echo "#define SYSCALLTBL_POWERPC_${wordsize}_MAX_ID $max_nr"
32}
33
34$gcc -m${wordsize} -E -dM -x c $input \
35 |sed -ne 's/^#define __NR_//p' \
36 |sort -t' ' -k2 -nu \
37 |create_table ${wordsize}
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index 8c72b44444cb..cee4e2f7c057 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -1,6 +1,113 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compiler.h> 2#include <linux/compiler.h>
3 3
4static int s390_call__parse(struct arch *arch, struct ins_operands *ops,
5 struct map_symbol *ms)
6{
7 char *endptr, *tok, *name;
8 struct map *map = ms->map;
9 struct addr_map_symbol target = {
10 .map = map,
11 };
12
13 tok = strchr(ops->raw, ',');
14 if (!tok)
15 return -1;
16
17 ops->target.addr = strtoull(tok + 1, &endptr, 16);
18
19 name = strchr(endptr, '<');
20 if (name == NULL)
21 return -1;
22
23 name++;
24
25 if (arch->objdump.skip_functions_char &&
26 strchr(name, arch->objdump.skip_functions_char))
27 return -1;
28
29 tok = strchr(name, '>');
30 if (tok == NULL)
31 return -1;
32
33 *tok = '\0';
34 ops->target.name = strdup(name);
35 *tok = '>';
36
37 if (ops->target.name == NULL)
38 return -1;
39 target.addr = map__objdump_2mem(map, ops->target.addr);
40
41 if (map_groups__find_ams(&target) == 0 &&
42 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
43 ops->target.sym = target.sym;
44
45 return 0;
46}
47
48static int call__scnprintf(struct ins *ins, char *bf, size_t size,
49 struct ins_operands *ops);
50
51static struct ins_ops s390_call_ops = {
52 .parse = s390_call__parse,
53 .scnprintf = call__scnprintf,
54};
55
56static int s390_mov__parse(struct arch *arch __maybe_unused,
57 struct ins_operands *ops,
58 struct map_symbol *ms __maybe_unused)
59{
60 char *s = strchr(ops->raw, ','), *target, *endptr;
61
62 if (s == NULL)
63 return -1;
64
65 *s = '\0';
66 ops->source.raw = strdup(ops->raw);
67 *s = ',';
68
69 if (ops->source.raw == NULL)
70 return -1;
71
72 target = ++s;
73 ops->target.raw = strdup(target);
74 if (ops->target.raw == NULL)
75 goto out_free_source;
76
77 ops->target.addr = strtoull(target, &endptr, 16);
78 if (endptr == target)
79 goto out_free_target;
80
81 s = strchr(endptr, '<');
82 if (s == NULL)
83 goto out_free_target;
84 endptr = strchr(s + 1, '>');
85 if (endptr == NULL)
86 goto out_free_target;
87
88 *endptr = '\0';
89 ops->target.name = strdup(s + 1);
90 *endptr = '>';
91 if (ops->target.name == NULL)
92 goto out_free_target;
93
94 return 0;
95
96out_free_target:
97 zfree(&ops->target.raw);
98out_free_source:
99 zfree(&ops->source.raw);
100 return -1;
101}
102
103static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
104 struct ins_operands *ops);
105
106static struct ins_ops s390_mov_ops = {
107 .parse = s390_mov__parse,
108 .scnprintf = mov__scnprintf,
109};
110
4static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name) 111static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
5{ 112{
6 struct ins_ops *ops = NULL; 113 struct ins_ops *ops = NULL;
@@ -14,21 +121,54 @@ static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *na
14 if (!strcmp(name, "bras") || 121 if (!strcmp(name, "bras") ||
15 !strcmp(name, "brasl") || 122 !strcmp(name, "brasl") ||
16 !strcmp(name, "basr")) 123 !strcmp(name, "basr"))
17 ops = &call_ops; 124 ops = &s390_call_ops;
18 if (!strcmp(name, "br")) 125 if (!strcmp(name, "br"))
19 ops = &ret_ops; 126 ops = &ret_ops;
127 /* override load/store relative to PC */
128 if (!strcmp(name, "lrl") ||
129 !strcmp(name, "lgrl") ||
130 !strcmp(name, "lgfrl") ||
131 !strcmp(name, "llgfrl") ||
132 !strcmp(name, "strl") ||
133 !strcmp(name, "stgrl"))
134 ops = &s390_mov_ops;
20 135
21 if (ops) 136 if (ops)
22 arch__associate_ins_ops(arch, name, ops); 137 arch__associate_ins_ops(arch, name, ops);
23 return ops; 138 return ops;
24} 139}
25 140
141static int s390__cpuid_parse(struct arch *arch, char *cpuid)
142{
143 unsigned int family;
144 char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
145 int ret;
146
147 /*
148 * cpuid string format:
149 * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
150 */
151 ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
152 model, cpumf_v, cpumf_a);
153 if (ret >= 2) {
154 arch->family = family;
155 arch->model = 0;
156 return 0;
157 }
158
159 return -1;
160}
161
26static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused) 162static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
27{ 163{
164 int err = 0;
165
28 if (!arch->initialized) { 166 if (!arch->initialized) {
29 arch->initialized = true; 167 arch->initialized = true;
30 arch->associate_instruction_ops = s390__associate_ins_ops; 168 arch->associate_instruction_ops = s390__associate_ins_ops;
169 if (cpuid)
170 err = s390__cpuid_parse(arch, cpuid);
31 } 171 }
32 172
33 return 0; 173 return err;
34} 174}
diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index 9fa6c3e5782c..a4c30f1c70be 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -1,8 +1,9 @@
1/* 1/*
2 * Implementation of get_cpuid(). 2 * Implementation of get_cpuid().
3 * 3 *
4 * Copyright 2014 IBM Corp. 4 * Copyright IBM Corp. 2014, 2018
5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com> 5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
6 * Thomas Richter <tmricht@linux.vnet.ibm.com>
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only) 9 * it under the terms of the GNU General Public License (version 2 only)
@@ -13,16 +14,153 @@
13#include <unistd.h> 14#include <unistd.h>
14#include <stdio.h> 15#include <stdio.h>
15#include <string.h> 16#include <string.h>
17#include <ctype.h>
16 18
17#include "../../util/header.h" 19#include "../../util/header.h"
20#include "../../util/util.h"
21
22#define SYSINFO_MANU "Manufacturer:"
23#define SYSINFO_TYPE "Type:"
24#define SYSINFO_MODEL "Model:"
25#define SRVLVL_CPUMF "CPU-MF:"
26#define SRVLVL_VERSION "version="
27#define SRVLVL_AUTHORIZATION "authorization="
28#define SYSINFO "/proc/sysinfo"
29#define SRVLVL "/proc/service_levels"
18 30
19int get_cpuid(char *buffer, size_t sz) 31int get_cpuid(char *buffer, size_t sz)
20{ 32{
21 const char *cpuid = "IBM/S390"; 33 char *cp, *line = NULL, *line2;
34 char type[8], model[33], version[8], manufacturer[32], authorization[8];
35 int tpsize = 0, mdsize = 0, vssize = 0, mfsize = 0, atsize = 0;
36 int read;
37 unsigned long line_sz;
38 size_t nbytes;
39 FILE *sysinfo;
40
41 /*
42 * Scan /proc/sysinfo line by line and read out values for
43 * Manufacturer:, Type: and Model:, for example:
44 * Manufacturer: IBM
45 * Type: 2964
46 * Model: 702 N96
47 * The first word is the Model Capacity and the second word is
48 * Model (can be omitted). Both words have a maximum size of 16
49 * bytes.
50 */
51 memset(manufacturer, 0, sizeof(manufacturer));
52 memset(type, 0, sizeof(type));
53 memset(model, 0, sizeof(model));
54 memset(version, 0, sizeof(version));
55 memset(authorization, 0, sizeof(authorization));
56
57 sysinfo = fopen(SYSINFO, "r");
58 if (sysinfo == NULL)
59 return -1;
60
61 while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
62 if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
63 line2 = line + strlen(SYSINFO_MANU);
64
65 while ((cp = strtok_r(line2, "\n ", &line2))) {
66 mfsize += scnprintf(manufacturer + mfsize,
67 sizeof(manufacturer) - mfsize, "%s", cp);
68 }
69 }
70
71 if (!strncmp(line, SYSINFO_TYPE, strlen(SYSINFO_TYPE))) {
72 line2 = line + strlen(SYSINFO_TYPE);
22 73
23 if (strlen(cpuid) + 1 > sz) 74 while ((cp = strtok_r(line2, "\n ", &line2))) {
75 tpsize += scnprintf(type + tpsize,
76 sizeof(type) - tpsize, "%s", cp);
77 }
78 }
79
80 if (!strncmp(line, SYSINFO_MODEL, strlen(SYSINFO_MODEL))) {
81 line2 = line + strlen(SYSINFO_MODEL);
82
83 while ((cp = strtok_r(line2, "\n ", &line2))) {
84 mdsize += scnprintf(model + mdsize, sizeof(model) - mdsize,
85 "%s%s", model[0] ? "," : "", cp);
86 }
87 break;
88 }
89 }
90 fclose(sysinfo);
91
92 /* Missing manufacturer, type or model information should not happen */
93 if (!manufacturer[0] || !type[0] || !model[0])
24 return -1; 94 return -1;
25 95
26 strcpy(buffer, cpuid); 96 /*
27 return 0; 97 * Scan /proc/service_levels and return the CPU-MF counter facility
98 * version number and authorization level.
99 * Optional, does not exist on z/VM guests.
100 */
101 sysinfo = fopen(SRVLVL, "r");
102 if (sysinfo == NULL)
103 goto skip_sysinfo;
104 while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
105 if (strncmp(line, SRVLVL_CPUMF, strlen(SRVLVL_CPUMF)))
106 continue;
107
108 line2 = line + strlen(SRVLVL_CPUMF);
109 while ((cp = strtok_r(line2, "\n ", &line2))) {
110 if (!strncmp(cp, SRVLVL_VERSION,
111 strlen(SRVLVL_VERSION))) {
112 char *sep = strchr(cp, '=');
113
114 vssize += scnprintf(version + vssize,
115 sizeof(version) - vssize, "%s", sep + 1);
116 }
117 if (!strncmp(cp, SRVLVL_AUTHORIZATION,
118 strlen(SRVLVL_AUTHORIZATION))) {
119 char *sep = strchr(cp, '=');
120
121 atsize += scnprintf(authorization + atsize,
122 sizeof(authorization) - atsize, "%s", sep + 1);
123 }
124 }
125 }
126 fclose(sysinfo);
127
128skip_sysinfo:
129 free(line);
130
131 if (version[0] && authorization[0] )
132 nbytes = snprintf(buffer, sz, "%s,%s,%s,%s,%s",
133 manufacturer, type, model, version,
134 authorization);
135 else
136 nbytes = snprintf(buffer, sz, "%s,%s,%s", manufacturer, type,
137 model);
138 return (nbytes >= sz) ? -1 : 0;
139}
140
141char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
142{
143 char *buf = malloc(128);
144
145 if (buf && get_cpuid(buf, 128) < 0)
146 zfree(&buf);
147 return buf;
148}
149
150/*
151 * Compare the cpuid string returned by get_cpuid() function
152 * with the name generated by the jevents file read from
153 * pmu-events/arch/s390/mapfile.csv.
154 *
155 * Parameter mapcpuid is the cpuid as stored in the
156 * pmu-events/arch/s390/mapfile.csv. This is just the type number.
157 * Parameter cpuid is the cpuid returned by function get_cpuid().
158 */
159int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
160{
161 char *cp = strchr(cpuid, ',');
162
163 if (cp == NULL)
164 return -1;
165 return strncmp(cp + 1, mapcpuid, strlen(mapcpuid));
28} 166}
diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 06abe8108b33..7a7721604b86 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -60,6 +60,7 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
60 union perf_event *event; 60 union perf_event *event;
61 u64 test_tsc, comm1_tsc, comm2_tsc; 61 u64 test_tsc, comm1_tsc, comm2_tsc;
62 u64 test_time, comm1_time = 0, comm2_time = 0; 62 u64 test_time, comm1_time = 0, comm2_time = 0;
63 struct perf_mmap *md;
63 64
64 threads = thread_map__new(-1, getpid(), UINT_MAX); 65 threads = thread_map__new(-1, getpid(), UINT_MAX);
65 CHECK_NOT_NULL__(threads); 66 CHECK_NOT_NULL__(threads);
@@ -109,7 +110,11 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
109 perf_evlist__disable(evlist); 110 perf_evlist__disable(evlist);
110 111
111 for (i = 0; i < evlist->nr_mmaps; i++) { 112 for (i = 0; i < evlist->nr_mmaps; i++) {
112 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 113 md = &evlist->mmap[i];
114 if (perf_mmap__read_init(md) < 0)
115 continue;
116
117 while ((event = perf_mmap__read_event(md)) != NULL) {
113 struct perf_sample sample; 118 struct perf_sample sample;
114 119
115 if (event->header.type != PERF_RECORD_COMM || 120 if (event->header.type != PERF_RECORD_COMM ||
@@ -128,8 +133,9 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
128 comm2_time = sample.time; 133 comm2_time = sample.time;
129 } 134 }
130next_event: 135next_event:
131 perf_evlist__mmap_consume(evlist, i); 136 perf_mmap__consume(md);
132 } 137 }
138 perf_mmap__read_done(md);
133 } 139 }
134 140
135 if (!comm1_time || !comm2_time) 141 if (!comm1_time || !comm2_time)
diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c
index 6aa3f2a38321..b135af62011c 100644
--- a/tools/perf/arch/x86/util/auxtrace.c
+++ b/tools/perf/arch/x86/util/auxtrace.c
@@ -37,15 +37,11 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist,
37 intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME); 37 intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME);
38 intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); 38 intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME);
39 39
40 if (evlist) { 40 evlist__for_each_entry(evlist, evsel) {
41 evlist__for_each_entry(evlist, evsel) { 41 if (intel_pt_pmu && evsel->attr.type == intel_pt_pmu->type)
42 if (intel_pt_pmu && 42 found_pt = true;
43 evsel->attr.type == intel_pt_pmu->type) 43 if (intel_bts_pmu && evsel->attr.type == intel_bts_pmu->type)
44 found_pt = true; 44 found_bts = true;
45 if (intel_bts_pmu &&
46 evsel->attr.type == intel_bts_pmu->type)
47 found_bts = true;
48 }
49 } 45 }
50 46
51 if (found_pt && found_bts) { 47 if (found_pt && found_bts) {
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index f15731a3d438..51709a961496 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -40,10 +40,11 @@
40struct perf_annotate { 40struct perf_annotate {
41 struct perf_tool tool; 41 struct perf_tool tool;
42 struct perf_session *session; 42 struct perf_session *session;
43 bool use_tui, use_stdio, use_gtk; 43 bool use_tui, use_stdio, use_stdio2, use_gtk;
44 bool full_paths; 44 bool full_paths;
45 bool print_line; 45 bool print_line;
46 bool skip_missing; 46 bool skip_missing;
47 bool has_br_stack;
47 const char *sym_hist_filter; 48 const char *sym_hist_filter;
48 const char *cpu_list; 49 const char *cpu_list;
49 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 50 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -146,16 +147,78 @@ static void process_branch_stack(struct branch_stack *bs, struct addr_location *
146 free(bi); 147 free(bi);
147} 148}
148 149
150static int hist_iter__branch_callback(struct hist_entry_iter *iter,
151 struct addr_location *al __maybe_unused,
152 bool single __maybe_unused,
153 void *arg __maybe_unused)
154{
155 struct hist_entry *he = iter->he;
156 struct branch_info *bi;
157 struct perf_sample *sample = iter->sample;
158 struct perf_evsel *evsel = iter->evsel;
159 int err;
160
161 hist__account_cycles(sample->branch_stack, al, sample, false);
162
163 bi = he->branch_info;
164 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx);
165
166 if (err)
167 goto out;
168
169 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx);
170
171out:
172 return err;
173}
174
175static int process_branch_callback(struct perf_evsel *evsel,
176 struct perf_sample *sample,
177 struct addr_location *al __maybe_unused,
178 struct perf_annotate *ann,
179 struct machine *machine)
180{
181 struct hist_entry_iter iter = {
182 .evsel = evsel,
183 .sample = sample,
184 .add_entry_cb = hist_iter__branch_callback,
185 .hide_unresolved = symbol_conf.hide_unresolved,
186 .ops = &hist_iter_branch,
187 };
188
189 struct addr_location a;
190 int ret;
191
192 if (machine__resolve(machine, &a, sample) < 0)
193 return -1;
194
195 if (a.sym == NULL)
196 return 0;
197
198 if (a.map != NULL)
199 a.map->dso->hit = 1;
200
201 ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann);
202 return ret;
203}
204
205static bool has_annotation(struct perf_annotate *ann)
206{
207 return ui__has_annotation() || ann->use_stdio2;
208}
209
149static int perf_evsel__add_sample(struct perf_evsel *evsel, 210static int perf_evsel__add_sample(struct perf_evsel *evsel,
150 struct perf_sample *sample, 211 struct perf_sample *sample,
151 struct addr_location *al, 212 struct addr_location *al,
152 struct perf_annotate *ann) 213 struct perf_annotate *ann,
214 struct machine *machine)
153{ 215{
154 struct hists *hists = evsel__hists(evsel); 216 struct hists *hists = evsel__hists(evsel);
155 struct hist_entry *he; 217 struct hist_entry *he;
156 int ret; 218 int ret;
157 219
158 if (ann->sym_hist_filter != NULL && 220 if ((!ann->has_br_stack || !has_annotation(ann)) &&
221 ann->sym_hist_filter != NULL &&
159 (al->sym == NULL || 222 (al->sym == NULL ||
160 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) { 223 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
161 /* We're only interested in a symbol named sym_hist_filter */ 224 /* We're only interested in a symbol named sym_hist_filter */
@@ -178,6 +241,9 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
178 */ 241 */
179 process_branch_stack(sample->branch_stack, al, sample); 242 process_branch_stack(sample->branch_stack, al, sample);
180 243
244 if (ann->has_br_stack && has_annotation(ann))
245 return process_branch_callback(evsel, sample, al, ann, machine);
246
181 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 247 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
182 if (he == NULL) 248 if (he == NULL)
183 return -ENOMEM; 249 return -ENOMEM;
@@ -206,7 +272,8 @@ static int process_sample_event(struct perf_tool *tool,
206 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) 272 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
207 goto out_put; 273 goto out_put;
208 274
209 if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { 275 if (!al.filtered &&
276 perf_evsel__add_sample(evsel, sample, &al, ann, machine)) {
210 pr_warning("problem incrementing symbol count, " 277 pr_warning("problem incrementing symbol count, "
211 "skipping event\n"); 278 "skipping event\n");
212 ret = -1; 279 ret = -1;
@@ -220,8 +287,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
220 struct perf_evsel *evsel, 287 struct perf_evsel *evsel,
221 struct perf_annotate *ann) 288 struct perf_annotate *ann)
222{ 289{
223 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, 290 if (!ann->use_stdio2)
224 ann->print_line, ann->full_paths, 0, 0); 291 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
292 ann->print_line, ann->full_paths, 0, 0);
293 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel,
294 ann->print_line, ann->full_paths);
225} 295}
226 296
227static void hists__find_annotations(struct hists *hists, 297static void hists__find_annotations(struct hists *hists,
@@ -238,6 +308,10 @@ static void hists__find_annotations(struct hists *hists,
238 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) 308 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
239 goto find_next; 309 goto find_next;
240 310
311 if (ann->sym_hist_filter &&
312 (strcmp(he->ms.sym->name, ann->sym_hist_filter) != 0))
313 goto find_next;
314
241 notes = symbol__annotation(he->ms.sym); 315 notes = symbol__annotation(he->ms.sym);
242 if (notes->src == NULL) { 316 if (notes->src == NULL) {
243find_next: 317find_next:
@@ -269,6 +343,7 @@ find_next:
269 nd = rb_next(nd); 343 nd = rb_next(nd);
270 } else if (use_browser == 1) { 344 } else if (use_browser == 1) {
271 key = hist_entry__tui_annotate(he, evsel, NULL); 345 key = hist_entry__tui_annotate(he, evsel, NULL);
346
272 switch (key) { 347 switch (key) {
273 case -1: 348 case -1:
274 if (!ann->skip_missing) 349 if (!ann->skip_missing)
@@ -420,6 +495,9 @@ int cmd_annotate(int argc, const char **argv)
420 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"), 495 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
421 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"), 496 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
422 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"), 497 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
498 OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
499 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
500 "don't load vmlinux even if found"),
423 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 501 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
424 "file", "vmlinux pathname"), 502 "file", "vmlinux pathname"),
425 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 503 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
@@ -489,20 +567,22 @@ int cmd_annotate(int argc, const char **argv)
489 if (annotate.session == NULL) 567 if (annotate.session == NULL)
490 return -1; 568 return -1;
491 569
570 annotate.has_br_stack = perf_header__has_feat(&annotate.session->header,
571 HEADER_BRANCH_STACK);
572
492 ret = symbol__annotation_init(); 573 ret = symbol__annotation_init();
493 if (ret < 0) 574 if (ret < 0)
494 goto out_delete; 575 goto out_delete;
495 576
577 annotation_config__init();
578
496 symbol_conf.try_vmlinux_path = true; 579 symbol_conf.try_vmlinux_path = true;
497 580
498 ret = symbol__init(&annotate.session->header.env); 581 ret = symbol__init(&annotate.session->header.env);
499 if (ret < 0) 582 if (ret < 0)
500 goto out_delete; 583 goto out_delete;
501 584
502 if (setup_sorting(NULL) < 0) 585 if (annotate.use_stdio || annotate.use_stdio2)
503 usage_with_options(annotate_usage, options);
504
505 if (annotate.use_stdio)
506 use_browser = 0; 586 use_browser = 0;
507 else if (annotate.use_tui) 587 else if (annotate.use_tui)
508 use_browser = 1; 588 use_browser = 1;
@@ -511,6 +591,15 @@ int cmd_annotate(int argc, const char **argv)
511 591
512 setup_browser(true); 592 setup_browser(true);
513 593
594 if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) {
595 sort__mode = SORT_MODE__BRANCH;
596 if (setup_sorting(annotate.session->evlist) < 0)
597 usage_with_options(annotate_usage, options);
598 } else {
599 if (setup_sorting(NULL) < 0)
600 usage_with_options(annotate_usage, options);
601 }
602
514 ret = __cmd_annotate(&annotate); 603 ret = __cmd_annotate(&annotate);
515 604
516out_delete: 605out_delete:
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index 539c3d460158..2126bfbcb385 100644
--- a/tools/perf/builtin-c2c.c
+++ b/tools/perf/builtin-c2c.c
@@ -32,6 +32,7 @@
32#include "evsel.h" 32#include "evsel.h"
33#include "ui/browsers/hists.h" 33#include "ui/browsers/hists.h"
34#include "thread.h" 34#include "thread.h"
35#include "mem2node.h"
35 36
36struct c2c_hists { 37struct c2c_hists {
37 struct hists hists; 38 struct hists hists;
@@ -49,6 +50,7 @@ struct c2c_hist_entry {
49 struct c2c_hists *hists; 50 struct c2c_hists *hists;
50 struct c2c_stats stats; 51 struct c2c_stats stats;
51 unsigned long *cpuset; 52 unsigned long *cpuset;
53 unsigned long *nodeset;
52 struct c2c_stats *node_stats; 54 struct c2c_stats *node_stats;
53 unsigned int cacheline_idx; 55 unsigned int cacheline_idx;
54 56
@@ -59,6 +61,11 @@ struct c2c_hist_entry {
59 * because of its callchain dynamic entry 61 * because of its callchain dynamic entry
60 */ 62 */
61 struct hist_entry he; 63 struct hist_entry he;
64
65 unsigned long paddr;
66 unsigned long paddr_cnt;
67 bool paddr_zero;
68 char *nodestr;
62}; 69};
63 70
64static char const *coalesce_default = "pid,iaddr"; 71static char const *coalesce_default = "pid,iaddr";
@@ -66,6 +73,7 @@ static char const *coalesce_default = "pid,iaddr";
66struct perf_c2c { 73struct perf_c2c {
67 struct perf_tool tool; 74 struct perf_tool tool;
68 struct c2c_hists hists; 75 struct c2c_hists hists;
76 struct mem2node mem2node;
69 77
70 unsigned long **nodes; 78 unsigned long **nodes;
71 int nodes_cnt; 79 int nodes_cnt;
@@ -123,6 +131,10 @@ static void *c2c_he_zalloc(size_t size)
123 if (!c2c_he->cpuset) 131 if (!c2c_he->cpuset)
124 return NULL; 132 return NULL;
125 133
134 c2c_he->nodeset = bitmap_alloc(c2c.nodes_cnt);
135 if (!c2c_he->nodeset)
136 return NULL;
137
126 c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats)); 138 c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats));
127 if (!c2c_he->node_stats) 139 if (!c2c_he->node_stats)
128 return NULL; 140 return NULL;
@@ -145,6 +157,8 @@ static void c2c_he_free(void *he)
145 } 157 }
146 158
147 free(c2c_he->cpuset); 159 free(c2c_he->cpuset);
160 free(c2c_he->nodeset);
161 free(c2c_he->nodestr);
148 free(c2c_he->node_stats); 162 free(c2c_he->node_stats);
149 free(c2c_he); 163 free(c2c_he);
150} 164}
@@ -194,6 +208,28 @@ static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
194 set_bit(sample->cpu, c2c_he->cpuset); 208 set_bit(sample->cpu, c2c_he->cpuset);
195} 209}
196 210
211static void c2c_he__set_node(struct c2c_hist_entry *c2c_he,
212 struct perf_sample *sample)
213{
214 int node;
215
216 if (!sample->phys_addr) {
217 c2c_he->paddr_zero = true;
218 return;
219 }
220
221 node = mem2node__node(&c2c.mem2node, sample->phys_addr);
222 if (WARN_ONCE(node < 0, "WARNING: failed to find node\n"))
223 return;
224
225 set_bit(node, c2c_he->nodeset);
226
227 if (c2c_he->paddr != sample->phys_addr) {
228 c2c_he->paddr_cnt++;
229 c2c_he->paddr = sample->phys_addr;
230 }
231}
232
197static void compute_stats(struct c2c_hist_entry *c2c_he, 233static void compute_stats(struct c2c_hist_entry *c2c_he,
198 struct c2c_stats *stats, 234 struct c2c_stats *stats,
199 u64 weight) 235 u64 weight)
@@ -237,9 +273,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
237 if (mi == NULL) 273 if (mi == NULL)
238 return -ENOMEM; 274 return -ENOMEM;
239 275
240 mi_dup = memdup(mi, sizeof(*mi)); 276 /*
241 if (!mi_dup) 277 * The mi object is released in hists__add_entry_ops,
242 goto free_mi; 278 * if it gets sorted out into existing data, so we need
279 * to take the copy now.
280 */
281 mi_dup = mem_info__get(mi);
243 282
244 c2c_decode_stats(&stats, mi); 283 c2c_decode_stats(&stats, mi);
245 284
@@ -247,13 +286,14 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
247 &al, NULL, NULL, mi, 286 &al, NULL, NULL, mi,
248 sample, true); 287 sample, true);
249 if (he == NULL) 288 if (he == NULL)
250 goto free_mi_dup; 289 goto free_mi;
251 290
252 c2c_he = container_of(he, struct c2c_hist_entry, he); 291 c2c_he = container_of(he, struct c2c_hist_entry, he);
253 c2c_add_stats(&c2c_he->stats, &stats); 292 c2c_add_stats(&c2c_he->stats, &stats);
254 c2c_add_stats(&c2c_hists->stats, &stats); 293 c2c_add_stats(&c2c_hists->stats, &stats);
255 294
256 c2c_he__set_cpu(c2c_he, sample); 295 c2c_he__set_cpu(c2c_he, sample);
296 c2c_he__set_node(c2c_he, sample);
257 297
258 hists__inc_nr_samples(&c2c_hists->hists, he->filtered); 298 hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
259 ret = hist_entry__append_callchain(he, sample); 299 ret = hist_entry__append_callchain(he, sample);
@@ -272,19 +312,15 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
272 312
273 mi = mi_dup; 313 mi = mi_dup;
274 314
275 mi_dup = memdup(mi, sizeof(*mi));
276 if (!mi_dup)
277 goto free_mi;
278
279 c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2); 315 c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
280 if (!c2c_hists) 316 if (!c2c_hists)
281 goto free_mi_dup; 317 goto free_mi;
282 318
283 he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops, 319 he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
284 &al, NULL, NULL, mi, 320 &al, NULL, NULL, mi,
285 sample, true); 321 sample, true);
286 if (he == NULL) 322 if (he == NULL)
287 goto free_mi_dup; 323 goto free_mi;
288 324
289 c2c_he = container_of(he, struct c2c_hist_entry, he); 325 c2c_he = container_of(he, struct c2c_hist_entry, he);
290 c2c_add_stats(&c2c_he->stats, &stats); 326 c2c_add_stats(&c2c_he->stats, &stats);
@@ -294,6 +330,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
294 compute_stats(c2c_he, &stats, sample->weight); 330 compute_stats(c2c_he, &stats, sample->weight);
295 331
296 c2c_he__set_cpu(c2c_he, sample); 332 c2c_he__set_cpu(c2c_he, sample);
333 c2c_he__set_node(c2c_he, sample);
297 334
298 hists__inc_nr_samples(&c2c_hists->hists, he->filtered); 335 hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
299 ret = hist_entry__append_callchain(he, sample); 336 ret = hist_entry__append_callchain(he, sample);
@@ -303,10 +340,9 @@ out:
303 addr_location__put(&al); 340 addr_location__put(&al);
304 return ret; 341 return ret;
305 342
306free_mi_dup:
307 free(mi_dup);
308free_mi: 343free_mi:
309 free(mi); 344 mem_info__put(mi_dup);
345 mem_info__put(mi);
310 ret = -ENOMEM; 346 ret = -ENOMEM;
311 goto out; 347 goto out;
312} 348}
@@ -457,6 +493,31 @@ static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
457 return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr)); 493 return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
458} 494}
459 495
496static int
497dcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
498 struct hist_entry *he)
499{
500 struct c2c_hist_entry *c2c_he;
501 int width = c2c_width(fmt, hpp, he->hists);
502
503 c2c_he = container_of(he, struct c2c_hist_entry, he);
504 if (WARN_ON_ONCE(!c2c_he->nodestr))
505 return 0;
506
507 return scnprintf(hpp->buf, hpp->size, "%*s", width, c2c_he->nodestr);
508}
509
510static int
511dcacheline_node_count(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
512 struct hist_entry *he)
513{
514 struct c2c_hist_entry *c2c_he;
515 int width = c2c_width(fmt, hpp, he->hists);
516
517 c2c_he = container_of(he, struct c2c_hist_entry, he);
518 return scnprintf(hpp->buf, hpp->size, "%*lu", width, c2c_he->paddr_cnt);
519}
520
460static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 521static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
461 struct hist_entry *he) 522 struct hist_entry *he)
462{ 523{
@@ -1202,23 +1263,47 @@ cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1202 } 1263 }
1203 1264
1204static struct c2c_dimension dim_dcacheline = { 1265static struct c2c_dimension dim_dcacheline = {
1205 .header = HEADER_LOW("Cacheline"), 1266 .header = HEADER_SPAN("--- Cacheline ----", "Address", 2),
1206 .name = "dcacheline", 1267 .name = "dcacheline",
1207 .cmp = dcacheline_cmp, 1268 .cmp = dcacheline_cmp,
1208 .entry = dcacheline_entry, 1269 .entry = dcacheline_entry,
1209 .width = 18, 1270 .width = 18,
1210}; 1271};
1211 1272
1212static struct c2c_header header_offset_tui = HEADER_LOW("Off"); 1273static struct c2c_dimension dim_dcacheline_node = {
1274 .header = HEADER_LOW("Node"),
1275 .name = "dcacheline_node",
1276 .cmp = empty_cmp,
1277 .entry = dcacheline_node_entry,
1278 .width = 4,
1279};
1280
1281static struct c2c_dimension dim_dcacheline_count = {
1282 .header = HEADER_LOW("PA cnt"),
1283 .name = "dcacheline_count",
1284 .cmp = empty_cmp,
1285 .entry = dcacheline_node_count,
1286 .width = 6,
1287};
1288
1289static struct c2c_header header_offset_tui = HEADER_SPAN("-----", "Off", 2);
1213 1290
1214static struct c2c_dimension dim_offset = { 1291static struct c2c_dimension dim_offset = {
1215 .header = HEADER_BOTH("Data address", "Offset"), 1292 .header = HEADER_SPAN("--- Data address -", "Offset", 2),
1216 .name = "offset", 1293 .name = "offset",
1217 .cmp = offset_cmp, 1294 .cmp = offset_cmp,
1218 .entry = offset_entry, 1295 .entry = offset_entry,
1219 .width = 18, 1296 .width = 18,
1220}; 1297};
1221 1298
1299static struct c2c_dimension dim_offset_node = {
1300 .header = HEADER_LOW("Node"),
1301 .name = "offset_node",
1302 .cmp = empty_cmp,
1303 .entry = dcacheline_node_entry,
1304 .width = 4,
1305};
1306
1222static struct c2c_dimension dim_iaddr = { 1307static struct c2c_dimension dim_iaddr = {
1223 .header = HEADER_LOW("Code address"), 1308 .header = HEADER_LOW("Code address"),
1224 .name = "iaddr", 1309 .name = "iaddr",
@@ -1538,7 +1623,10 @@ static struct c2c_dimension dim_dcacheline_num_empty = {
1538 1623
1539static struct c2c_dimension *dimensions[] = { 1624static struct c2c_dimension *dimensions[] = {
1540 &dim_dcacheline, 1625 &dim_dcacheline,
1626 &dim_dcacheline_node,
1627 &dim_dcacheline_count,
1541 &dim_offset, 1628 &dim_offset,
1629 &dim_offset_node,
1542 &dim_iaddr, 1630 &dim_iaddr,
1543 &dim_tot_hitm, 1631 &dim_tot_hitm,
1544 &dim_lcl_hitm, 1632 &dim_lcl_hitm,
@@ -1841,20 +1929,56 @@ static inline int valid_hitm_or_store(struct hist_entry *he)
1841 return has_hitm || c2c_he->stats.store; 1929 return has_hitm || c2c_he->stats.store;
1842} 1930}
1843 1931
1844static void calc_width(struct hist_entry *he) 1932static void set_node_width(struct c2c_hist_entry *c2c_he, int len)
1933{
1934 struct c2c_dimension *dim;
1935
1936 dim = &c2c.hists == c2c_he->hists ?
1937 &dim_dcacheline_node : &dim_offset_node;
1938
1939 if (len > dim->width)
1940 dim->width = len;
1941}
1942
1943static int set_nodestr(struct c2c_hist_entry *c2c_he)
1944{
1945 char buf[30];
1946 int len;
1947
1948 if (c2c_he->nodestr)
1949 return 0;
1950
1951 if (bitmap_weight(c2c_he->nodeset, c2c.nodes_cnt)) {
1952 len = bitmap_scnprintf(c2c_he->nodeset, c2c.nodes_cnt,
1953 buf, sizeof(buf));
1954 } else {
1955 len = scnprintf(buf, sizeof(buf), "N/A");
1956 }
1957
1958 set_node_width(c2c_he, len);
1959 c2c_he->nodestr = strdup(buf);
1960 return c2c_he->nodestr ? 0 : -ENOMEM;
1961}
1962
1963static void calc_width(struct c2c_hist_entry *c2c_he)
1845{ 1964{
1846 struct c2c_hists *c2c_hists; 1965 struct c2c_hists *c2c_hists;
1847 1966
1848 c2c_hists = container_of(he->hists, struct c2c_hists, hists); 1967 c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
1849 hists__calc_col_len(&c2c_hists->hists, he); 1968 hists__calc_col_len(&c2c_hists->hists, &c2c_he->he);
1969 set_nodestr(c2c_he);
1850} 1970}
1851 1971
1852static int filter_cb(struct hist_entry *he) 1972static int filter_cb(struct hist_entry *he)
1853{ 1973{
1974 struct c2c_hist_entry *c2c_he;
1975
1976 c2c_he = container_of(he, struct c2c_hist_entry, he);
1977
1854 if (c2c.show_src && !he->srcline) 1978 if (c2c.show_src && !he->srcline)
1855 he->srcline = hist_entry__get_srcline(he); 1979 he->srcline = hist_entry__get_srcline(he);
1856 1980
1857 calc_width(he); 1981 calc_width(c2c_he);
1858 1982
1859 if (!valid_hitm_or_store(he)) 1983 if (!valid_hitm_or_store(he))
1860 he->filtered = HIST_FILTER__C2C; 1984 he->filtered = HIST_FILTER__C2C;
@@ -1871,12 +1995,11 @@ static int resort_cl_cb(struct hist_entry *he)
1871 c2c_he = container_of(he, struct c2c_hist_entry, he); 1995 c2c_he = container_of(he, struct c2c_hist_entry, he);
1872 c2c_hists = c2c_he->hists; 1996 c2c_hists = c2c_he->hists;
1873 1997
1874 calc_width(he);
1875
1876 if (display && c2c_hists) { 1998 if (display && c2c_hists) {
1877 static unsigned int idx; 1999 static unsigned int idx;
1878 2000
1879 c2c_he->cacheline_idx = idx++; 2001 c2c_he->cacheline_idx = idx++;
2002 calc_width(c2c_he);
1880 2003
1881 c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort); 2004 c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
1882 2005
@@ -2350,14 +2473,66 @@ static void perf_c2c_display(struct perf_session *session)
2350} 2473}
2351#endif /* HAVE_SLANG_SUPPORT */ 2474#endif /* HAVE_SLANG_SUPPORT */
2352 2475
2353static void ui_quirks(void) 2476static char *fill_line(const char *orig, int len)
2477{
2478 int i, j, olen = strlen(orig);
2479 char *buf;
2480
2481 buf = zalloc(len + 1);
2482 if (!buf)
2483 return NULL;
2484
2485 j = len / 2 - olen / 2;
2486
2487 for (i = 0; i < j - 1; i++)
2488 buf[i] = '-';
2489
2490 buf[i++] = ' ';
2491
2492 strcpy(buf + i, orig);
2493
2494 i += olen;
2495
2496 buf[i++] = ' ';
2497
2498 for (; i < len; i++)
2499 buf[i] = '-';
2500
2501 return buf;
2502}
2503
2504static int ui_quirks(void)
2354{ 2505{
2506 const char *nodestr = "Data address";
2507 char *buf;
2508
2355 if (!c2c.use_stdio) { 2509 if (!c2c.use_stdio) {
2356 dim_offset.width = 5; 2510 dim_offset.width = 5;
2357 dim_offset.header = header_offset_tui; 2511 dim_offset.header = header_offset_tui;
2512 nodestr = "CL";
2358 } 2513 }
2359 2514
2360 dim_percent_hitm.header = percent_hitm_header[c2c.display]; 2515 dim_percent_hitm.header = percent_hitm_header[c2c.display];
2516
2517 /* Fix the zero line for dcacheline column. */
2518 buf = fill_line("Cacheline", dim_dcacheline.width +
2519 dim_dcacheline_node.width +
2520 dim_dcacheline_count.width + 4);
2521 if (!buf)
2522 return -ENOMEM;
2523
2524 dim_dcacheline.header.line[0].text = buf;
2525
2526 /* Fix the zero line for offset column. */
2527 buf = fill_line(nodestr, dim_offset.width +
2528 dim_offset_node.width +
2529 dim_dcacheline_count.width + 4);
2530 if (!buf)
2531 return -ENOMEM;
2532
2533 dim_offset.header.line[0].text = buf;
2534
2535 return 0;
2361} 2536}
2362 2537
2363#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent" 2538#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
@@ -2473,7 +2648,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
2473 "percent_lcl_hitm," 2648 "percent_lcl_hitm,"
2474 "percent_stores_l1hit," 2649 "percent_stores_l1hit,"
2475 "percent_stores_l1miss," 2650 "percent_stores_l1miss,"
2476 "offset,", 2651 "offset,offset_node,dcacheline_count,",
2477 add_pid ? "pid," : "", 2652 add_pid ? "pid," : "",
2478 add_tid ? "tid," : "", 2653 add_tid ? "tid," : "",
2479 add_iaddr ? "iaddr," : "", 2654 add_iaddr ? "iaddr," : "",
@@ -2602,17 +2777,21 @@ static int perf_c2c__report(int argc, const char **argv)
2602 goto out; 2777 goto out;
2603 } 2778 }
2604 2779
2605 err = setup_callchain(session->evlist); 2780 err = mem2node__init(&c2c.mem2node, &session->header.env);
2606 if (err) 2781 if (err)
2607 goto out_session; 2782 goto out_session;
2608 2783
2784 err = setup_callchain(session->evlist);
2785 if (err)
2786 goto out_mem2node;
2787
2609 if (symbol__init(&session->header.env) < 0) 2788 if (symbol__init(&session->header.env) < 0)
2610 goto out_session; 2789 goto out_mem2node;
2611 2790
2612 /* No pipe support at the moment. */ 2791 /* No pipe support at the moment. */
2613 if (perf_data__is_pipe(session->data)) { 2792 if (perf_data__is_pipe(session->data)) {
2614 pr_debug("No pipe support at the moment.\n"); 2793 pr_debug("No pipe support at the moment.\n");
2615 goto out_session; 2794 goto out_mem2node;
2616 } 2795 }
2617 2796
2618 if (c2c.use_stdio) 2797 if (c2c.use_stdio)
@@ -2625,12 +2804,14 @@ static int perf_c2c__report(int argc, const char **argv)
2625 err = perf_session__process_events(session); 2804 err = perf_session__process_events(session);
2626 if (err) { 2805 if (err) {
2627 pr_err("failed to process sample\n"); 2806 pr_err("failed to process sample\n");
2628 goto out_session; 2807 goto out_mem2node;
2629 } 2808 }
2630 2809
2631 c2c_hists__reinit(&c2c.hists, 2810 c2c_hists__reinit(&c2c.hists,
2632 "cl_idx," 2811 "cl_idx,"
2633 "dcacheline," 2812 "dcacheline,"
2813 "dcacheline_node,"
2814 "dcacheline_count,"
2634 "tot_recs," 2815 "tot_recs,"
2635 "percent_hitm," 2816 "percent_hitm,"
2636 "tot_hitm,lcl_hitm,rmt_hitm," 2817 "tot_hitm,lcl_hitm,rmt_hitm,"
@@ -2652,10 +2833,15 @@ static int perf_c2c__report(int argc, const char **argv)
2652 2833
2653 ui_progress__finish(); 2834 ui_progress__finish();
2654 2835
2655 ui_quirks(); 2836 if (ui_quirks()) {
2837 pr_err("failed to setup UI\n");
2838 goto out_mem2node;
2839 }
2656 2840
2657 perf_c2c_display(session); 2841 perf_c2c_display(session);
2658 2842
2843out_mem2node:
2844 mem2node__exit(&c2c.mem2node);
2659out_session: 2845out_session:
2660 perf_session__delete(session); 2846 perf_session__delete(session);
2661out: 2847out:
@@ -2706,7 +2892,7 @@ static int perf_c2c__record(int argc, const char **argv)
2706 argc = parse_options(argc, argv, options, record_mem_usage, 2892 argc = parse_options(argc, argv, options, record_mem_usage,
2707 PARSE_OPT_KEEP_UNKNOWN); 2893 PARSE_OPT_KEEP_UNKNOWN);
2708 2894
2709 rec_argc = argc + 10; /* max number of arguments */ 2895 rec_argc = argc + 11; /* max number of arguments */
2710 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 2896 rec_argv = calloc(rec_argc + 1, sizeof(char *));
2711 if (!rec_argv) 2897 if (!rec_argv)
2712 return -1; 2898 return -1;
@@ -2722,6 +2908,7 @@ static int perf_c2c__record(int argc, const char **argv)
2722 rec_argv[i++] = "-W"; 2908 rec_argv[i++] = "-W";
2723 2909
2724 rec_argv[i++] = "-d"; 2910 rec_argv[i++] = "-d";
2911 rec_argv[i++] = "--phys-data";
2725 rec_argv[i++] = "--sample-cpu"; 2912 rec_argv[i++] = "--sample-cpu";
2726 2913
2727 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { 2914 for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 25a42acabee1..f42f228e8899 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -72,6 +72,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
72 ssize_t size = strlen(val); 72 ssize_t size = strlen(val);
73 int flags = O_WRONLY; 73 int flags = O_WRONLY;
74 char errbuf[512]; 74 char errbuf[512];
75 char *val_copy;
75 76
76 file = get_tracing_file(name); 77 file = get_tracing_file(name);
77 if (!file) { 78 if (!file) {
@@ -91,12 +92,23 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
91 goto out; 92 goto out;
92 } 93 }
93 94
94 if (write(fd, val, size) == size) 95 /*
96 * Copy the original value and append a '\n'. Without this,
97 * the kernel can hide possible errors.
98 */
99 val_copy = strdup(val);
100 if (!val_copy)
101 goto out_close;
102 val_copy[size] = '\n';
103
104 if (write(fd, val_copy, size + 1) == size + 1)
95 ret = 0; 105 ret = 0;
96 else 106 else
97 pr_debug("write '%s' to tracing/%s failed: %s\n", 107 pr_debug("write '%s' to tracing/%s failed: %s\n",
98 val, name, str_error_r(errno, errbuf, sizeof(errbuf))); 108 val, name, str_error_r(errno, errbuf, sizeof(errbuf)));
99 109
110 free(val_copy);
111out_close:
100 close(fd); 112 close(fd);
101out: 113out:
102 put_tracing_file(file); 114 put_tracing_file(file);
@@ -280,8 +292,10 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
280 signal(SIGCHLD, sig_handler); 292 signal(SIGCHLD, sig_handler);
281 signal(SIGPIPE, sig_handler); 293 signal(SIGPIPE, sig_handler);
282 294
283 if (reset_tracing_files(ftrace) < 0) 295 if (reset_tracing_files(ftrace) < 0) {
296 pr_err("failed to reset ftrace\n");
284 goto out; 297 goto out;
298 }
285 299
286 /* reset ftrace buffer */ 300 /* reset ftrace buffer */
287 if (write_tracing_file("trace", "0") < 0) 301 if (write_tracing_file("trace", "0") < 0)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 55d919dc5bc6..72e2ca096bf5 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -743,16 +743,23 @@ static bool verify_vcpu(int vcpu)
743static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, 743static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
744 u64 *mmap_time) 744 u64 *mmap_time)
745{ 745{
746 struct perf_evlist *evlist = kvm->evlist;
746 union perf_event *event; 747 union perf_event *event;
748 struct perf_mmap *md;
747 u64 timestamp; 749 u64 timestamp;
748 s64 n = 0; 750 s64 n = 0;
749 int err; 751 int err;
750 752
751 *mmap_time = ULLONG_MAX; 753 *mmap_time = ULLONG_MAX;
752 while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) { 754 md = &evlist->mmap[idx];
753 err = perf_evlist__parse_sample_timestamp(kvm->evlist, event, &timestamp); 755 err = perf_mmap__read_init(md);
756 if (err < 0)
757 return (err == -EAGAIN) ? 0 : -1;
758
759 while ((event = perf_mmap__read_event(md)) != NULL) {
760 err = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
754 if (err) { 761 if (err) {
755 perf_evlist__mmap_consume(kvm->evlist, idx); 762 perf_mmap__consume(md);
756 pr_err("Failed to parse sample\n"); 763 pr_err("Failed to parse sample\n");
757 return -1; 764 return -1;
758 } 765 }
@@ -762,7 +769,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
762 * FIXME: Here we can't consume the event, as perf_session__queue_event will 769 * FIXME: Here we can't consume the event, as perf_session__queue_event will
763 * point to it, and it'll get possibly overwritten by the kernel. 770 * point to it, and it'll get possibly overwritten by the kernel.
764 */ 771 */
765 perf_evlist__mmap_consume(kvm->evlist, idx); 772 perf_mmap__consume(md);
766 773
767 if (err) { 774 if (err) {
768 pr_err("Failed to enqueue sample: %d\n", err); 775 pr_err("Failed to enqueue sample: %d\n", err);
@@ -779,6 +786,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
779 break; 786 break;
780 } 787 }
781 788
789 perf_mmap__read_done(md);
782 return n; 790 return n;
783} 791}
784 792
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index bf4ca749d1ac..22ebeb92ac51 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -45,6 +45,7 @@
45 45
46#include <errno.h> 46#include <errno.h>
47#include <inttypes.h> 47#include <inttypes.h>
48#include <locale.h>
48#include <poll.h> 49#include <poll.h>
49#include <unistd.h> 50#include <unistd.h>
50#include <sched.h> 51#include <sched.h>
@@ -70,7 +71,6 @@ struct record {
70 struct auxtrace_record *itr; 71 struct auxtrace_record *itr;
71 struct perf_evlist *evlist; 72 struct perf_evlist *evlist;
72 struct perf_session *session; 73 struct perf_session *session;
73 const char *progname;
74 int realtime_prio; 74 int realtime_prio;
75 bool no_buildid; 75 bool no_buildid;
76 bool no_buildid_set; 76 bool no_buildid_set;
@@ -273,6 +273,24 @@ static void record__read_auxtrace_snapshot(struct record *rec)
273 } 273 }
274} 274}
275 275
276static int record__auxtrace_init(struct record *rec)
277{
278 int err;
279
280 if (!rec->itr) {
281 rec->itr = auxtrace_record__init(rec->evlist, &err);
282 if (err)
283 return err;
284 }
285
286 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
287 rec->opts.auxtrace_snapshot_opts);
288 if (err)
289 return err;
290
291 return auxtrace_parse_filters(rec->evlist);
292}
293
276#else 294#else
277 295
278static inline 296static inline
@@ -293,6 +311,11 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
293 return 0; 311 return 0;
294} 312}
295 313
314static int record__auxtrace_init(struct record *rec __maybe_unused)
315{
316 return 0;
317}
318
296#endif 319#endif
297 320
298static int record__mmap_evlist(struct record *rec, 321static int record__mmap_evlist(struct record *rec,
@@ -509,7 +532,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
509 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 532 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
510 533
511 if (maps[i].base) { 534 if (maps[i].base) {
512 if (perf_mmap__push(&maps[i], overwrite, rec, record__pushfn) != 0) { 535 if (perf_mmap__push(&maps[i], rec, record__pushfn) != 0) {
513 rc = -1; 536 rc = -1;
514 goto out; 537 goto out;
515 } 538 }
@@ -731,13 +754,10 @@ static int record__synthesize(struct record *rec, bool tail)
731 return 0; 754 return 0;
732 755
733 if (data->is_pipe) { 756 if (data->is_pipe) {
734 err = perf_event__synthesize_features( 757 /*
735 tool, session, rec->evlist, process_synthesized_event); 758 * We need to synthesize events first, because some
736 if (err < 0) { 759 * features works on top of them (on report side).
737 pr_err("Couldn't synthesize features.\n"); 760 */
738 return err;
739 }
740
741 err = perf_event__synthesize_attrs(tool, session, 761 err = perf_event__synthesize_attrs(tool, session,
742 process_synthesized_event); 762 process_synthesized_event);
743 if (err < 0) { 763 if (err < 0) {
@@ -745,6 +765,13 @@ static int record__synthesize(struct record *rec, bool tail)
745 goto out; 765 goto out;
746 } 766 }
747 767
768 err = perf_event__synthesize_features(tool, session, rec->evlist,
769 process_synthesized_event);
770 if (err < 0) {
771 pr_err("Couldn't synthesize features.\n");
772 return err;
773 }
774
748 if (have_tracepoints(&rec->evlist->entries)) { 775 if (have_tracepoints(&rec->evlist->entries)) {
749 /* 776 /*
750 * FIXME err <= 0 here actually means that 777 * FIXME err <= 0 here actually means that
@@ -830,7 +857,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
830 int status = 0; 857 int status = 0;
831 unsigned long waking = 0; 858 unsigned long waking = 0;
832 const bool forks = argc > 0; 859 const bool forks = argc > 0;
833 struct machine *machine;
834 struct perf_tool *tool = &rec->tool; 860 struct perf_tool *tool = &rec->tool;
835 struct record_opts *opts = &rec->opts; 861 struct record_opts *opts = &rec->opts;
836 struct perf_data *data = &rec->data; 862 struct perf_data *data = &rec->data;
@@ -838,8 +864,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
838 bool disabled = false, draining = false; 864 bool disabled = false, draining = false;
839 int fd; 865 int fd;
840 866
841 rec->progname = argv[0];
842
843 atexit(record__sig_exit); 867 atexit(record__sig_exit);
844 signal(SIGCHLD, sig_handler); 868 signal(SIGCHLD, sig_handler);
845 signal(SIGINT, sig_handler); 869 signal(SIGINT, sig_handler);
@@ -881,6 +905,15 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
881 } 905 }
882 } 906 }
883 907
908 /*
909 * If we have just single event and are sending data
910 * through pipe, we need to force the ids allocation,
911 * because we synthesize event name through the pipe
912 * and need the id for that.
913 */
914 if (data->is_pipe && rec->evlist->nr_entries == 1)
915 rec->opts.sample_id = true;
916
884 if (record__open(rec) != 0) { 917 if (record__open(rec) != 0) {
885 err = -1; 918 err = -1;
886 goto out_child; 919 goto out_child;
@@ -926,8 +959,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
926 goto out_child; 959 goto out_child;
927 } 960 }
928 961
929 machine = &session->machines.host;
930
931 err = record__synthesize(rec, false); 962 err = record__synthesize(rec, false);
932 if (err < 0) 963 if (err < 0)
933 goto out_child; 964 goto out_child;
@@ -955,6 +986,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
955 * Let the child rip 986 * Let the child rip
956 */ 987 */
957 if (forks) { 988 if (forks) {
989 struct machine *machine = &session->machines.host;
958 union perf_event *event; 990 union perf_event *event;
959 pid_t tgid; 991 pid_t tgid;
960 992
@@ -1251,10 +1283,12 @@ static int perf_record_config(const char *var, const char *value, void *cb)
1251 return -1; 1283 return -1;
1252 return 0; 1284 return 0;
1253 } 1285 }
1254 if (!strcmp(var, "record.call-graph")) 1286 if (!strcmp(var, "record.call-graph")) {
1255 var = "call-graph.record-mode"; /* fall-through */ 1287 var = "call-graph.record-mode";
1288 return perf_default_config(var, value, cb);
1289 }
1256 1290
1257 return perf_default_config(var, value, cb); 1291 return 0;
1258} 1292}
1259 1293
1260struct clockid_map { 1294struct clockid_map {
@@ -1542,7 +1576,11 @@ static struct option __record_options[] = {
1542 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, 1576 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
1543 "synthesize non-sample events at the end of output"), 1577 "synthesize non-sample events at the end of output"),
1544 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), 1578 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1545 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1579 OPT_BOOLEAN(0, "strict-freq", &record.opts.strict_freq,
1580 "Fail if the specified frequency can't be used"),
1581 OPT_CALLBACK('F', "freq", &record.opts, "freq or 'max'",
1582 "profile at this frequency",
1583 record__parse_freq),
1546 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1584 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1547 "number of mmap data pages and AUX area tracing mmap pages", 1585 "number of mmap data pages and AUX area tracing mmap pages",
1548 record__parse_mmap_pages), 1586 record__parse_mmap_pages),
@@ -1651,6 +1689,8 @@ int cmd_record(int argc, const char **argv)
1651 struct record *rec = &record; 1689 struct record *rec = &record;
1652 char errbuf[BUFSIZ]; 1690 char errbuf[BUFSIZ];
1653 1691
1692 setlocale(LC_ALL, "");
1693
1654#ifndef HAVE_LIBBPF_SUPPORT 1694#ifndef HAVE_LIBBPF_SUPPORT
1655# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c) 1695# define set_nobuild(s, l, c) set_option_nobuild(record_options, s, l, "NO_LIBBPF=1", c)
1656 set_nobuild('\0', "clang-path", true); 1696 set_nobuild('\0', "clang-path", true);
@@ -1711,17 +1751,6 @@ int cmd_record(int argc, const char **argv)
1711 alarm(rec->switch_output.time); 1751 alarm(rec->switch_output.time);
1712 } 1752 }
1713 1753
1714 if (!rec->itr) {
1715 rec->itr = auxtrace_record__init(rec->evlist, &err);
1716 if (err)
1717 goto out;
1718 }
1719
1720 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
1721 rec->opts.auxtrace_snapshot_opts);
1722 if (err)
1723 goto out;
1724
1725 /* 1754 /*
1726 * Allow aliases to facilitate the lookup of symbols for address 1755 * Allow aliases to facilitate the lookup of symbols for address
1727 * filters. Refer to auxtrace_parse_filters(). 1756 * filters. Refer to auxtrace_parse_filters().
@@ -1730,7 +1759,7 @@ int cmd_record(int argc, const char **argv)
1730 1759
1731 symbol__init(NULL); 1760 symbol__init(NULL);
1732 1761
1733 err = auxtrace_parse_filters(rec->evlist); 1762 err = record__auxtrace_init(rec);
1734 if (err) 1763 if (err)
1735 goto out; 1764 goto out;
1736 1765
@@ -1803,7 +1832,7 @@ int cmd_record(int argc, const char **argv)
1803 err = target__validate(&rec->opts.target); 1832 err = target__validate(&rec->opts.target);
1804 if (err) { 1833 if (err) {
1805 target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 1834 target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
1806 ui__warning("%s", errbuf); 1835 ui__warning("%s\n", errbuf);
1807 } 1836 }
1808 1837
1809 err = target__parse_uid(&rec->opts.target); 1838 err = target__parse_uid(&rec->opts.target);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4ad5dc649716..0f198f6d9b77 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -68,6 +68,7 @@ struct report {
68 bool header; 68 bool header;
69 bool header_only; 69 bool header_only;
70 bool nonany_branch_mode; 70 bool nonany_branch_mode;
71 bool group_set;
71 int max_stack; 72 int max_stack;
72 struct perf_read_values show_threads_values; 73 struct perf_read_values show_threads_values;
73 const char *pretty_printing_style; 74 const char *pretty_printing_style;
@@ -193,6 +194,45 @@ out:
193 return err; 194 return err;
194} 195}
195 196
197/*
198 * Events in data file are not collect in groups, but we still want
199 * the group display. Set the artificial group and set the leader's
200 * forced_leader flag to notify the display code.
201 */
202static void setup_forced_leader(struct report *report,
203 struct perf_evlist *evlist)
204{
205 if (report->group_set && !evlist->nr_groups) {
206 struct perf_evsel *leader = perf_evlist__first(evlist);
207
208 perf_evlist__set_leader(evlist);
209 leader->forced_leader = true;
210 }
211}
212
213static int process_feature_event(struct perf_tool *tool,
214 union perf_event *event,
215 struct perf_session *session __maybe_unused)
216{
217 struct report *rep = container_of(tool, struct report, tool);
218
219 if (event->feat.feat_id < HEADER_LAST_FEATURE)
220 return perf_event__process_feature(tool, event, session);
221
222 if (event->feat.feat_id != HEADER_LAST_FEATURE) {
223 pr_err("failed: wrong feature ID: %" PRIu64 "\n",
224 event->feat.feat_id);
225 return -1;
226 }
227
228 /*
229 * All features are received, we can force the
230 * group if needed.
231 */
232 setup_forced_leader(rep, session->evlist);
233 return 0;
234}
235
196static int process_sample_event(struct perf_tool *tool, 236static int process_sample_event(struct perf_tool *tool,
197 union perf_event *event, 237 union perf_event *event,
198 struct perf_sample *sample, 238 struct perf_sample *sample,
@@ -400,8 +440,10 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
400 440
401 nr_samples = convert_unit(nr_samples, &unit); 441 nr_samples = convert_unit(nr_samples, &unit);
402 ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit); 442 ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit);
403 if (evname != NULL) 443 if (evname != NULL) {
404 ret += fprintf(fp, " of event '%s'", evname); 444 ret += fprintf(fp, " of event%s '%s'",
445 evsel->nr_members > 1 ? "s" : "", evname);
446 }
405 447
406 if (rep->time_str) 448 if (rep->time_str)
407 ret += fprintf(fp, " (time slices: %s)", rep->time_str); 449 ret += fprintf(fp, " (time slices: %s)", rep->time_str);
@@ -614,6 +656,7 @@ static int stats_print(struct report *rep)
614static void tasks_setup(struct report *rep) 656static void tasks_setup(struct report *rep)
615{ 657{
616 memset(&rep->tool, 0, sizeof(rep->tool)); 658 memset(&rep->tool, 0, sizeof(rep->tool));
659 rep->tool.ordered_events = true;
617 if (rep->mmaps_mode) { 660 if (rep->mmaps_mode) {
618 rep->tool.mmap = perf_event__process_mmap; 661 rep->tool.mmap = perf_event__process_mmap;
619 rep->tool.mmap2 = perf_event__process_mmap2; 662 rep->tool.mmap2 = perf_event__process_mmap2;
@@ -954,7 +997,7 @@ int cmd_report(int argc, const char **argv)
954 .id_index = perf_event__process_id_index, 997 .id_index = perf_event__process_id_index,
955 .auxtrace_info = perf_event__process_auxtrace_info, 998 .auxtrace_info = perf_event__process_auxtrace_info,
956 .auxtrace = perf_event__process_auxtrace, 999 .auxtrace = perf_event__process_auxtrace,
957 .feature = perf_event__process_feature, 1000 .feature = process_feature_event,
958 .ordered_events = true, 1001 .ordered_events = true,
959 .ordering_requires_timestamps = true, 1002 .ordering_requires_timestamps = true,
960 }, 1003 },
@@ -975,6 +1018,8 @@ int cmd_report(int argc, const char **argv)
975 OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"), 1018 OPT_BOOLEAN(0, "mmaps", &report.mmaps_mode, "Display recorded tasks memory maps"),
976 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1019 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
977 "file", "vmlinux pathname"), 1020 "file", "vmlinux pathname"),
1021 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
1022 "don't load vmlinux even if found"),
978 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 1023 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
979 "file", "kallsyms pathname"), 1024 "file", "kallsyms pathname"),
980 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 1025 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
@@ -1056,7 +1101,7 @@ int cmd_report(int argc, const char **argv)
1056 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1101 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1057 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 1102 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1058 "Show a column with the sum of periods"), 1103 "Show a column with the sum of periods"),
1059 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 1104 OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &report.group_set,
1060 "Show event group information together"), 1105 "Show event group information together"),
1061 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", 1106 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
1062 "use branch records for per branch histogram filling", 1107 "use branch records for per branch histogram filling",
@@ -1173,6 +1218,8 @@ repeat:
1173 has_br_stack = perf_header__has_feat(&session->header, 1218 has_br_stack = perf_header__has_feat(&session->header,
1174 HEADER_BRANCH_STACK); 1219 HEADER_BRANCH_STACK);
1175 1220
1221 setup_forced_leader(&report, session->evlist);
1222
1176 if (itrace_synth_opts.last_branch) 1223 if (itrace_synth_opts.last_branch)
1177 has_br_stack = true; 1224 has_br_stack = true;
1178 1225
@@ -1295,6 +1342,7 @@ repeat:
1295 symbol_conf.priv_size += sizeof(u32); 1342 symbol_conf.priv_size += sizeof(u32);
1296 symbol_conf.sort_by_name = true; 1343 symbol_conf.sort_by_name = true;
1297 } 1344 }
1345 annotation_config__init();
1298 } 1346 }
1299 1347
1300 if (symbol__init(&session->header.env) < 0) 1348 if (symbol__init(&session->header.env) < 0)
@@ -1332,6 +1380,15 @@ repeat:
1332 report.range_num = 1; 1380 report.range_num = 1;
1333 } 1381 }
1334 1382
1383 if (session->tevent.pevent &&
1384 pevent_set_function_resolver(session->tevent.pevent,
1385 machine__resolve_kernel_addr,
1386 &session->machines.host) < 0) {
1387 pr_err("%s: failed to set libtraceevent function resolver\n",
1388 __func__);
1389 return -1;
1390 }
1391
1335 sort__setup_elide(stdout); 1392 sort__setup_elide(stdout);
1336 1393
1337 ret = __cmd_report(&report); 1394 ret = __cmd_report(&report);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 83283fedb00f..4dfdee668b0c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -254,6 +254,10 @@ struct thread_runtime {
254 u64 total_delay_time; 254 u64 total_delay_time;
255 255
256 int last_state; 256 int last_state;
257
258 char shortname[3];
259 bool comm_changed;
260
257 u64 migrations; 261 u64 migrations;
258}; 262};
259 263
@@ -897,6 +901,37 @@ struct sort_dimension {
897 struct list_head list; 901 struct list_head list;
898}; 902};
899 903
904/*
905 * handle runtime stats saved per thread
906 */
907static struct thread_runtime *thread__init_runtime(struct thread *thread)
908{
909 struct thread_runtime *r;
910
911 r = zalloc(sizeof(struct thread_runtime));
912 if (!r)
913 return NULL;
914
915 init_stats(&r->run_stats);
916 thread__set_priv(thread, r);
917
918 return r;
919}
920
921static struct thread_runtime *thread__get_runtime(struct thread *thread)
922{
923 struct thread_runtime *tr;
924
925 tr = thread__priv(thread);
926 if (tr == NULL) {
927 tr = thread__init_runtime(thread);
928 if (tr == NULL)
929 pr_debug("Failed to malloc memory for runtime data.\n");
930 }
931
932 return tr;
933}
934
900static int 935static int
901thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r) 936thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r)
902{ 937{
@@ -1480,6 +1515,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1480{ 1515{
1481 const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid"); 1516 const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid");
1482 struct thread *sched_in; 1517 struct thread *sched_in;
1518 struct thread_runtime *tr;
1483 int new_shortname; 1519 int new_shortname;
1484 u64 timestamp0, timestamp = sample->time; 1520 u64 timestamp0, timestamp = sample->time;
1485 s64 delta; 1521 s64 delta;
@@ -1519,22 +1555,28 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1519 if (sched_in == NULL) 1555 if (sched_in == NULL)
1520 return -1; 1556 return -1;
1521 1557
1558 tr = thread__get_runtime(sched_in);
1559 if (tr == NULL) {
1560 thread__put(sched_in);
1561 return -1;
1562 }
1563
1522 sched->curr_thread[this_cpu] = thread__get(sched_in); 1564 sched->curr_thread[this_cpu] = thread__get(sched_in);
1523 1565
1524 printf(" "); 1566 printf(" ");
1525 1567
1526 new_shortname = 0; 1568 new_shortname = 0;
1527 if (!sched_in->shortname[0]) { 1569 if (!tr->shortname[0]) {
1528 if (!strcmp(thread__comm_str(sched_in), "swapper")) { 1570 if (!strcmp(thread__comm_str(sched_in), "swapper")) {
1529 /* 1571 /*
1530 * Don't allocate a letter-number for swapper:0 1572 * Don't allocate a letter-number for swapper:0
1531 * as a shortname. Instead, we use '.' for it. 1573 * as a shortname. Instead, we use '.' for it.
1532 */ 1574 */
1533 sched_in->shortname[0] = '.'; 1575 tr->shortname[0] = '.';
1534 sched_in->shortname[1] = ' '; 1576 tr->shortname[1] = ' ';
1535 } else { 1577 } else {
1536 sched_in->shortname[0] = sched->next_shortname1; 1578 tr->shortname[0] = sched->next_shortname1;
1537 sched_in->shortname[1] = sched->next_shortname2; 1579 tr->shortname[1] = sched->next_shortname2;
1538 1580
1539 if (sched->next_shortname1 < 'Z') { 1581 if (sched->next_shortname1 < 'Z') {
1540 sched->next_shortname1++; 1582 sched->next_shortname1++;
@@ -1552,6 +1594,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1552 for (i = 0; i < cpus_nr; i++) { 1594 for (i = 0; i < cpus_nr; i++) {
1553 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i; 1595 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i;
1554 struct thread *curr_thread = sched->curr_thread[cpu]; 1596 struct thread *curr_thread = sched->curr_thread[cpu];
1597 struct thread_runtime *curr_tr;
1555 const char *pid_color = color; 1598 const char *pid_color = color;
1556 const char *cpu_color = color; 1599 const char *cpu_color = color;
1557 1600
@@ -1569,9 +1612,14 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1569 else 1612 else
1570 color_fprintf(stdout, cpu_color, "*"); 1613 color_fprintf(stdout, cpu_color, "*");
1571 1614
1572 if (sched->curr_thread[cpu]) 1615 if (sched->curr_thread[cpu]) {
1573 color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname); 1616 curr_tr = thread__get_runtime(sched->curr_thread[cpu]);
1574 else 1617 if (curr_tr == NULL) {
1618 thread__put(sched_in);
1619 return -1;
1620 }
1621 color_fprintf(stdout, pid_color, "%2s ", curr_tr->shortname);
1622 } else
1575 color_fprintf(stdout, color, " "); 1623 color_fprintf(stdout, color, " ");
1576 } 1624 }
1577 1625
@@ -1580,14 +1628,15 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1580 1628
1581 timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp)); 1629 timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp));
1582 color_fprintf(stdout, color, " %12s secs ", stimestamp); 1630 color_fprintf(stdout, color, " %12s secs ", stimestamp);
1583 if (new_shortname || (verbose > 0 && sched_in->tid)) { 1631 if (new_shortname || tr->comm_changed || (verbose > 0 && sched_in->tid)) {
1584 const char *pid_color = color; 1632 const char *pid_color = color;
1585 1633
1586 if (thread__has_color(sched_in)) 1634 if (thread__has_color(sched_in))
1587 pid_color = COLOR_PIDS; 1635 pid_color = COLOR_PIDS;
1588 1636
1589 color_fprintf(stdout, pid_color, "%s => %s:%d", 1637 color_fprintf(stdout, pid_color, "%s => %s:%d",
1590 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); 1638 tr->shortname, thread__comm_str(sched_in), sched_in->tid);
1639 tr->comm_changed = false;
1591 } 1640 }
1592 1641
1593 if (sched->map.comp && new_cpu) 1642 if (sched->map.comp && new_cpu)
@@ -1691,6 +1740,37 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1691 return err; 1740 return err;
1692} 1741}
1693 1742
1743static int perf_sched__process_comm(struct perf_tool *tool __maybe_unused,
1744 union perf_event *event,
1745 struct perf_sample *sample,
1746 struct machine *machine)
1747{
1748 struct thread *thread;
1749 struct thread_runtime *tr;
1750 int err;
1751
1752 err = perf_event__process_comm(tool, event, sample, machine);
1753 if (err)
1754 return err;
1755
1756 thread = machine__find_thread(machine, sample->pid, sample->tid);
1757 if (!thread) {
1758 pr_err("Internal error: can't find thread\n");
1759 return -1;
1760 }
1761
1762 tr = thread__get_runtime(thread);
1763 if (tr == NULL) {
1764 thread__put(thread);
1765 return -1;
1766 }
1767
1768 tr->comm_changed = true;
1769 thread__put(thread);
1770
1771 return 0;
1772}
1773
1694static int perf_sched__read_events(struct perf_sched *sched) 1774static int perf_sched__read_events(struct perf_sched *sched)
1695{ 1775{
1696 const struct perf_evsel_str_handler handlers[] = { 1776 const struct perf_evsel_str_handler handlers[] = {
@@ -2200,37 +2280,6 @@ static void save_idle_callchain(struct idle_thread_runtime *itr,
2200 callchain_cursor__copy(&itr->cursor, &callchain_cursor); 2280 callchain_cursor__copy(&itr->cursor, &callchain_cursor);
2201} 2281}
2202 2282
2203/*
2204 * handle runtime stats saved per thread
2205 */
2206static struct thread_runtime *thread__init_runtime(struct thread *thread)
2207{
2208 struct thread_runtime *r;
2209
2210 r = zalloc(sizeof(struct thread_runtime));
2211 if (!r)
2212 return NULL;
2213
2214 init_stats(&r->run_stats);
2215 thread__set_priv(thread, r);
2216
2217 return r;
2218}
2219
2220static struct thread_runtime *thread__get_runtime(struct thread *thread)
2221{
2222 struct thread_runtime *tr;
2223
2224 tr = thread__priv(thread);
2225 if (tr == NULL) {
2226 tr = thread__init_runtime(thread);
2227 if (tr == NULL)
2228 pr_debug("Failed to malloc memory for runtime data.\n");
2229 }
2230
2231 return tr;
2232}
2233
2234static struct thread *timehist_get_thread(struct perf_sched *sched, 2283static struct thread *timehist_get_thread(struct perf_sched *sched,
2235 struct perf_sample *sample, 2284 struct perf_sample *sample,
2236 struct machine *machine, 2285 struct machine *machine,
@@ -3291,7 +3340,7 @@ int cmd_sched(int argc, const char **argv)
3291 struct perf_sched sched = { 3340 struct perf_sched sched = {
3292 .tool = { 3341 .tool = {
3293 .sample = perf_sched__process_tracepoint_sample, 3342 .sample = perf_sched__process_tracepoint_sample,
3294 .comm = perf_event__process_comm, 3343 .comm = perf_sched__process_comm,
3295 .namespaces = perf_event__process_namespaces, 3344 .namespaces = perf_event__process_namespaces,
3296 .lost = perf_event__process_lost, 3345 .lost = perf_event__process_lost,
3297 .fork = perf_sched__process_fork_event, 3346 .fork = perf_sched__process_fork_event,
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ab19a6ee4093..313c42423393 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1489,6 +1489,7 @@ struct perf_script {
1489 bool show_switch_events; 1489 bool show_switch_events;
1490 bool show_namespace_events; 1490 bool show_namespace_events;
1491 bool show_lost_events; 1491 bool show_lost_events;
1492 bool show_round_events;
1492 bool allocated; 1493 bool allocated;
1493 bool per_event_dump; 1494 bool per_event_dump;
1494 struct cpu_map *cpus; 1495 struct cpu_map *cpus;
@@ -2104,6 +2105,16 @@ process_lost_event(struct perf_tool *tool,
2104 return 0; 2105 return 0;
2105} 2106}
2106 2107
2108static int
2109process_finished_round_event(struct perf_tool *tool __maybe_unused,
2110 union perf_event *event,
2111 struct ordered_events *oe __maybe_unused)
2112
2113{
2114 perf_event__fprintf(event, stdout);
2115 return 0;
2116}
2117
2107static void sig_handler(int sig __maybe_unused) 2118static void sig_handler(int sig __maybe_unused)
2108{ 2119{
2109 session_done = 1; 2120 session_done = 1;
@@ -2200,6 +2211,10 @@ static int __cmd_script(struct perf_script *script)
2200 script->tool.namespaces = process_namespaces_event; 2211 script->tool.namespaces = process_namespaces_event;
2201 if (script->show_lost_events) 2212 if (script->show_lost_events)
2202 script->tool.lost = process_lost_event; 2213 script->tool.lost = process_lost_event;
2214 if (script->show_round_events) {
2215 script->tool.ordered_events = false;
2216 script->tool.finished_round = process_finished_round_event;
2217 }
2203 2218
2204 if (perf_script__setup_per_event_dump(script)) { 2219 if (perf_script__setup_per_event_dump(script)) {
2205 pr_err("Couldn't create the per event dump files\n"); 2220 pr_err("Couldn't create the per event dump files\n");
@@ -2659,8 +2674,8 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
2659 } 2674 }
2660 2675
2661 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2676 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2662 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 2677 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2663 lang_dirent->d_name); 2678 lang_dirent->d_name);
2664 lang_dir = opendir(lang_path); 2679 lang_dir = opendir(lang_path);
2665 if (!lang_dir) 2680 if (!lang_dir)
2666 continue; 2681 continue;
@@ -2669,8 +2684,8 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
2669 script_root = get_script_root(script_dirent, REPORT_SUFFIX); 2684 script_root = get_script_root(script_dirent, REPORT_SUFFIX);
2670 if (script_root) { 2685 if (script_root) {
2671 desc = script_desc__findnew(script_root); 2686 desc = script_desc__findnew(script_root);
2672 snprintf(script_path, MAXPATHLEN, "%s/%s", 2687 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2673 lang_path, script_dirent->d_name); 2688 lang_path, script_dirent->d_name);
2674 read_script_info(desc, script_path); 2689 read_script_info(desc, script_path);
2675 free(script_root); 2690 free(script_root);
2676 } 2691 }
@@ -2706,7 +2721,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
2706 int match, len; 2721 int match, len;
2707 FILE *fp; 2722 FILE *fp;
2708 2723
2709 sprintf(filename, "%s/bin/%s-record", dir_name, scriptname); 2724 scnprintf(filename, MAXPATHLEN, "%s/bin/%s-record", dir_name, scriptname);
2710 2725
2711 fp = fopen(filename, "r"); 2726 fp = fopen(filename, "r");
2712 if (!fp) 2727 if (!fp)
@@ -2784,8 +2799,8 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
2784 } 2799 }
2785 2800
2786 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2801 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2787 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, 2802 scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
2788 lang_dirent->d_name); 2803 lang_dirent->d_name);
2789#ifdef NO_LIBPERL 2804#ifdef NO_LIBPERL
2790 if (strstr(lang_path, "perl")) 2805 if (strstr(lang_path, "perl"))
2791 continue; 2806 continue;
@@ -2840,8 +2855,8 @@ static char *get_script_path(const char *script_root, const char *suffix)
2840 return NULL; 2855 return NULL;
2841 2856
2842 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 2857 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
2843 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 2858 scnprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
2844 lang_dirent->d_name); 2859 lang_dirent->d_name);
2845 lang_dir = opendir(lang_path); 2860 lang_dir = opendir(lang_path);
2846 if (!lang_dir) 2861 if (!lang_dir)
2847 continue; 2862 continue;
@@ -2852,8 +2867,8 @@ static char *get_script_path(const char *script_root, const char *suffix)
2852 free(__script_root); 2867 free(__script_root);
2853 closedir(lang_dir); 2868 closedir(lang_dir);
2854 closedir(scripts_dir); 2869 closedir(scripts_dir);
2855 snprintf(script_path, MAXPATHLEN, "%s/%s", 2870 scnprintf(script_path, MAXPATHLEN, "%s/%s",
2856 lang_path, script_dirent->d_name); 2871 lang_path, script_dirent->d_name);
2857 return strdup(script_path); 2872 return strdup(script_path);
2858 } 2873 }
2859 free(__script_root); 2874 free(__script_root);
@@ -3139,6 +3154,8 @@ int cmd_script(int argc, const char **argv)
3139 "Show namespace events (if recorded)"), 3154 "Show namespace events (if recorded)"),
3140 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events, 3155 OPT_BOOLEAN('\0', "show-lost-events", &script.show_lost_events,
3141 "Show lost events (if recorded)"), 3156 "Show lost events (if recorded)"),
3157 OPT_BOOLEAN('\0', "show-round-events", &script.show_round_events,
3158 "Show round events (if recorded)"),
3142 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump, 3159 OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump,
3143 "Dump trace output to files named by the monitored events"), 3160 "Dump trace output to files named by the monitored events"),
3144 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 3161 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 98bf9d32f222..f5c454855908 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -168,6 +168,7 @@ static struct timespec ref_time;
168static struct cpu_map *aggr_map; 168static struct cpu_map *aggr_map;
169static aggr_get_id_t aggr_get_id; 169static aggr_get_id_t aggr_get_id;
170static bool append_file; 170static bool append_file;
171static bool interval_count;
171static const char *output_name; 172static const char *output_name;
172static int output_fd; 173static int output_fd;
173static int print_free_counters_hint; 174static int print_free_counters_hint;
@@ -507,14 +508,13 @@ static int perf_stat_synthesize_config(bool is_pipe)
507 508
508#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 509#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
509 510
510static int __store_counter_ids(struct perf_evsel *counter, 511static int __store_counter_ids(struct perf_evsel *counter)
511 struct cpu_map *cpus,
512 struct thread_map *threads)
513{ 512{
514 int cpu, thread; 513 int cpu, thread;
515 514
516 for (cpu = 0; cpu < cpus->nr; cpu++) { 515 for (cpu = 0; cpu < xyarray__max_x(counter->fd); cpu++) {
517 for (thread = 0; thread < threads->nr; thread++) { 516 for (thread = 0; thread < xyarray__max_y(counter->fd);
517 thread++) {
518 int fd = FD(counter, cpu, thread); 518 int fd = FD(counter, cpu, thread);
519 519
520 if (perf_evlist__id_add_fd(evsel_list, counter, 520 if (perf_evlist__id_add_fd(evsel_list, counter,
@@ -534,7 +534,7 @@ static int store_counter_ids(struct perf_evsel *counter)
534 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr)) 534 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
535 return -ENOMEM; 535 return -ENOMEM;
536 536
537 return __store_counter_ids(counter, cpus, threads); 537 return __store_counter_ids(counter);
538} 538}
539 539
540static bool perf_evsel__should_store_id(struct perf_evsel *counter) 540static bool perf_evsel__should_store_id(struct perf_evsel *counter)
@@ -571,6 +571,8 @@ static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel)
571static int __run_perf_stat(int argc, const char **argv) 571static int __run_perf_stat(int argc, const char **argv)
572{ 572{
573 int interval = stat_config.interval; 573 int interval = stat_config.interval;
574 int times = stat_config.times;
575 int timeout = stat_config.timeout;
574 char msg[BUFSIZ]; 576 char msg[BUFSIZ];
575 unsigned long long t0, t1; 577 unsigned long long t0, t1;
576 struct perf_evsel *counter; 578 struct perf_evsel *counter;
@@ -584,6 +586,9 @@ static int __run_perf_stat(int argc, const char **argv)
584 if (interval) { 586 if (interval) {
585 ts.tv_sec = interval / USEC_PER_MSEC; 587 ts.tv_sec = interval / USEC_PER_MSEC;
586 ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC; 588 ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC;
589 } else if (timeout) {
590 ts.tv_sec = timeout / USEC_PER_MSEC;
591 ts.tv_nsec = (timeout % USEC_PER_MSEC) * NSEC_PER_MSEC;
587 } else { 592 } else {
588 ts.tv_sec = 1; 593 ts.tv_sec = 1;
589 ts.tv_nsec = 0; 594 ts.tv_nsec = 0;
@@ -632,7 +637,19 @@ try_again:
632 if (verbose > 0) 637 if (verbose > 0)
633 ui__warning("%s\n", msg); 638 ui__warning("%s\n", msg);
634 goto try_again; 639 goto try_again;
635 } 640 } else if (target__has_per_thread(&target) &&
641 evsel_list->threads &&
642 evsel_list->threads->err_thread != -1) {
643 /*
644 * For global --per-thread case, skip current
645 * error thread.
646 */
647 if (!thread_map__remove(evsel_list->threads,
648 evsel_list->threads->err_thread)) {
649 evsel_list->threads->err_thread = -1;
650 goto try_again;
651 }
652 }
636 653
637 perf_evsel__open_strerror(counter, &target, 654 perf_evsel__open_strerror(counter, &target,
638 errno, msg, sizeof(msg)); 655 errno, msg, sizeof(msg));
@@ -696,10 +713,14 @@ try_again:
696 perf_evlist__start_workload(evsel_list); 713 perf_evlist__start_workload(evsel_list);
697 enable_counters(); 714 enable_counters();
698 715
699 if (interval) { 716 if (interval || timeout) {
700 while (!waitpid(child_pid, &status, WNOHANG)) { 717 while (!waitpid(child_pid, &status, WNOHANG)) {
701 nanosleep(&ts, NULL); 718 nanosleep(&ts, NULL);
719 if (timeout)
720 break;
702 process_interval(); 721 process_interval();
722 if (interval_count && !(--times))
723 break;
703 } 724 }
704 } 725 }
705 waitpid(child_pid, &status, 0); 726 waitpid(child_pid, &status, 0);
@@ -716,8 +737,13 @@ try_again:
716 enable_counters(); 737 enable_counters();
717 while (!done) { 738 while (!done) {
718 nanosleep(&ts, NULL); 739 nanosleep(&ts, NULL);
719 if (interval) 740 if (timeout)
741 break;
742 if (interval) {
720 process_interval(); 743 process_interval();
744 if (interval_count && !(--times))
745 break;
746 }
721 } 747 }
722 } 748 }
723 749
@@ -917,7 +943,7 @@ static void print_metric_csv(void *ctx,
917 char buf[64], *vals, *ends; 943 char buf[64], *vals, *ends;
918 944
919 if (unit == NULL || fmt == NULL) { 945 if (unit == NULL || fmt == NULL) {
920 fprintf(out, "%s%s%s%s", csv_sep, csv_sep, csv_sep, csv_sep); 946 fprintf(out, "%s%s", csv_sep, csv_sep);
921 return; 947 return;
922 } 948 }
923 snprintf(buf, sizeof(buf), fmt, val); 949 snprintf(buf, sizeof(buf), fmt, val);
@@ -1225,6 +1251,31 @@ static void aggr_update_shadow(void)
1225 } 1251 }
1226} 1252}
1227 1253
1254static void uniquify_event_name(struct perf_evsel *counter)
1255{
1256 char *new_name;
1257 char *config;
1258
1259 if (!counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
1260 strlen(counter->pmu_name)))
1261 return;
1262
1263 config = strchr(counter->name, '/');
1264 if (config) {
1265 if (asprintf(&new_name,
1266 "%s%s", counter->pmu_name, config) > 0) {
1267 free(counter->name);
1268 counter->name = new_name;
1269 }
1270 } else {
1271 if (asprintf(&new_name,
1272 "%s [%s]", counter->name, counter->pmu_name) > 0) {
1273 free(counter->name);
1274 counter->name = new_name;
1275 }
1276 }
1277}
1278
1228static void collect_all_aliases(struct perf_evsel *counter, 1279static void collect_all_aliases(struct perf_evsel *counter,
1229 void (*cb)(struct perf_evsel *counter, void *data, 1280 void (*cb)(struct perf_evsel *counter, void *data,
1230 bool first), 1281 bool first),
@@ -1253,7 +1304,9 @@ static bool collect_data(struct perf_evsel *counter,
1253 if (counter->merged_stat) 1304 if (counter->merged_stat)
1254 return false; 1305 return false;
1255 cb(counter, data, true); 1306 cb(counter, data, true);
1256 if (!no_merge && counter->auto_merge_stats) 1307 if (no_merge)
1308 uniquify_event_name(counter);
1309 else if (counter->auto_merge_stats)
1257 collect_all_aliases(counter, cb, data); 1310 collect_all_aliases(counter, cb, data);
1258 return true; 1311 return true;
1259} 1312}
@@ -1891,6 +1944,10 @@ static const struct option stat_options[] = {
1891 "command to run after to the measured command"), 1944 "command to run after to the measured command"),
1892 OPT_UINTEGER('I', "interval-print", &stat_config.interval, 1945 OPT_UINTEGER('I', "interval-print", &stat_config.interval,
1893 "print counts at regular interval in ms (>= 10)"), 1946 "print counts at regular interval in ms (>= 10)"),
1947 OPT_INTEGER(0, "interval-count", &stat_config.times,
1948 "print counts for fixed number of times"),
1949 OPT_UINTEGER(0, "timeout", &stat_config.timeout,
1950 "stop workload and print counts after a timeout period in ms (>= 10ms)"),
1894 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, 1951 OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
1895 "aggregate counts per processor socket", AGGR_SOCKET), 1952 "aggregate counts per processor socket", AGGR_SOCKET),
1896 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode, 1953 OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
@@ -2274,11 +2331,16 @@ static int add_default_attributes(void)
2274 return 0; 2331 return 0;
2275 2332
2276 if (transaction_run) { 2333 if (transaction_run) {
2334 struct parse_events_error errinfo;
2335
2277 if (pmu_have_event("cpu", "cycles-ct") && 2336 if (pmu_have_event("cpu", "cycles-ct") &&
2278 pmu_have_event("cpu", "el-start")) 2337 pmu_have_event("cpu", "el-start"))
2279 err = parse_events(evsel_list, transaction_attrs, NULL); 2338 err = parse_events(evsel_list, transaction_attrs,
2339 &errinfo);
2280 else 2340 else
2281 err = parse_events(evsel_list, transaction_limited_attrs, NULL); 2341 err = parse_events(evsel_list,
2342 transaction_limited_attrs,
2343 &errinfo);
2282 if (err) { 2344 if (err) {
2283 fprintf(stderr, "Cannot set up transaction events\n"); 2345 fprintf(stderr, "Cannot set up transaction events\n");
2284 return -1; 2346 return -1;
@@ -2688,7 +2750,7 @@ int cmd_stat(int argc, const char **argv)
2688 int status = -EINVAL, run_idx; 2750 int status = -EINVAL, run_idx;
2689 const char *mode; 2751 const char *mode;
2690 FILE *output = stderr; 2752 FILE *output = stderr;
2691 unsigned int interval; 2753 unsigned int interval, timeout;
2692 const char * const stat_subcommands[] = { "record", "report" }; 2754 const char * const stat_subcommands[] = { "record", "report" };
2693 2755
2694 setlocale(LC_ALL, ""); 2756 setlocale(LC_ALL, "");
@@ -2719,6 +2781,7 @@ int cmd_stat(int argc, const char **argv)
2719 return __cmd_report(argc, argv); 2781 return __cmd_report(argc, argv);
2720 2782
2721 interval = stat_config.interval; 2783 interval = stat_config.interval;
2784 timeout = stat_config.timeout;
2722 2785
2723 /* 2786 /*
2724 * For record command the -o is already taken care of. 2787 * For record command the -o is already taken care of.
@@ -2871,6 +2934,33 @@ int cmd_stat(int argc, const char **argv)
2871 "Please proceed with caution.\n"); 2934 "Please proceed with caution.\n");
2872 } 2935 }
2873 2936
2937 if (stat_config.times && interval)
2938 interval_count = true;
2939 else if (stat_config.times && !interval) {
2940 pr_err("interval-count option should be used together with "
2941 "interval-print.\n");
2942 parse_options_usage(stat_usage, stat_options, "interval-count", 0);
2943 parse_options_usage(stat_usage, stat_options, "I", 1);
2944 goto out;
2945 }
2946
2947 if (timeout && timeout < 100) {
2948 if (timeout < 10) {
2949 pr_err("timeout must be >= 10ms.\n");
2950 parse_options_usage(stat_usage, stat_options, "timeout", 0);
2951 goto out;
2952 } else
2953 pr_warning("timeout < 100ms. "
2954 "The overhead percentage could be high in some cases. "
2955 "Please proceed with caution.\n");
2956 }
2957 if (timeout && interval) {
2958 pr_err("timeout option is not supported with interval-print.\n");
2959 parse_options_usage(stat_usage, stat_options, "timeout", 0);
2960 parse_options_usage(stat_usage, stat_options, "I", 1);
2961 goto out;
2962 }
2963
2874 if (perf_evlist__alloc_stats(evsel_list, interval)) 2964 if (perf_evlist__alloc_stats(evsel_list, interval))
2875 goto out; 2965 goto out;
2876 2966
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index b7c823ba8374..f39bd60d2708 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -817,14 +817,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
817 struct perf_session *session = top->session; 817 struct perf_session *session = top->session;
818 union perf_event *event; 818 union perf_event *event;
819 struct machine *machine; 819 struct machine *machine;
820 u64 end, start;
821 int ret; 820 int ret;
822 821
823 md = opts->overwrite ? &evlist->overwrite_mmap[idx] : &evlist->mmap[idx]; 822 md = opts->overwrite ? &evlist->overwrite_mmap[idx] : &evlist->mmap[idx];
824 if (perf_mmap__read_init(md, opts->overwrite, &start, &end) < 0) 823 if (perf_mmap__read_init(md) < 0)
825 return; 824 return;
826 825
827 while ((event = perf_mmap__read_event(md, opts->overwrite, &start, end)) != NULL) { 826 while ((event = perf_mmap__read_event(md)) != NULL) {
828 ret = perf_evlist__parse_sample(evlist, event, &sample); 827 ret = perf_evlist__parse_sample(evlist, event, &sample);
829 if (ret) { 828 if (ret) {
830 pr_err("Can't parse sample, err = %d\n", ret); 829 pr_err("Can't parse sample, err = %d\n", ret);
@@ -879,7 +878,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
879 } else 878 } else
880 ++session->evlist->stats.nr_unknown_events; 879 ++session->evlist->stats.nr_unknown_events;
881next_event: 880next_event:
882 perf_mmap__consume(md, opts->overwrite); 881 perf_mmap__consume(md);
883 } 882 }
884 883
885 perf_mmap__read_done(md); 884 perf_mmap__read_done(md);
@@ -991,7 +990,7 @@ static int perf_top_overwrite_fallback(struct perf_top *top,
991 evlist__for_each_entry(evlist, counter) 990 evlist__for_each_entry(evlist, counter)
992 counter->attr.write_backward = false; 991 counter->attr.write_backward = false;
993 opts->overwrite = false; 992 opts->overwrite = false;
994 ui__warning("fall back to non-overwrite mode\n"); 993 pr_debug2("fall back to non-overwrite mode\n");
995 return 1; 994 return 1;
996} 995}
997 996
@@ -1224,8 +1223,10 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1224 1223
1225static int perf_top_config(const char *var, const char *value, void *cb __maybe_unused) 1224static int perf_top_config(const char *var, const char *value, void *cb __maybe_unused)
1226{ 1225{
1227 if (!strcmp(var, "top.call-graph")) 1226 if (!strcmp(var, "top.call-graph")) {
1228 var = "call-graph.record-mode"; /* fall-through */ 1227 var = "call-graph.record-mode";
1228 return perf_default_config(var, value, cb);
1229 }
1229 if (!strcmp(var, "top.children")) { 1230 if (!strcmp(var, "top.children")) {
1230 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 1231 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1231 return 0; 1232 return 0;
@@ -1307,7 +1308,9 @@ int cmd_top(int argc, const char **argv)
1307 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name", 1308 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
1308 "symbol to annotate"), 1309 "symbol to annotate"),
1309 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"), 1310 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
1310 OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"), 1311 OPT_CALLBACK('F', "freq", &top.record_opts, "freq or 'max'",
1312 "profile at this frequency",
1313 record__parse_freq),
1311 OPT_INTEGER('E', "entries", &top.print_entries, 1314 OPT_INTEGER('E', "entries", &top.print_entries,
1312 "display this many functions"), 1315 "display this many functions"),
1313 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1316 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
@@ -1490,6 +1493,8 @@ int cmd_top(int argc, const char **argv)
1490 if (status < 0) 1493 if (status < 0)
1491 goto out_delete_evlist; 1494 goto out_delete_evlist;
1492 1495
1496 annotation_config__init();
1497
1493 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1498 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1494 if (symbol__init(NULL) < 0) 1499 if (symbol__init(NULL) < 0)
1495 return -1; 1500 return -1;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index e7f1b182fc15..87b95c9410b4 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -19,6 +19,7 @@
19#include <traceevent/event-parse.h> 19#include <traceevent/event-parse.h>
20#include <api/fs/tracing_path.h> 20#include <api/fs/tracing_path.h>
21#include "builtin.h" 21#include "builtin.h"
22#include "util/cgroup.h"
22#include "util/color.h" 23#include "util/color.h"
23#include "util/debug.h" 24#include "util/debug.h"
24#include "util/env.h" 25#include "util/env.h"
@@ -83,6 +84,7 @@ struct trace {
83 struct perf_evlist *evlist; 84 struct perf_evlist *evlist;
84 struct machine *host; 85 struct machine *host;
85 struct thread *current; 86 struct thread *current;
87 struct cgroup *cgroup;
86 u64 base_time; 88 u64 base_time;
87 FILE *output; 89 FILE *output;
88 unsigned long nr_events; 90 unsigned long nr_events;
@@ -2370,6 +2372,34 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2370 trace__sched_stat_runtime)) 2372 trace__sched_stat_runtime))
2371 goto out_error_sched_stat_runtime; 2373 goto out_error_sched_stat_runtime;
2372 2374
2375 /*
2376 * If a global cgroup was set, apply it to all the events without an
2377 * explicit cgroup. I.e.:
2378 *
2379 * trace -G A -e sched:*switch
2380 *
2381 * Will set all raw_syscalls:sys_{enter,exit}, pgfault, vfs_getname, etc
2382 * _and_ sched:sched_switch to the 'A' cgroup, while:
2383 *
2384 * trace -e sched:*switch -G A
2385 *
2386 * will only set the sched:sched_switch event to the 'A' cgroup, all the
2387 * other events (raw_syscalls:sys_{enter,exit}, etc are left "without"
2388 * a cgroup (on the root cgroup, sys wide, etc).
2389 *
2390 * Multiple cgroups:
2391 *
2392 * trace -G A -e sched:*switch -G B
2393 *
2394 * the syscall ones go to the 'A' cgroup, the sched:sched_switch goes
2395 * to the 'B' cgroup.
2396 *
2397 * evlist__set_default_cgroup() grabs a reference of the passed cgroup
2398 * only for the evsels still without a cgroup, i.e. evsel->cgroup == NULL.
2399 */
2400 if (trace->cgroup)
2401 evlist__set_default_cgroup(trace->evlist, trace->cgroup);
2402
2373 err = perf_evlist__create_maps(evlist, &trace->opts.target); 2403 err = perf_evlist__create_maps(evlist, &trace->opts.target);
2374 if (err < 0) { 2404 if (err < 0) {
2375 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n"); 2405 fprintf(trace->output, "Problems parsing the target to trace, check your options!\n");
@@ -2472,8 +2502,13 @@ again:
2472 2502
2473 for (i = 0; i < evlist->nr_mmaps; i++) { 2503 for (i = 0; i < evlist->nr_mmaps; i++) {
2474 union perf_event *event; 2504 union perf_event *event;
2505 struct perf_mmap *md;
2506
2507 md = &evlist->mmap[i];
2508 if (perf_mmap__read_init(md) < 0)
2509 continue;
2475 2510
2476 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 2511 while ((event = perf_mmap__read_event(md)) != NULL) {
2477 struct perf_sample sample; 2512 struct perf_sample sample;
2478 2513
2479 ++trace->nr_events; 2514 ++trace->nr_events;
@@ -2486,7 +2521,7 @@ again:
2486 2521
2487 trace__handle_event(trace, event, &sample); 2522 trace__handle_event(trace, event, &sample);
2488next_event: 2523next_event:
2489 perf_evlist__mmap_consume(evlist, i); 2524 perf_mmap__consume(md);
2490 2525
2491 if (interrupted) 2526 if (interrupted)
2492 goto out_disable; 2527 goto out_disable;
@@ -2496,6 +2531,7 @@ next_event:
2496 draining = true; 2531 draining = true;
2497 } 2532 }
2498 } 2533 }
2534 perf_mmap__read_done(md);
2499 } 2535 }
2500 2536
2501 if (trace->nr_events == before) { 2537 if (trace->nr_events == before) {
@@ -2533,6 +2569,7 @@ out_delete_evlist:
2533 trace__symbols__exit(trace); 2569 trace__symbols__exit(trace);
2534 2570
2535 perf_evlist__delete(evlist); 2571 perf_evlist__delete(evlist);
2572 cgroup__put(trace->cgroup);
2536 trace->evlist = NULL; 2573 trace->evlist = NULL;
2537 trace->live = false; 2574 trace->live = false;
2538 return err; 2575 return err;
@@ -2972,6 +3009,18 @@ out:
2972 return err; 3009 return err;
2973} 3010}
2974 3011
3012static int trace__parse_cgroups(const struct option *opt, const char *str, int unset)
3013{
3014 struct trace *trace = opt->value;
3015
3016 if (!list_empty(&trace->evlist->entries))
3017 return parse_cgroups(opt, str, unset);
3018
3019 trace->cgroup = evlist__findnew_cgroup(trace->evlist, str);
3020
3021 return 0;
3022}
3023
2975int cmd_trace(int argc, const char **argv) 3024int cmd_trace(int argc, const char **argv)
2976{ 3025{
2977 const char *trace_usage[] = { 3026 const char *trace_usage[] = {
@@ -3062,6 +3111,8 @@ int cmd_trace(int argc, const char **argv)
3062 "print the PERF_RECORD_SAMPLE PERF_SAMPLE_ info, for debugging"), 3111 "print the PERF_RECORD_SAMPLE PERF_SAMPLE_ info, for debugging"),
3063 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 3112 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3064 "per thread proc mmap processing timeout in ms"), 3113 "per thread proc mmap processing timeout in ms"),
3114 OPT_CALLBACK('G', "cgroup", &trace, "name", "monitor event in cgroup name only",
3115 trace__parse_cgroups),
3065 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay, 3116 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay,
3066 "ms to wait before starting measurement after program " 3117 "ms to wait before starting measurement after program "
3067 "start"), 3118 "start"),
@@ -3088,6 +3139,11 @@ int cmd_trace(int argc, const char **argv)
3088 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands, 3139 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3089 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION); 3140 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
3090 3141
3142 if ((nr_cgroups || trace.cgroup) && !trace.opts.target.system_wide) {
3143 usage_with_options_msg(trace_usage, trace_options,
3144 "cgroup monitoring only available in system-wide mode");
3145 }
3146
3091 err = bpf__setup_stdout(trace.evlist); 3147 err = bpf__setup_stdout(trace.evlist);
3092 if (err) { 3148 if (err) {
3093 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf)); 3149 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 790ec25919a0..9aff89bc7535 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -42,6 +42,7 @@ arch/parisc/include/uapi/asm/errno.h
42arch/powerpc/include/uapi/asm/errno.h 42arch/powerpc/include/uapi/asm/errno.h
43arch/sparc/include/uapi/asm/errno.h 43arch/sparc/include/uapi/asm/errno.h
44arch/x86/include/uapi/asm/errno.h 44arch/x86/include/uapi/asm/errno.h
45arch/powerpc/include/uapi/asm/unistd.h
45include/asm-generic/bitops/arch_hweight.h 46include/asm-generic/bitops/arch_hweight.h
46include/asm-generic/bitops/const_hweight.h 47include/asm-generic/bitops/const_hweight.h
47include/asm-generic/bitops/__fls.h 48include/asm-generic/bitops/__fls.h
@@ -58,6 +59,7 @@ check () {
58 file=$1 59 file=$1
59 60
60 shift 61 shift
62 opts=
61 while [ -n "$*" ]; do 63 while [ -n "$*" ]; do
62 opts="$opts \"$1\"" 64 opts="$opts \"$1\""
63 shift 65 shift
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index 36673f98d66b..3eb7a39169f6 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -46,10 +46,6 @@
46#define CPUINFO_PROC {"Processor"} 46#define CPUINFO_PROC {"Processor"}
47#endif 47#endif
48 48
49#ifdef __metag__
50#define CPUINFO_PROC {"CPU"}
51#endif
52
53#ifdef __xtensa__ 49#ifdef __xtensa__
54#define CPUINFO_PROC {"core ID"} 50#define CPUINFO_PROC {"core ID"}
55#endif 51#endif
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cfe46236a5e5..8fec1abd0f1f 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -61,6 +61,8 @@ struct record_opts {
61 bool tail_synthesize; 61 bool tail_synthesize;
62 bool overwrite; 62 bool overwrite;
63 bool ignore_missing_thread; 63 bool ignore_missing_thread;
64 bool strict_freq;
65 bool sample_id;
64 unsigned int freq; 66 unsigned int freq;
65 unsigned int mmap_pages; 67 unsigned int mmap_pages;
66 unsigned int auxtrace_mmap_pages; 68 unsigned int auxtrace_mmap_pages;
@@ -82,4 +84,6 @@ struct record_opts {
82struct option; 84struct option;
83extern const char * const *record_usage; 85extern const char * const *record_usage;
84extern struct option *record_options; 86extern struct option *record_options;
87
88int record__parse_freq(const struct option *opt, const char *str, int unset);
85#endif 89#endif
diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
index 999a4e878162..17783913d330 100644
--- a/tools/perf/pmu-events/Build
+++ b/tools/perf/pmu-events/Build
@@ -1,10 +1,12 @@
1hostprogs := jevents 1hostprogs := jevents
2 2
3jevents-y += json.o jsmn.o jevents.o 3jevents-y += json.o jsmn.o jevents.o
4CHOSTFLAGS_jevents.o = -I$(srctree)/tools/include
4pmu-events-y += pmu-events.o 5pmu-events-y += pmu-events.o
5JDIR = pmu-events/arch/$(SRCARCH) 6JDIR = pmu-events/arch/$(SRCARCH)
6JSON = $(shell [ -d $(JDIR) ] && \ 7JSON = $(shell [ -d $(JDIR) ] && \
7 find $(JDIR) -name '*.json' -o -name 'mapfile.csv') 8 find $(JDIR) -name '*.json' -o -name 'mapfile.csv')
9
8# 10#
9# Locate/process JSON files in pmu-events/arch/ 11# Locate/process JSON files in pmu-events/arch/
10# directory and create tables in pmu-events.c. 12# directory and create tables in pmu-events.c.
diff --git a/tools/perf/pmu-events/README b/tools/perf/pmu-events/README
index c2ee3e4417fe..e62b09b6a844 100644
--- a/tools/perf/pmu-events/README
+++ b/tools/perf/pmu-events/README
@@ -11,12 +11,17 @@ tree tools/perf/pmu-events/arch/foo.
11 - Regular files with '.json' extension in the name are assumed to be 11 - Regular files with '.json' extension in the name are assumed to be
12 JSON files, each of which describes a set of PMU events. 12 JSON files, each of which describes a set of PMU events.
13 13
14 - Regular files with basename starting with 'mapfile.csv' are assumed 14 - The CSV file that maps a specific CPU to its set of PMU events is to
15 to be a CSV file that maps a specific CPU to its set of PMU events. 15 be named 'mapfile.csv' (see below for mapfile format).
16 (see below for mapfile format)
17 16
18 - Directories are traversed, but all other files are ignored. 17 - Directories are traversed, but all other files are ignored.
19 18
19 - To reduce JSON event duplication per architecture, platform JSONs may
20 use "ArchStdEvent" keyword to dereference an "Architecture standard
21 events", defined in architecture standard JSONs.
22 Architecture standard JSONs must be located in the architecture root
23 folder. Matching is based on the "EventName" field.
24
20The PMU events supported by a CPU model are expected to grouped into topics 25The PMU events supported by a CPU model are expected to grouped into topics
21such as Pipelining, Cache, Memory, Floating-point etc. All events for a topic 26such as Pipelining, Cache, Memory, Floating-point etc. All events for a topic
22should be placed in a separate JSON file - where the file name identifies 27should be placed in a separate JSON file - where the file name identifies
@@ -29,6 +34,10 @@ sub directory. Thus for the Silvermont X86 CPU:
29 Cache.json Memory.json Virtual-Memory.json 34 Cache.json Memory.json Virtual-Memory.json
30 Frontend.json Pipeline.json 35 Frontend.json Pipeline.json
31 36
37The JSONs folder for a CPU model/family may be placed in the root arch
38folder, or may be placed in a vendor sub-folder under the arch folder
39for instances where the arch and vendor are not the same.
40
32Using the JSON files and the mapfile, 'jevents' generates the C source file, 41Using the JSON files and the mapfile, 'jevents' generates the C source file,
33'pmu-events.c', which encodes the two sets of tables: 42'pmu-events.c', which encodes the two sets of tables:
34 43
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/branch.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json
index 3b6208763e50..0b0e6b26605b 100644
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/branch.json
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/branch.json
@@ -1,25 +1,23 @@
1[ 1[
2 {, 2 {
3 "EventCode": "0x7A", 3 "ArchStdEvent": "BR_INDIRECT_SPEC",
4 "EventName": "BR_INDIRECT_SPEC",
5 "BriefDescription": "Branch speculatively executed - Indirect branch"
6 }, 4 },
7 {, 5 {
8 "EventCode": "0xC9", 6 "EventCode": "0xC9",
9 "EventName": "BR_COND", 7 "EventName": "BR_COND",
10 "BriefDescription": "Conditional branch executed" 8 "BriefDescription": "Conditional branch executed"
11 }, 9 },
12 {, 10 {
13 "EventCode": "0xCA", 11 "EventCode": "0xCA",
14 "EventName": "BR_INDIRECT_MISPRED", 12 "EventName": "BR_INDIRECT_MISPRED",
15 "BriefDescription": "Indirect branch mispredicted" 13 "BriefDescription": "Indirect branch mispredicted"
16 }, 14 },
17 {, 15 {
18 "EventCode": "0xCB", 16 "EventCode": "0xCB",
19 "EventName": "BR_INDIRECT_MISPRED_ADDR", 17 "EventName": "BR_INDIRECT_MISPRED_ADDR",
20 "BriefDescription": "Indirect branch mispredicted because of address miscompare" 18 "BriefDescription": "Indirect branch mispredicted because of address miscompare"
21 }, 19 },
22 {, 20 {
23 "EventCode": "0xCC", 21 "EventCode": "0xCC",
24 "EventName": "BR_COND_MISPRED", 22 "EventName": "BR_COND_MISPRED",
25 "BriefDescription": "Conditional branch mispredicted" 23 "BriefDescription": "Conditional branch mispredicted"
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json
new file mode 100644
index 000000000000..ce33b2553277
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/bus.json
@@ -0,0 +1,8 @@
1[
2 {
3 "ArchStdEvent": "BUS_ACCESS_RD",
4 },
5 {
6 "ArchStdEvent": "BUS_ACCESS_WR",
7 }
8]
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json
new file mode 100644
index 000000000000..5dfbec43c9f9
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/cache.json
@@ -0,0 +1,27 @@
1[
2 {
3 "EventCode": "0xC2",
4 "EventName": "PREFETCH_LINEFILL",
5 "BriefDescription": "Linefill because of prefetch"
6 },
7 {
8 "EventCode": "0xC3",
9 "EventName": "PREFETCH_LINEFILL_DROP",
10 "BriefDescription": "Instruction Cache Throttle occurred"
11 },
12 {
13 "EventCode": "0xC4",
14 "EventName": "READ_ALLOC_ENTER",
15 "BriefDescription": "Entering read allocate mode"
16 },
17 {
18 "EventCode": "0xC5",
19 "EventName": "READ_ALLOC",
20 "BriefDescription": "Read allocate mode"
21 },
22 {
23 "EventCode": "0xC8",
24 "EventName": "EXT_SNOOP",
25 "BriefDescription": "SCU Snooped data from another CPU for this CPU"
26 }
27]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/memory.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json
index 480d9f7460ab..25ae642ba381 100644
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/memory.json
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/memory.json
@@ -1,20 +1,10 @@
1[ 1[
2 {, 2 {
3 "EventCode": "0x60",
4 "EventName": "BUS_ACCESS_LD",
5 "BriefDescription": "Bus access - Read"
6 },
7 {,
8 "EventCode": "0x61",
9 "EventName": "BUS_ACCESS_ST",
10 "BriefDescription": "Bus access - Write"
11 },
12 {,
13 "EventCode": "0xC0", 3 "EventCode": "0xC0",
14 "EventName": "EXT_MEM_REQ", 4 "EventName": "EXT_MEM_REQ",
15 "BriefDescription": "External memory request" 5 "BriefDescription": "External memory request"
16 }, 6 },
17 {, 7 {
18 "EventCode": "0xC1", 8 "EventCode": "0xC1",
19 "EventName": "EXT_MEM_REQ_NC", 9 "EventName": "EXT_MEM_REQ_NC",
20 "BriefDescription": "Non-cacheable external memory request" 10 "BriefDescription": "Non-cacheable external memory request"
diff --git a/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json
new file mode 100644
index 000000000000..6cc6cbd7bf0b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/other.json
@@ -0,0 +1,28 @@
1[
2 {
3 "ArchStdEvent": "EXC_IRQ",
4 },
5 {
6 "ArchStdEvent": "EXC_FIQ",
7 },
8 {
9 "EventCode": "0xC6",
10 "EventName": "PRE_DECODE_ERR",
11 "BriefDescription": "Pre-decode error"
12 },
13 {
14 "EventCode": "0xD0",
15 "EventName": "L1I_CACHE_ERR",
16 "BriefDescription": "L1 Instruction Cache (data or tag) memory error"
17 },
18 {
19 "EventCode": "0xD1",
20 "EventName": "L1D_CACHE_ERR",
21 "BriefDescription": "L1 Data Cache (data, tag or dirty) memory error, correctable or non-correctable"
22 },
23 {
24 "EventCode": "0xD2",
25 "EventName": "TLB_ERR",
26 "BriefDescription": "TLB memory error"
27 }
28]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/pipeline.json b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json
index 3149fb90555a..f45a6b5d0025 100644
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/pipeline.json
+++ b/tools/perf/pmu-events/arch/arm64/arm/cortex-a53/pipeline.json
@@ -1,50 +1,50 @@
1[ 1[
2 {, 2 {
3 "EventCode": "0xC7", 3 "EventCode": "0xC7",
4 "EventName": "STALL_SB_FULL", 4 "EventName": "STALL_SB_FULL",
5 "BriefDescription": "Data Write operation that stalls the pipeline because the store buffer is full" 5 "BriefDescription": "Data Write operation that stalls the pipeline because the store buffer is full"
6 }, 6 },
7 {, 7 {
8 "EventCode": "0xE0", 8 "EventCode": "0xE0",
9 "EventName": "OTHER_IQ_DEP_STALL", 9 "EventName": "OTHER_IQ_DEP_STALL",
10 "BriefDescription": "Cycles that the DPU IQ is empty and that is not because of a recent micro-TLB miss, instruction cache miss or pre-decode error" 10 "BriefDescription": "Cycles that the DPU IQ is empty and that is not because of a recent micro-TLB miss, instruction cache miss or pre-decode error"
11 }, 11 },
12 {, 12 {
13 "EventCode": "0xE1", 13 "EventCode": "0xE1",
14 "EventName": "IC_DEP_STALL", 14 "EventName": "IC_DEP_STALL",
15 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction cache miss being processed" 15 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction cache miss being processed"
16 }, 16 },
17 {, 17 {
18 "EventCode": "0xE2", 18 "EventCode": "0xE2",
19 "EventName": "IUTLB_DEP_STALL", 19 "EventName": "IUTLB_DEP_STALL",
20 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction micro-TLB miss being processed" 20 "BriefDescription": "Cycles the DPU IQ is empty and there is an instruction micro-TLB miss being processed"
21 }, 21 },
22 {, 22 {
23 "EventCode": "0xE3", 23 "EventCode": "0xE3",
24 "EventName": "DECODE_DEP_STALL", 24 "EventName": "DECODE_DEP_STALL",
25 "BriefDescription": "Cycles the DPU IQ is empty and there is a pre-decode error being processed" 25 "BriefDescription": "Cycles the DPU IQ is empty and there is a pre-decode error being processed"
26 }, 26 },
27 {, 27 {
28 "EventCode": "0xE4", 28 "EventCode": "0xE4",
29 "EventName": "OTHER_INTERLOCK_STALL", 29 "EventName": "OTHER_INTERLOCK_STALL",
30 "BriefDescription": "Cycles there is an interlock other than Advanced SIMD/Floating-point instructions or load/store instruction" 30 "BriefDescription": "Cycles there is an interlock other than Advanced SIMD/Floating-point instructions or load/store instruction"
31 }, 31 },
32 {, 32 {
33 "EventCode": "0xE5", 33 "EventCode": "0xE5",
34 "EventName": "AGU_DEP_STALL", 34 "EventName": "AGU_DEP_STALL",
35 "BriefDescription": "Cycles there is an interlock for a load/store instruction waiting for data to calculate the address in the AGU" 35 "BriefDescription": "Cycles there is an interlock for a load/store instruction waiting for data to calculate the address in the AGU"
36 }, 36 },
37 {, 37 {
38 "EventCode": "0xE6", 38 "EventCode": "0xE6",
39 "EventName": "SIMD_DEP_STALL", 39 "EventName": "SIMD_DEP_STALL",
40 "BriefDescription": "Cycles there is an interlock for an Advanced SIMD/Floating-point operation." 40 "BriefDescription": "Cycles there is an interlock for an Advanced SIMD/Floating-point operation."
41 }, 41 },
42 {, 42 {
43 "EventCode": "0xE7", 43 "EventCode": "0xE7",
44 "EventName": "LD_DEP_STALL", 44 "EventName": "LD_DEP_STALL",
45 "BriefDescription": "Cycles there is a stall in the Wr stage because of a load miss" 45 "BriefDescription": "Cycles there is a stall in the Wr stage because of a load miss"
46 }, 46 },
47 {, 47 {
48 "EventCode": "0xE8", 48 "EventCode": "0xE8",
49 "EventName": "ST_DEP_STALL", 49 "EventName": "ST_DEP_STALL",
50 "BriefDescription": "Cycles there is a stall in the Wr stage because of a store" 50 "BriefDescription": "Cycles there is a stall in the Wr stage because of a store"
diff --git a/tools/perf/pmu-events/arch/arm64/armv8-recommended.json b/tools/perf/pmu-events/arch/arm64/armv8-recommended.json
new file mode 100644
index 000000000000..6328828c018c
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/armv8-recommended.json
@@ -0,0 +1,452 @@
1[
2 {
3 "PublicDescription": "Attributable Level 1 data cache access, read",
4 "EventCode": "0x40",
5 "EventName": "L1D_CACHE_RD",
6 "BriefDescription": "L1D cache access, read"
7 },
8 {
9 "PublicDescription": "Attributable Level 1 data cache access, write",
10 "EventCode": "0x41",
11 "EventName": "L1D_CACHE_WR",
12 "BriefDescription": "L1D cache access, write"
13 },
14 {
15 "PublicDescription": "Attributable Level 1 data cache refill, read",
16 "EventCode": "0x42",
17 "EventName": "L1D_CACHE_REFILL_RD",
18 "BriefDescription": "L1D cache refill, read"
19 },
20 {
21 "PublicDescription": "Attributable Level 1 data cache refill, write",
22 "EventCode": "0x43",
23 "EventName": "L1D_CACHE_REFILL_WR",
24 "BriefDescription": "L1D cache refill, write"
25 },
26 {
27 "PublicDescription": "Attributable Level 1 data cache refill, inner",
28 "EventCode": "0x44",
29 "EventName": "L1D_CACHE_REFILL_INNER",
30 "BriefDescription": "L1D cache refill, inner"
31 },
32 {
33 "PublicDescription": "Attributable Level 1 data cache refill, outer",
34 "EventCode": "0x45",
35 "EventName": "L1D_CACHE_REFILL_OUTER",
36 "BriefDescription": "L1D cache refill, outer"
37 },
38 {
39 "PublicDescription": "Attributable Level 1 data cache Write-Back, victim",
40 "EventCode": "0x46",
41 "EventName": "L1D_CACHE_WB_VICTIM",
42 "BriefDescription": "L1D cache Write-Back, victim"
43 },
44 {
45 "PublicDescription": "Level 1 data cache Write-Back, cleaning and coherency",
46 "EventCode": "0x47",
47 "EventName": "L1D_CACHE_WB_CLEAN",
48 "BriefDescription": "L1D cache Write-Back, cleaning and coherency"
49 },
50 {
51 "PublicDescription": "Attributable Level 1 data cache invalidate",
52 "EventCode": "0x48",
53 "EventName": "L1D_CACHE_INVAL",
54 "BriefDescription": "L1D cache invalidate"
55 },
56 {
57 "PublicDescription": "Attributable Level 1 data TLB refill, read",
58 "EventCode": "0x4C",
59 "EventName": "L1D_TLB_REFILL_RD",
60 "BriefDescription": "L1D tlb refill, read"
61 },
62 {
63 "PublicDescription": "Attributable Level 1 data TLB refill, write",
64 "EventCode": "0x4D",
65 "EventName": "L1D_TLB_REFILL_WR",
66 "BriefDescription": "L1D tlb refill, write"
67 },
68 {
69 "PublicDescription": "Attributable Level 1 data or unified TLB access, read",
70 "EventCode": "0x4E",
71 "EventName": "L1D_TLB_RD",
72 "BriefDescription": "L1D tlb access, read"
73 },
74 {
75 "PublicDescription": "Attributable Level 1 data or unified TLB access, write",
76 "EventCode": "0x4F",
77 "EventName": "L1D_TLB_WR",
78 "BriefDescription": "L1D tlb access, write"
79 },
80 {
81 "PublicDescription": "Attributable Level 2 data cache access, read",
82 "EventCode": "0x50",
83 "EventName": "L2D_CACHE_RD",
84 "BriefDescription": "L2D cache access, read"
85 },
86 {
87 "PublicDescription": "Attributable Level 2 data cache access, write",
88 "EventCode": "0x51",
89 "EventName": "L2D_CACHE_WR",
90 "BriefDescription": "L2D cache access, write"
91 },
92 {
93 "PublicDescription": "Attributable Level 2 data cache refill, read",
94 "EventCode": "0x52",
95 "EventName": "L2D_CACHE_REFILL_RD",
96 "BriefDescription": "L2D cache refill, read"
97 },
98 {
99 "PublicDescription": "Attributable Level 2 data cache refill, write",
100 "EventCode": "0x53",
101 "EventName": "L2D_CACHE_REFILL_WR",
102 "BriefDescription": "L2D cache refill, write"
103 },
104 {
105 "PublicDescription": "Attributable Level 2 data cache Write-Back, victim",
106 "EventCode": "0x56",
107 "EventName": "L2D_CACHE_WB_VICTIM",
108 "BriefDescription": "L2D cache Write-Back, victim"
109 },
110 {
111 "PublicDescription": "Level 2 data cache Write-Back, cleaning and coherency",
112 "EventCode": "0x57",
113 "EventName": "L2D_CACHE_WB_CLEAN",
114 "BriefDescription": "L2D cache Write-Back, cleaning and coherency"
115 },
116 {
117 "PublicDescription": "Attributable Level 2 data cache invalidate",
118 "EventCode": "0x58",
119 "EventName": "L2D_CACHE_INVAL",
120 "BriefDescription": "L2D cache invalidate"
121 },
122 {
123 "PublicDescription": "Attributable Level 2 data or unified TLB refill, read",
124 "EventCode": "0x5c",
125 "EventName": "L2D_TLB_REFILL_RD",
126 "BriefDescription": "L2D cache refill, read"
127 },
128 {
129 "PublicDescription": "Attributable Level 2 data or unified TLB refill, write",
130 "EventCode": "0x5d",
131 "EventName": "L2D_TLB_REFILL_WR",
132 "BriefDescription": "L2D cache refill, write"
133 },
134 {
135 "PublicDescription": "Attributable Level 2 data or unified TLB access, read",
136 "EventCode": "0x5e",
137 "EventName": "L2D_TLB_RD",
138 "BriefDescription": "L2D cache access, read"
139 },
140 {
141 "PublicDescription": "Attributable Level 2 data or unified TLB access, write",
142 "EventCode": "0x5f",
143 "EventName": "L2D_TLB_WR",
144 "BriefDescription": "L2D cache access, write"
145 },
146 {
147 "PublicDescription": "Bus access read",
148 "EventCode": "0x60",
149 "EventName": "BUS_ACCESS_RD",
150 "BriefDescription": "Bus access read"
151 },
152 {
153 "PublicDescription": "Bus access write",
154 "EventCode": "0x61",
155 "EventName": "BUS_ACCESS_WR",
156 "BriefDescription": "Bus access write"
157 }
158 {
159 "PublicDescription": "Bus access, Normal, Cacheable, Shareable",
160 "EventCode": "0x62",
161 "EventName": "BUS_ACCESS_SHARED",
162 "BriefDescription": "Bus access, Normal, Cacheable, Shareable"
163 }
164 {
165 "PublicDescription": "Bus access, not Normal, Cacheable, Shareable",
166 "EventCode": "0x63",
167 "EventName": "BUS_ACCESS_NOT_SHARED",
168 "BriefDescription": "Bus access, not Normal, Cacheable, Shareable"
169 }
170 {
171 "PublicDescription": "Bus access, Normal",
172 "EventCode": "0x64",
173 "EventName": "BUS_ACCESS_NORMAL",
174 "BriefDescription": "Bus access, Normal"
175 }
176 {
177 "PublicDescription": "Bus access, peripheral",
178 "EventCode": "0x65",
179 "EventName": "BUS_ACCESS_PERIPH",
180 "BriefDescription": "Bus access, peripheral"
181 }
182 {
183 "PublicDescription": "Data memory access, read",
184 "EventCode": "0x66",
185 "EventName": "MEM_ACCESS_RD",
186 "BriefDescription": "Data memory access, read"
187 }
188 {
189 "PublicDescription": "Data memory access, write",
190 "EventCode": "0x67",
191 "EventName": "MEM_ACCESS_WR",
192 "BriefDescription": "Data memory access, write"
193 }
194 {
195 "PublicDescription": "Unaligned access, read",
196 "EventCode": "0x68",
197 "EventName": "UNALIGNED_LD_SPEC",
198 "BriefDescription": "Unaligned access, read"
199 }
200 {
201 "PublicDescription": "Unaligned access, write",
202 "EventCode": "0x69",
203 "EventName": "UNALIGNED_ST_SPEC",
204 "BriefDescription": "Unaligned access, write"
205 }
206 {
207 "PublicDescription": "Unaligned access",
208 "EventCode": "0x6a",
209 "EventName": "UNALIGNED_LDST_SPEC",
210 "BriefDescription": "Unaligned access"
211 }
212 {
213 "PublicDescription": "Exclusive operation speculatively executed, LDREX or LDX",
214 "EventCode": "0x6c",
215 "EventName": "LDREX_SPEC",
216 "BriefDescription": "Exclusive operation speculatively executed, LDREX or LDX"
217 }
218 {
219 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX pass",
220 "EventCode": "0x6d",
221 "EventName": "STREX_PASS_SPEC",
222 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX pass"
223 }
224 {
225 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX fail",
226 "EventCode": "0x6e",
227 "EventName": "STREX_FAIL_SPEC",
228 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX fail"
229 }
230 {
231 "PublicDescription": "Exclusive operation speculatively executed, STREX or STX",
232 "EventCode": "0x6f",
233 "EventName": "STREX_SPEC",
234 "BriefDescription": "Exclusive operation speculatively executed, STREX or STX"
235 }
236 {
237 "PublicDescription": "Operation speculatively executed, load",
238 "EventCode": "0x70",
239 "EventName": "LD_SPEC",
240 "BriefDescription": "Operation speculatively executed, load"
241 }
242 {
243 "PublicDescription": "Operation speculatively executed, store"
244 "EventCode": "0x71",
245 "EventName": "ST_SPEC",
246 "BriefDescription": "Operation speculatively executed, store"
247 }
248 {
249 "PublicDescription": "Operation speculatively executed, load or store",
250 "EventCode": "0x72",
251 "EventName": "LDST_SPEC",
252 "BriefDescription": "Operation speculatively executed, load or store"
253 }
254 {
255 "PublicDescription": "Operation speculatively executed, integer data processing",
256 "EventCode": "0x73",
257 "EventName": "DP_SPEC",
258 "BriefDescription": "Operation speculatively executed, integer data processing"
259 }
260 {
261 "PublicDescription": "Operation speculatively executed, Advanced SIMD instruction",
262 "EventCode": "0x74",
263 "EventName": "ASE_SPEC",
264 "BriefDescription": "Operation speculatively executed, Advanced SIMD instruction",
265 }
266 {
267 "PublicDescription": "Operation speculatively executed, floating-point instruction",
268 "EventCode": "0x75",
269 "EventName": "VFP_SPEC",
270 "BriefDescription": "Operation speculatively executed, floating-point instruction"
271 }
272 {
273 "PublicDescription": "Operation speculatively executed, software change of the PC",
274 "EventCode": "0x76",
275 "EventName": "PC_WRITE_SPEC",
276 "BriefDescription": "Operation speculatively executed, software change of the PC"
277 }
278 {
279 "PublicDescription": "Operation speculatively executed, Cryptographic instruction",
280 "EventCode": "0x77",
281 "EventName": "CRYPTO_SPEC",
282 "BriefDescription": "Operation speculatively executed, Cryptographic instruction"
283 }
284 {
285 "PublicDescription": "Branch speculatively executed, immediate branch"
286 "EventCode": "0x78",
287 "EventName": "BR_IMMED_SPEC",
288 "BriefDescription": "Branch speculatively executed, immediate branch"
289 }
290 {
291 "PublicDescription": "Branch speculatively executed, procedure return"
292 "EventCode": "0x79",
293 "EventName": "BR_RETURN_SPEC",
294 "BriefDescription": "Branch speculatively executed, procedure return"
295 }
296 {
297 "PublicDescription": "Branch speculatively executed, indirect branch"
298 "EventCode": "0x7a",
299 "EventName": "BR_INDIRECT_SPEC",
300 "BriefDescription": "Branch speculatively executed, indirect branch"
301 }
302 {
303 "PublicDescription": "Barrier speculatively executed, ISB"
304 "EventCode": "0x7c",
305 "EventName": "ISB_SPEC",
306 "BriefDescription": "Barrier speculatively executed, ISB"
307 }
308 {
309 "PublicDescription": "Barrier speculatively executed, DSB"
310 "EventCode": "0x7d",
311 "EventName": "DSB_SPEC",
312 "BriefDescription": "Barrier speculatively executed, DSB"
313 }
314 {
315 "PublicDescription": "Barrier speculatively executed, DMB"
316 "EventCode": "0x7e",
317 "EventName": "DMB_SPEC",
318 "BriefDescription": "Barrier speculatively executed, DMB"
319 }
320 {
321 "PublicDescription": "Exception taken, Other synchronous"
322 "EventCode": "0x81",
323 "EventName": "EXC_UNDEF",
324 "BriefDescription": "Exception taken, Other synchronous"
325 }
326 {
327 "PublicDescription": "Exception taken, Supervisor Call"
328 "EventCode": "0x82",
329 "EventName": "EXC_SVC",
330 "BriefDescription": "Exception taken, Supervisor Call"
331 }
332 {
333 "PublicDescription": "Exception taken, Instruction Abort"
334 "EventCode": "0x83",
335 "EventName": "EXC_PABORT",
336 "BriefDescription": "Exception taken, Instruction Abort"
337 }
338 {
339 "PublicDescription": "Exception taken, Data Abort and SError"
340 "EventCode": "0x84",
341 "EventName": "EXC_DABORT",
342 "BriefDescription": "Exception taken, Data Abort and SError"
343 }
344 {
345 "PublicDescription": "Exception taken, IRQ"
346 "EventCode": "0x86",
347 "EventName": "EXC_IRQ",
348 "BriefDescription": "Exception taken, IRQ"
349 }
350 {
351 "PublicDescription": "Exception taken, FIQ"
352 "EventCode": "0x87",
353 "EventName": "EXC_FIQ",
354 "BriefDescription": "Exception taken, FIQ"
355 }
356 {
357 "PublicDescription": "Exception taken, Secure Monitor Call"
358 "EventCode": "0x88",
359 "EventName": "EXC_SMC",
360 "BriefDescription": "Exception taken, Secure Monitor Call"
361 }
362 {
363 "PublicDescription": "Exception taken, Hypervisor Call"
364 "EventCode": "0x8a",
365 "EventName": "EXC_HVC",
366 "BriefDescription": "Exception taken, Hypervisor Call"
367 }
368 {
369 "PublicDescription": "Exception taken, Instruction Abort not taken locally"
370 "EventCode": "0x8b",
371 "EventName": "EXC_TRAP_PABORT",
372 "BriefDescription": "Exception taken, Instruction Abort not taken locally"
373 }
374 {
375 "PublicDescription": "Exception taken, Data Abort or SError not taken locally"
376 "EventCode": "0x8c",
377 "EventName": "EXC_TRAP_DABORT",
378 "BriefDescription": "Exception taken, Data Abort or SError not taken locally"
379 }
380 {
381 "PublicDescription": "Exception taken, Other traps not taken locally"
382 "EventCode": "0x8d",
383 "EventName": "EXC_TRAP_OTHER",
384 "BriefDescription": "Exception taken, Other traps not taken locally"
385 }
386 {
387 "PublicDescription": "Exception taken, IRQ not taken locally"
388 "EventCode": "0x8e",
389 "EventName": "EXC_TRAP_IRQ",
390 "BriefDescription": "Exception taken, IRQ not taken locally"
391 }
392 {
393 "PublicDescription": "Exception taken, FIQ not taken locally"
394 "EventCode": "0x8f",
395 "EventName": "EXC_TRAP_FIQ",
396 "BriefDescription": "Exception taken, FIQ not taken locally"
397 }
398 {
399 "PublicDescription": "Release consistency operation speculatively executed, Load-Acquire"
400 "EventCode": "0x90",
401 "EventName": "RC_LD_SPEC",
402 "BriefDescription": "Release consistency operation speculatively executed, Load-Acquire"
403 }
404 {
405 "PublicDescription": "Release consistency operation speculatively executed, Store-Release"
406 "EventCode": "0x91",
407 "EventName": "RC_ST_SPEC",
408 "BriefDescription": "Release consistency operation speculatively executed, Store-Release"
409 }
410 {
411 "PublicDescription": "Attributable Level 3 data or unified cache access, read"
412 "EventCode": "0xa0",
413 "EventName": "L3D_CACHE_RD",
414 "BriefDescription": "Attributable Level 3 data or unified cache access, read"
415 }
416 {
417 "PublicDescription": "Attributable Level 3 data or unified cache access, write"
418 "EventCode": "0xa1",
419 "EventName": "L3D_CACHE_WR",
420 "BriefDescription": "Attributable Level 3 data or unified cache access, write"
421 }
422 {
423 "PublicDescription": "Attributable Level 3 data or unified cache refill, read"
424 "EventCode": "0xa2",
425 "EventName": "L3D_CACHE_REFILL_RD",
426 "BriefDescription": "Attributable Level 3 data or unified cache refill, read"
427 }
428 {
429 "PublicDescription": "Attributable Level 3 data or unified cache refill, write"
430 "EventCode": "0xa3",
431 "EventName": "L3D_CACHE_REFILL_WR",
432 "BriefDescription": "Attributable Level 3 data or unified cache refill, write"
433 }
434 {
435 "PublicDescription": "Attributable Level 3 data or unified cache Write-Back, victim"
436 "EventCode": "0xa6",
437 "EventName": "L3D_CACHE_WB_VICTIM",
438 "BriefDescription": "Attributable Level 3 data or unified cache Write-Back, victim"
439 }
440 {
441 "PublicDescription": "Attributable Level 3 data or unified cache Write-Back, cache clean"
442 "EventCode": "0xa7",
443 "EventName": "L3D_CACHE_WB_CLEAN",
444 "BriefDescription": "Attributable Level 3 data or unified cache Write-Back, cache clean"
445 }
446 {
447 "PublicDescription": "Attributable Level 3 data or unified cache access, invalidate"
448 "EventCode": "0xa8",
449 "EventName": "L3D_CACHE_INVAL",
450 "BriefDescription": "Attributable Level 3 data or unified cache access, invalidate"
451 }
452]
diff --git a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json
deleted file mode 100644
index 2db45c40ebc7..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2-imp-def.json
+++ /dev/null
@@ -1,62 +0,0 @@
1[
2 {
3 "PublicDescription": "Attributable Level 1 data cache access, read",
4 "EventCode": "0x40",
5 "EventName": "l1d_cache_rd",
6 "BriefDescription": "L1D cache read",
7 },
8 {
9 "PublicDescription": "Attributable Level 1 data cache access, write ",
10 "EventCode": "0x41",
11 "EventName": "l1d_cache_wr",
12 "BriefDescription": "L1D cache write",
13 },
14 {
15 "PublicDescription": "Attributable Level 1 data cache refill, read",
16 "EventCode": "0x42",
17 "EventName": "l1d_cache_refill_rd",
18 "BriefDescription": "L1D cache refill read",
19 },
20 {
21 "PublicDescription": "Attributable Level 1 data cache refill, write",
22 "EventCode": "0x43",
23 "EventName": "l1d_cache_refill_wr",
24 "BriefDescription": "L1D refill write",
25 },
26 {
27 "PublicDescription": "Attributable Level 1 data TLB refill, read",
28 "EventCode": "0x4C",
29 "EventName": "l1d_tlb_refill_rd",
30 "BriefDescription": "L1D tlb refill read",
31 },
32 {
33 "PublicDescription": "Attributable Level 1 data TLB refill, write",
34 "EventCode": "0x4D",
35 "EventName": "l1d_tlb_refill_wr",
36 "BriefDescription": "L1D tlb refill write",
37 },
38 {
39 "PublicDescription": "Attributable Level 1 data or unified TLB access, read",
40 "EventCode": "0x4E",
41 "EventName": "l1d_tlb_rd",
42 "BriefDescription": "L1D tlb read",
43 },
44 {
45 "PublicDescription": "Attributable Level 1 data or unified TLB access, write",
46 "EventCode": "0x4F",
47 "EventName": "l1d_tlb_wr",
48 "BriefDescription": "L1D tlb write",
49 },
50 {
51 "PublicDescription": "Bus access read",
52 "EventCode": "0x60",
53 "EventName": "bus_access_rd",
54 "BriefDescription": "Bus access read",
55 },
56 {
57 "PublicDescription": "Bus access write",
58 "EventCode": "0x61",
59 "EventName": "bus_access_wr",
60 "BriefDescription": "Bus access write",
61 }
62]
diff --git a/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/core-imp-def.json
new file mode 100644
index 000000000000..bc03c06c3918
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/cavium/thunderx2/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/cortex-a53/bus.json b/tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json
deleted file mode 100644
index 480d9f7460ab..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/bus.json
+++ /dev/null
@@ -1,22 +0,0 @@
1[
2 {,
3 "EventCode": "0x60",
4 "EventName": "BUS_ACCESS_LD",
5 "BriefDescription": "Bus access - Read"
6 },
7 {,
8 "EventCode": "0x61",
9 "EventName": "BUS_ACCESS_ST",
10 "BriefDescription": "Bus access - Write"
11 },
12 {,
13 "EventCode": "0xC0",
14 "EventName": "EXT_MEM_REQ",
15 "BriefDescription": "External memory request"
16 },
17 {,
18 "EventCode": "0xC1",
19 "EventName": "EXT_MEM_REQ_NC",
20 "BriefDescription": "Non-cacheable external memory request"
21 }
22]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json b/tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json
deleted file mode 100644
index 11baad6344b9..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/cache.json
+++ /dev/null
@@ -1,27 +0,0 @@
1[
2 {,
3 "EventCode": "0xC2",
4 "EventName": "PREFETCH_LINEFILL",
5 "BriefDescription": "Linefill because of prefetch"
6 },
7 {,
8 "EventCode": "0xC3",
9 "EventName": "PREFETCH_LINEFILL_DROP",
10 "BriefDescription": "Instruction Cache Throttle occurred"
11 },
12 {,
13 "EventCode": "0xC4",
14 "EventName": "READ_ALLOC_ENTER",
15 "BriefDescription": "Entering read allocate mode"
16 },
17 {,
18 "EventCode": "0xC5",
19 "EventName": "READ_ALLOC",
20 "BriefDescription": "Read allocate mode"
21 },
22 {,
23 "EventCode": "0xC8",
24 "EventName": "EXT_SNOOP",
25 "BriefDescription": "SCU Snooped data from another CPU for this CPU"
26 }
27]
diff --git a/tools/perf/pmu-events/arch/arm64/cortex-a53/other.json b/tools/perf/pmu-events/arch/arm64/cortex-a53/other.json
deleted file mode 100644
index 73a22402d003..000000000000
--- a/tools/perf/pmu-events/arch/arm64/cortex-a53/other.json
+++ /dev/null
@@ -1,32 +0,0 @@
1[
2 {,
3 "EventCode": "0x86",
4 "EventName": "EXC_IRQ",
5 "BriefDescription": "Exception taken, IRQ"
6 },
7 {,
8 "EventCode": "0x87",
9 "EventName": "EXC_FIQ",
10 "BriefDescription": "Exception taken, FIQ"
11 },
12 {,
13 "EventCode": "0xC6",
14 "EventName": "PRE_DECODE_ERR",
15 "BriefDescription": "Pre-decode error"
16 },
17 {,
18 "EventCode": "0xD0",
19 "EventName": "L1I_CACHE_ERR",
20 "BriefDescription": "L1 Instruction Cache (data or tag) memory error"
21 },
22 {,
23 "EventCode": "0xD1",
24 "EventName": "L1D_CACHE_ERR",
25 "BriefDescription": "L1 Data Cache (data, tag or dirty) memory error, correctable or non-correctable"
26 },
27 {,
28 "EventCode": "0xD2",
29 "EventName": "TLB_ERR",
30 "BriefDescription": "TLB memory error"
31 }
32]
diff --git a/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json
new file mode 100644
index 000000000000..9f0f15d15f75
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/hisilicon/hip08/core-imp-def.json
@@ -0,0 +1,122 @@
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_CACHE_WB_VICTIM",
16 },
17 {
18 "ArchStdEvent": "L1D_CACHE_WB_CLEAN",
19 },
20 {
21 "ArchStdEvent": "L1D_CACHE_INVAL",
22 },
23 {
24 "ArchStdEvent": "L1D_TLB_REFILL_RD",
25 },
26 {
27 "ArchStdEvent": "L1D_TLB_REFILL_WR",
28 },
29 {
30 "ArchStdEvent": "L1D_TLB_RD",
31 },
32 {
33 "ArchStdEvent": "L1D_TLB_WR",
34 },
35 {
36 "ArchStdEvent": "L2D_CACHE_RD",
37 },
38 {
39 "ArchStdEvent": "L2D_CACHE_WR",
40 },
41 {
42 "ArchStdEvent": "L2D_CACHE_REFILL_RD",
43 },
44 {
45 "ArchStdEvent": "L2D_CACHE_REFILL_WR",
46 },
47 {
48 "ArchStdEvent": "L2D_CACHE_WB_VICTIM",
49 },
50 {
51 "ArchStdEvent": "L2D_CACHE_WB_CLEAN",
52 },
53 {
54 "ArchStdEvent": "L2D_CACHE_INVAL",
55 },
56 {
57 "PublicDescription": "Level 1 instruction cache prefetch access count",
58 "EventCode": "0x102e",
59 "EventName": "L1I_CACHE_PRF",
60 "BriefDescription": "L1I cache prefetch access count",
61 },
62 {
63 "PublicDescription": "Level 1 instruction cache miss due to prefetch access count",
64 "EventCode": "0x102f",
65 "EventName": "L1I_CACHE_PRF_REFILL",
66 "BriefDescription": "L1I cache miss due to prefetch access count",
67 },
68 {
69 "PublicDescription": "Instruction queue is empty",
70 "EventCode": "0x1043",
71 "EventName": "IQ_IS_EMPTY",
72 "BriefDescription": "Instruction queue is empty",
73 },
74 {
75 "PublicDescription": "Instruction fetch stall cycles",
76 "EventCode": "0x1044",
77 "EventName": "IF_IS_STALL",
78 "BriefDescription": "Instruction fetch stall cycles",
79 },
80 {
81 "PublicDescription": "Instructions can receive, but not send",
82 "EventCode": "0x2014",
83 "EventName": "FETCH_BUBBLE",
84 "BriefDescription": "Instructions can receive, but not send",
85 },
86 {
87 "PublicDescription": "Prefetch request from LSU",
88 "EventCode": "0x6013",
89 "EventName": "PRF_REQ",
90 "BriefDescription": "Prefetch request from LSU",
91 },
92 {
93 "PublicDescription": "Hit on prefetched data",
94 "EventCode": "0x6014",
95 "EventName": "HIT_ON_PRF",
96 "BriefDescription": "Hit on prefetched data",
97 },
98 {
99 "PublicDescription": "Cycles of that the number of issuing micro operations are less than 4",
100 "EventCode": "0x7001",
101 "EventName": "EXE_STALL_CYCLE",
102 "BriefDescription": "Cycles of that the number of issue ups are less than 4",
103 },
104 {
105 "PublicDescription": "No any micro operation is issued and meanwhile any load operation is not resolved",
106 "EventCode": "0x7004",
107 "EventName": "MEM_STALL_ANYLOAD",
108 "BriefDescription": "No any micro operation is issued and meanwhile any load operation is not resolved",
109 },
110 {
111 "PublicDescription": "No any micro operation is issued and meanwhile there is any load operation missing L1 cache and pending data refill",
112 "EventCode": "0x7006",
113 "EventName": "MEM_STALL_L1MISS",
114 "BriefDescription": "No any micro operation is issued and meanwhile there is any load operation missing L1 cache and pending data refill",
115 },
116 {
117 "PublicDescription": "No any micro operation is issued and meanwhile there is any load operation missing both L1 and L2 cache and pending data refill from L3 cache",
118 "EventCode": "0x7007",
119 "EventName": "MEM_STALL_L2MISS",
120 "BriefDescription": "No any micro operation is issued and meanwhile there is any load operation missing both L1 and L2 cache and pending data refill from L3 cache",
121 },
122]
diff --git a/tools/perf/pmu-events/arch/arm64/mapfile.csv b/tools/perf/pmu-events/arch/arm64/mapfile.csv
index e61c9ca6cf9e..f03e26ecb658 100644
--- a/tools/perf/pmu-events/arch/arm64/mapfile.csv
+++ b/tools/perf/pmu-events/arch/arm64/mapfile.csv
@@ -12,5 +12,7 @@
12# 12#
13# 13#
14#Family-model,Version,Filename,EventType 14#Family-model,Version,Filename,EventType
150x00000000420f5160,v1,cavium,core 150x00000000410fd03[[:xdigit:]],v1,arm/cortex-a53,core
160x00000000410fd03[[:xdigit:]],v1,cortex-a53,core 160x00000000420f5160,v1,cavium/thunderx2,core
170x00000000430f0af0,v1,cavium/thunderx2,core
180x00000000480fd010,v1,hisilicon/hip08,core
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/cache.json b/tools/perf/pmu-events/arch/powerpc/power9/cache.json
index 7945c5196c43..851072105054 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/cache.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/cache.json
@@ -20,11 +20,6 @@
20 "BriefDescription": "Finish stall due to a scalar fixed point or CR instruction in the execution pipeline. These instructions get routed to the ALU, ALU2, and DIV pipes" 20 "BriefDescription": "Finish stall due to a scalar fixed point or CR instruction in the execution pipeline. These instructions get routed to the ALU, ALU2, and DIV pipes"
21 }, 21 },
22 {, 22 {,
23 "EventCode": "0x1D15C",
24 "EventName": "PM_MRK_DTLB_MISS_1G",
25 "BriefDescription": "Marked Data TLB reload (after a miss) page size 2M. Implies radix translation was used"
26 },
27 {,
28 "EventCode": "0x4D12A", 23 "EventCode": "0x4D12A",
29 "EventName": "PM_MRK_DATA_FROM_RL4_CYC", 24 "EventName": "PM_MRK_DATA_FROM_RL4_CYC",
30 "BriefDescription": "Duration in cycles to reload from another chip's L4 on the same Node or Group ( Remote) due to a marked load" 25 "BriefDescription": "Duration in cycles to reload from another chip's L4 on the same Node or Group ( Remote) due to a marked load"
@@ -80,21 +75,6 @@
80 "BriefDescription": "Threshold counter exceed a count of 4096" 75 "BriefDescription": "Threshold counter exceed a count of 4096"
81 }, 76 },
82 {, 77 {,
83 "EventCode": "0x3D156",
84 "EventName": "PM_MRK_DTLB_MISS_64K",
85 "BriefDescription": "Marked Data TLB Miss page size 64K"
86 },
87 {,
88 "EventCode": "0x4C15E",
89 "EventName": "PM_MRK_DTLB_MISS_16M",
90 "BriefDescription": "Marked Data TLB Miss page size 16M"
91 },
92 {,
93 "EventCode": "0x2D15E",
94 "EventName": "PM_MRK_DTLB_MISS_16G",
95 "BriefDescription": "Marked Data TLB Miss page size 16G"
96 },
97 {,
98 "EventCode": "0x3F14A", 78 "EventCode": "0x3F14A",
99 "EventName": "PM_MRK_DPTEG_FROM_RMEM", 79 "EventName": "PM_MRK_DPTEG_FROM_RMEM",
100 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 80 "BriefDescription": "A Page Table Entry was loaded into the TLB from another chip's memory on the same Node or Group ( Remote) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -123,10 +103,5 @@
123 "EventCode": "0x1002A", 103 "EventCode": "0x1002A",
124 "EventName": "PM_CMPLU_STALL_LARX", 104 "EventName": "PM_CMPLU_STALL_LARX",
125 "BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied" 105 "BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied"
126 },
127 {,
128 "EventCode": "0x1C058",
129 "EventName": "PM_DTLB_MISS_16G",
130 "BriefDescription": "Data TLB Miss page size 16G"
131 } 106 }
132] \ No newline at end of file 107] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
index bd8361b5fd6a..f9fa84b16fb5 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/frontend.json
@@ -155,11 +155,6 @@
155 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load" 155 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a marked load"
156 }, 156 },
157 {, 157 {,
158 "EventCode": "0x3C056",
159 "EventName": "PM_DTLB_MISS_64K",
160 "BriefDescription": "Data TLB Miss page size 64K"
161 },
162 {,
163 "EventCode": "0x30060", 158 "EventCode": "0x30060",
164 "EventName": "PM_TM_TRANS_RUN_INST", 159 "EventName": "PM_TM_TRANS_RUN_INST",
165 "BriefDescription": "Run instructions completed in transactional state (gated by the run latch)" 160 "BriefDescription": "Run instructions completed in transactional state (gated by the run latch)"
@@ -345,11 +340,6 @@
345 "BriefDescription": "Larx finished" 340 "BriefDescription": "Larx finished"
346 }, 341 },
347 {, 342 {,
348 "EventCode": "0x4C056",
349 "EventName": "PM_DTLB_MISS_16M",
350 "BriefDescription": "Data TLB Miss page size 16M"
351 },
352 {,
353 "EventCode": "0x1003A", 343 "EventCode": "0x1003A",
354 "EventName": "PM_CMPLU_STALL_LSU_FIN", 344 "EventName": "PM_CMPLU_STALL_LSU_FIN",
355 "BriefDescription": "Finish stall because the NTF instruction was an LSU op (other than a load or a store) with all its dependencies met and just going through the LSU pipe to finish" 345 "BriefDescription": "Finish stall because the NTF instruction was an LSU op (other than a load or a store) with all its dependencies met and just going through the LSU pipe to finish"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/marked.json b/tools/perf/pmu-events/arch/powerpc/power9/marked.json
index 22f9f32060a8..b1954c38bab1 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/marked.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/marked.json
@@ -530,11 +530,6 @@
530 "BriefDescription": "Counts all Icache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch" 530 "BriefDescription": "Counts all Icache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch"
531 }, 531 },
532 {, 532 {,
533 "EventCode": "0x4003C",
534 "EventName": "PM_DISP_HELD_SYNC_HOLD",
535 "BriefDescription": "Cycles in which dispatch is held because of a synchronizing instruction in the pipeline"
536 },
537 {,
538 "EventCode": "0x3003C", 533 "EventCode": "0x3003C",
539 "EventName": "PM_CMPLU_STALL_NESTED_TEND", 534 "EventName": "PM_CMPLU_STALL_NESTED_TEND",
540 "BriefDescription": "Completion stall because the ISU is updating the TEXASR to keep track of the nested tend and decrement the TEXASR nested level. This is a short delay" 535 "BriefDescription": "Completion stall because the ISU is updating the TEXASR to keep track of the nested tend and decrement the TEXASR nested level. This is a short delay"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/memory.json b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
index 9960d1c0dd44..2e2ebc700c74 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/memory.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/memory.json
@@ -45,11 +45,6 @@
45 "BriefDescription": "count of Loads completed" 45 "BriefDescription": "count of Loads completed"
46 }, 46 },
47 {, 47 {,
48 "EventCode": "0x2D156",
49 "EventName": "PM_MRK_DTLB_MISS_4K",
50 "BriefDescription": "Marked Data TLB Miss page size 4k"
51 },
52 {,
53 "EventCode": "0x4C042", 48 "EventCode": "0x4C042",
54 "EventName": "PM_DATA_FROM_L3", 49 "EventName": "PM_DATA_FROM_L3",
55 "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a demand load" 50 "BriefDescription": "The processor's data cache was reloaded from local core's L3 due to a demand load"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/other.json b/tools/perf/pmu-events/arch/powerpc/power9/other.json
index 5ce312973f1e..48cf4f920b3f 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/other.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/other.json
@@ -70,6 +70,11 @@
70 "BriefDescription": "Cycles thread running at priority level 0 or 1" 70 "BriefDescription": "Cycles thread running at priority level 0 or 1"
71 }, 71 },
72 {, 72 {,
73 "EventCode": "0x4C054",
74 "EventName": "PM_DERAT_MISS_16G_1G",
75 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16G (hpt mode) or 1G (radix mode)"
76 },
77 {,
73 "EventCode": "0x2084", 78 "EventCode": "0x2084",
74 "EventName": "PM_FLUSH_HB_RESTORE_CYC", 79 "EventName": "PM_FLUSH_HB_RESTORE_CYC",
75 "BriefDescription": "Cycles in which no new instructions can be dispatched to the ICT after a flush. History buffer recovery" 80 "BriefDescription": "Cycles in which no new instructions can be dispatched to the ICT after a flush. History buffer recovery"
@@ -107,12 +112,12 @@
107 {, 112 {,
108 "EventCode": "0x360B2", 113 "EventCode": "0x360B2",
109 "EventName": "PM_L3_GRP_GUESS_WRONG_LOW", 114 "EventName": "PM_L3_GRP_GUESS_WRONG_LOW",
110 "BriefDescription": "Initial scope=group (GS or NNS) but data from outside group (far or rem). Prediction too Low" 115 "BriefDescription": "Prefetch scope predictor selected GS or NNS, but was wrong because scope was LNS"
111 }, 116 },
112 {, 117 {,
113 "EventCode": "0x168A6", 118 "EventCode": "0x168A6",
114 "EventName": "PM_TM_CAM_OVERFLOW", 119 "EventName": "PM_TM_CAM_OVERFLOW",
115 "BriefDescription": "L3 TM cam overflow during L2 co of SC" 120 "BriefDescription": "L3 TM CAM is full when a L2 castout of TM_SC line occurs. Line is pushed to memory"
116 }, 121 },
117 {, 122 {,
118 "EventCode": "0xE8B0", 123 "EventCode": "0xE8B0",
@@ -150,11 +155,6 @@
150 "BriefDescription": "All ISU rejects" 155 "BriefDescription": "All ISU rejects"
151 }, 156 },
152 {, 157 {,
153 "EventCode": "0x460A6",
154 "EventName": "PM_RD_FORMING_SC",
155 "BriefDescription": "Read forming SC"
156 },
157 {,
158 "EventCode": "0x468A0", 158 "EventCode": "0x468A0",
159 "EventName": "PM_L3_PF_OFF_CHIP_MEM", 159 "EventName": "PM_L3_PF_OFF_CHIP_MEM",
160 "BriefDescription": "L3 PF from Off chip memory" 160 "BriefDescription": "L3 PF from Off chip memory"
@@ -187,7 +187,7 @@
187 {, 187 {,
188 "EventCode": "0x368A6", 188 "EventCode": "0x368A6",
189 "EventName": "PM_SNP_TM_HIT_T", 189 "EventName": "PM_SNP_TM_HIT_T",
190 "BriefDescription": "Snp TM sthit T/Tn/Te" 190 "BriefDescription": "TM snoop that is a store hits line in L3 in T, Tn or Te state (shared modified)"
191 }, 191 },
192 {, 192 {,
193 "EventCode": "0x3001A", 193 "EventCode": "0x3001A",
@@ -205,6 +205,11 @@
205 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's ECO L3 on the same chip due to a marked load" 205 "BriefDescription": "Duration in cycles to reload with Modified (M) data from another core's ECO L3 on the same chip due to a marked load"
206 }, 206 },
207 {, 207 {,
208 "EventCode": "0xF0B4",
209 "EventName": "PM_DC_PREF_CONS_ALLOC",
210 "BriefDescription": "Prefetch stream allocated in the conservative phase by either the hardware prefetch mechanism or software prefetch. The sum of this pair subtracted from the total number of allocs will give the total allocs in normal phase"
211 },
212 {,
208 "EventCode": "0xF894", 213 "EventCode": "0xF894",
209 "EventName": "PM_LSU3_L1_CAM_CANCEL", 214 "EventName": "PM_LSU3_L1_CAM_CANCEL",
210 "BriefDescription": "ls3 l1 tm cam cancel" 215 "BriefDescription": "ls3 l1 tm cam cancel"
@@ -227,7 +232,12 @@
227 {, 232 {,
228 "EventCode": "0x468A6", 233 "EventCode": "0x468A6",
229 "EventName": "PM_RD_CLEARING_SC", 234 "EventName": "PM_RD_CLEARING_SC",
230 "BriefDescription": "Read clearing SC" 235 "BriefDescription": "Core TM load hits line in L3 in TM_SC state and causes it to be invalidated"
236 },
237 {,
238 "EventCode": "0xD0B0",
239 "EventName": "PM_HWSYNC",
240 "BriefDescription": ""
231 }, 241 },
232 {, 242 {,
233 "EventCode": "0x168B0", 243 "EventCode": "0x168B0",
@@ -265,6 +275,11 @@
265 "BriefDescription": "Prefetch stream allocated by the hardware prefetch mechanism" 275 "BriefDescription": "Prefetch stream allocated by the hardware prefetch mechanism"
266 }, 276 },
267 {, 277 {,
278 "EventCode": "0xF0BC",
279 "EventName": "PM_LS2_UNALIGNED_ST",
280 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
281 },
282 {,
268 "EventCode": "0xD0AC", 283 "EventCode": "0xD0AC",
269 "EventName": "PM_SRQ_SYNC_CYC", 284 "EventName": "PM_SRQ_SYNC_CYC",
270 "BriefDescription": "A sync is in the S2Q (edge detect to count)" 285 "BriefDescription": "A sync is in the S2Q (edge detect to count)"
@@ -275,6 +290,11 @@
275 "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet" 290 "BriefDescription": "Marked instruction was reloaded from a location beyond the local chiplet"
276 }, 291 },
277 {, 292 {,
293 "EventCode": "0x58A8",
294 "EventName": "PM_DECODE_HOLD_ICT_FULL",
295 "BriefDescription": "Counts the number of cycles in which the IFU was not able to decode and transmit one or more instructions because all itags were in use. This means the ICT is full for this thread"
296 },
297 {,
278 "EventCode": "0x26082", 298 "EventCode": "0x26082",
279 "EventName": "PM_L2_IC_INV", 299 "EventName": "PM_L2_IC_INV",
280 "BriefDescription": "I-cache Invalidates sent over the realod bus to the core" 300 "BriefDescription": "I-cache Invalidates sent over the realod bus to the core"
@@ -365,6 +385,16 @@
365 "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load" 385 "BriefDescription": "Duration in cycles to reload either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked load"
366 }, 386 },
367 {, 387 {,
388 "EventCode": "0xF888",
389 "EventName": "PM_LSU1_STORE_REJECT",
390 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met"
391 },
392 {,
393 "EventCode": "0xC098",
394 "EventName": "PM_LS2_UNALIGNED_LD",
395 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
396 },
397 {,
368 "EventCode": "0x20058", 398 "EventCode": "0x20058",
369 "EventName": "PM_DARQ1_10_12_ENTRIES", 399 "EventName": "PM_DARQ1_10_12_ENTRIES",
370 "BriefDescription": "Cycles in which 10 or more DARQ1 entries (out of 12) are in use" 400 "BriefDescription": "Cycles in which 10 or more DARQ1 entries (out of 12) are in use"
@@ -372,7 +402,7 @@
372 {, 402 {,
373 "EventCode": "0x360A6", 403 "EventCode": "0x360A6",
374 "EventName": "PM_SNP_TM_HIT_M", 404 "EventName": "PM_SNP_TM_HIT_M",
375 "BriefDescription": "Snp TM st hit M/Mu" 405 "BriefDescription": "TM snoop that is a store hits line in L3 in M or Mu state (exclusive modified)"
376 }, 406 },
377 {, 407 {,
378 "EventCode": "0x5898", 408 "EventCode": "0x5898",
@@ -395,9 +425,9 @@
395 "BriefDescription": "A data line was written to the L1 due to a hardware or software prefetch" 425 "BriefDescription": "A data line was written to the L1 due to a hardware or software prefetch"
396 }, 426 },
397 {, 427 {,
398 "EventCode": "0xF888", 428 "EventCode": "0x2608E",
399 "EventName": "PM_LSU1_STORE_REJECT", 429 "EventName": "PM_TM_LD_CONF",
400 "BriefDescription": "All internal store rejects cause the instruction to go back to the SRQ and go to sleep until woken up to try again after the condition has been met" 430 "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)"
401 }, 431 },
402 {, 432 {,
403 "EventCode": "0x1D144", 433 "EventCode": "0x1D144",
@@ -422,7 +452,7 @@
422 {, 452 {,
423 "EventCode": "0x26884", 453 "EventCode": "0x26884",
424 "EventName": "PM_DSIDE_MRU_TOUCH", 454 "EventName": "PM_DSIDE_MRU_TOUCH",
425 "BriefDescription": "D-side L2 MRU touch sent to L2" 455 "BriefDescription": "D-side L2 MRU touch commands sent to the L2"
426 }, 456 },
427 {, 457 {,
428 "EventCode": "0x30134", 458 "EventCode": "0x30134",
@@ -440,6 +470,16 @@
440 "BriefDescription": "XL-form branch was mispredicted due to the predicted target address missing from EAT. The EAT forces a mispredict in this case since there is no predicated target to validate. This is a rare case that may occur when the EAT is full and a branch is issued" 470 "BriefDescription": "XL-form branch was mispredicted due to the predicted target address missing from EAT. The EAT forces a mispredict in this case since there is no predicated target to validate. This is a rare case that may occur when the EAT is full and a branch is issued"
441 }, 471 },
442 {, 472 {,
473 "EventCode": "0xC094",
474 "EventName": "PM_LS0_UNALIGNED_LD",
475 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
476 },
477 {,
478 "EventCode": "0xF8BC",
479 "EventName": "PM_LS3_UNALIGNED_ST",
480 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
481 },
482 {,
443 "EventCode": "0x460AE", 483 "EventCode": "0x460AE",
444 "EventName": "PM_L3_P2_CO_RTY", 484 "EventName": "PM_L3_P2_CO_RTY",
445 "BriefDescription": "L3 CO received retry port 2 (memory only), every retry counted" 485 "BriefDescription": "L3 CO received retry port 2 (memory only), every retry counted"
@@ -492,7 +532,7 @@
492 {, 532 {,
493 "EventCode": "0xC880", 533 "EventCode": "0xC880",
494 "EventName": "PM_LS1_LD_VECTOR_FIN", 534 "EventName": "PM_LS1_LD_VECTOR_FIN",
495 "BriefDescription": "" 535 "BriefDescription": "LS1 finished load vector op"
496 }, 536 },
497 {, 537 {,
498 "EventCode": "0x2894", 538 "EventCode": "0x2894",
@@ -515,6 +555,11 @@
515 "BriefDescription": "Marked derat reload (miss) for any page size" 555 "BriefDescription": "Marked derat reload (miss) for any page size"
516 }, 556 },
517 {, 557 {,
558 "EventCode": "0x160A0",
559 "EventName": "PM_L3_PF_MISS_L3",
560 "BriefDescription": "L3 PF missed in L3"
561 },
562 {,
518 "EventCode": "0x1C04A", 563 "EventCode": "0x1C04A",
519 "EventName": "PM_DATA_FROM_RL2L3_SHR", 564 "EventName": "PM_DATA_FROM_RL2L3_SHR",
520 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load" 565 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load"
@@ -565,11 +610,21 @@
565 "BriefDescription": "L2 guess local (LNS) and guess was not correct (ie data not on chip)" 610 "BriefDescription": "L2 guess local (LNS) and guess was not correct (ie data not on chip)"
566 }, 611 },
567 {, 612 {,
613 "EventCode": "0xC888",
614 "EventName": "PM_LSU_DTLB_MISS_64K",
615 "BriefDescription": "Data TLB Miss page size 64K"
616 },
617 {,
568 "EventCode": "0xE0A4", 618 "EventCode": "0xE0A4",
569 "EventName": "PM_TMA_REQ_L2", 619 "EventName": "PM_TMA_REQ_L2",
570 "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding" 620 "BriefDescription": "addrs only req to L2 only on the first one,Indication that Load footprint is not expanding"
571 }, 621 },
572 {, 622 {,
623 "EventCode": "0xC088",
624 "EventName": "PM_LSU_DTLB_MISS_4K",
625 "BriefDescription": "Data TLB Miss page size 4K"
626 },
627 {,
573 "EventCode": "0x3C042", 628 "EventCode": "0x3C042",
574 "EventName": "PM_DATA_FROM_L3_DISP_CONFLICT", 629 "EventName": "PM_DATA_FROM_L3_DISP_CONFLICT",
575 "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a demand load" 630 "BriefDescription": "The processor's data cache was reloaded from local core's L3 with dispatch conflict due to a demand load"
@@ -602,7 +657,7 @@
602 {, 657 {,
603 "EventCode": "0x26084", 658 "EventCode": "0x26084",
604 "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER", 659 "EventName": "PM_L2_RCLD_DISP_FAIL_OTHER",
605 "BriefDescription": "All I-or-D side load dispatch attempts for this thread that failed due to reason other than address collision (excludes i_l2mru_tch_reqs)" 660 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread that failed due to reasons other than an address collision conflicts with an L2 machines (e.g. Read-Claim/Snoop machine not available)"
606 }, 661 },
607 {, 662 {,
608 "EventCode": "0x101E4", 663 "EventCode": "0x101E4",
@@ -647,12 +702,12 @@
647 {, 702 {,
648 "EventCode": "0x46080", 703 "EventCode": "0x46080",
649 "EventName": "PM_L2_DISP_ALL_L2MISS", 704 "EventName": "PM_L2_DISP_ALL_L2MISS",
650 "BriefDescription": "All successful Ld/St dispatches for this thread that were an L2 miss (excludes i_l2mru_tch_reqs)" 705 "BriefDescription": "All successful D-side-Ld/St or I-side-instruction-fetch dispatches for this thread that were an L2 miss"
651 }, 706 },
652 {, 707 {,
653 "EventCode": "0x160A0", 708 "EventCode": "0xF8B8",
654 "EventName": "PM_L3_PF_MISS_L3", 709 "EventName": "PM_LS1_UNALIGNED_ST",
655 "BriefDescription": "L3 PF missed in L3" 710 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
656 }, 711 },
657 {, 712 {,
658 "EventCode": "0x408C", 713 "EventCode": "0x408C",
@@ -667,7 +722,7 @@
667 {, 722 {,
668 "EventCode": "0x160B2", 723 "EventCode": "0x160B2",
669 "EventName": "PM_L3_LOC_GUESS_CORRECT", 724 "EventName": "PM_L3_LOC_GUESS_CORRECT",
670 "BriefDescription": "initial scope=node/chip (LNS) and data from local node (local) (pred successful) - always PFs only" 725 "BriefDescription": "Prefetch scope predictor selected LNS and was correct"
671 }, 726 },
672 {, 727 {,
673 "EventCode": "0x48B4", 728 "EventCode": "0x48B4",
@@ -767,7 +822,7 @@
767 {, 822 {,
768 "EventCode": "0x36082", 823 "EventCode": "0x36082",
769 "EventName": "PM_L2_LD_DISP", 824 "EventName": "PM_L2_LD_DISP",
770 "BriefDescription": "All successful I-or-D side load dispatches for this thread (excludes i_l2mru_tch_reqs)" 825 "BriefDescription": "All successful D-side-Ld or I-side-instruction-fetch dispatches for this thread"
771 }, 826 },
772 {, 827 {,
773 "EventCode": "0xF8B0", 828 "EventCode": "0xF8B0",
@@ -787,7 +842,7 @@
787 {, 842 {,
788 "EventCode": "0x16884", 843 "EventCode": "0x16884",
789 "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR", 844 "EventName": "PM_L2_RCLD_DISP_FAIL_ADDR",
790 "BriefDescription": "All I-od-D side load dispatch attempts for this thread that failed due to address collision with RC/CO/SN/SQ machine (excludes i_l2mru_tch_reqs)" 845 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread that failed due to an address collision conflicts with an L2 machines already working on this line (e.g. ld-hit-stq or Read-claim/Castout/Snoop machines)"
791 }, 846 },
792 {, 847 {,
793 "EventCode": "0x460A0", 848 "EventCode": "0x460A0",
@@ -830,6 +885,11 @@
830 "BriefDescription": "Instruction prefetch requests" 885 "BriefDescription": "Instruction prefetch requests"
831 }, 886 },
832 {, 887 {,
888 "EventCode": "0xC898",
889 "EventName": "PM_LS3_UNALIGNED_LD",
890 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
891 },
892 {,
833 "EventCode": "0x488C", 893 "EventCode": "0x488C",
834 "EventName": "PM_IC_PREF_WRITE", 894 "EventName": "PM_IC_PREF_WRITE",
835 "BriefDescription": "Instruction prefetch written into IL1" 895 "BriefDescription": "Instruction prefetch written into IL1"
@@ -837,7 +897,7 @@
837 {, 897 {,
838 "EventCode": "0xF89C", 898 "EventCode": "0xF89C",
839 "EventName": "PM_XLATE_MISS", 899 "EventName": "PM_XLATE_MISS",
840 "BriefDescription": "The LSU requested a line from L2 for translation. It may be satisfied from any source beyond L2. Includes speculative instructions" 900 "BriefDescription": "The LSU requested a line from L2 for translation. It may be satisfied from any source beyond L2. Includes speculative instructions. Includes instruction, prefetch and demand"
841 }, 901 },
842 {, 902 {,
843 "EventCode": "0x14158", 903 "EventCode": "0x14158",
@@ -850,9 +910,14 @@
850 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L3 on the same chip due to a marked load" 910 "BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L3 on the same chip due to a marked load"
851 }, 911 },
852 {, 912 {,
913 "EventCode": "0xC88C",
914 "EventName": "PM_LSU_DTLB_MISS_16G_1G",
915 "BriefDescription": "Data TLB Miss page size 16G (HPT) or 1G (Radix)"
916 },
917 {,
853 "EventCode": "0x268A6", 918 "EventCode": "0x268A6",
854 "EventName": "PM_TM_RST_SC", 919 "EventName": "PM_TM_RST_SC",
855 "BriefDescription": "TM-snp rst RM SC" 920 "BriefDescription": "TM snoop hits line in L3 that is TM_SC state and causes it to be invalidated"
856 }, 921 },
857 {, 922 {,
858 "EventCode": "0x468A4", 923 "EventCode": "0x468A4",
@@ -917,7 +982,7 @@
917 {, 982 {,
918 "EventCode": "0x46086", 983 "EventCode": "0x46086",
919 "EventName": "PM_L2_SN_M_RD_DONE", 984 "EventName": "PM_L2_SN_M_RD_DONE",
920 "BriefDescription": "SNP dispatched for a read and was M (true M)" 985 "BriefDescription": "Snoop dispatched for a read and was M (true M)"
921 }, 986 },
922 {, 987 {,
923 "EventCode": "0x40154", 988 "EventCode": "0x40154",
@@ -980,14 +1045,9 @@
980 "BriefDescription": "Link stack predicts right address" 1045 "BriefDescription": "Link stack predicts right address"
981 }, 1046 },
982 {, 1047 {,
983 "EventCode": "0x4C05A",
984 "EventName": "PM_DTLB_MISS_1G",
985 "BriefDescription": "Data TLB reload (after a miss) page size 1G. Implies radix translation was used"
986 },
987 {,
988 "EventCode": "0x36886", 1048 "EventCode": "0x36886",
989 "EventName": "PM_L2_SN_SX_I_DONE", 1049 "EventName": "PM_L2_SN_SX_I_DONE",
990 "BriefDescription": "SNP dispatched and went from Sx to Ix" 1050 "BriefDescription": "Snoop dispatched and went from Sx to Ix"
991 }, 1051 },
992 {, 1052 {,
993 "EventCode": "0x4E04A", 1053 "EventCode": "0x4E04A",
@@ -1000,11 +1060,6 @@
1000 "BriefDescription": "Duration in cycles to reload from another chip's L4 on a different Node or Group (Distant) due to a marked load" 1060 "BriefDescription": "Duration in cycles to reload from another chip's L4 on a different Node or Group (Distant) due to a marked load"
1001 }, 1061 },
1002 {, 1062 {,
1003 "EventCode": "0x2608E",
1004 "EventName": "PM_TM_LD_CONF",
1005 "BriefDescription": "TM Load (fav or non-fav) ran into conflict (failed)"
1006 },
1007 {,
1008 "EventCode": "0x4080", 1063 "EventCode": "0x4080",
1009 "EventName": "PM_INST_FROM_L1", 1064 "EventName": "PM_INST_FROM_L1",
1010 "BriefDescription": "Instruction fetches from L1. L1 instruction hit" 1065 "BriefDescription": "Instruction fetches from L1. L1 instruction hit"
@@ -1037,7 +1092,7 @@
1037 {, 1092 {,
1038 "EventCode": "0x260A6", 1093 "EventCode": "0x260A6",
1039 "EventName": "PM_NON_TM_RST_SC", 1094 "EventName": "PM_NON_TM_RST_SC",
1040 "BriefDescription": "Non-TM snp rst TM SC" 1095 "BriefDescription": "Non-TM snoop hits line in L3 that is TM_SC state and causes it to be invalidated"
1041 }, 1096 },
1042 {, 1097 {,
1043 "EventCode": "0x3608A", 1098 "EventCode": "0x3608A",
@@ -1065,11 +1120,6 @@
1065 "BriefDescription": "Branch mispredict flushes. Includes target and address misprecition" 1120 "BriefDescription": "Branch mispredict flushes. Includes target and address misprecition"
1066 }, 1121 },
1067 {, 1122 {,
1068 "EventCode": "0x508C",
1069 "EventName": "PM_SHL_CREATED",
1070 "BriefDescription": "Store-Hit-Load Table Entry Created"
1071 },
1072 {,
1073 "EventCode": "0x1504C", 1123 "EventCode": "0x1504C",
1074 "EventName": "PM_IPTEG_FROM_LL4", 1124 "EventName": "PM_IPTEG_FROM_LL4",
1075 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a instruction side request" 1125 "BriefDescription": "A Page Table Entry was loaded into the TLB from the local chip's L4 cache due to a instruction side request"
@@ -1107,7 +1157,7 @@
1107 {, 1157 {,
1108 "EventCode": "0x2608A", 1158 "EventCode": "0x2608A",
1109 "EventName": "PM_ISIDE_DISP_FAIL_ADDR", 1159 "EventName": "PM_ISIDE_DISP_FAIL_ADDR",
1110 "BriefDescription": "All I-side dispatch attempts for this thread that failed due to a addr collision with another machine (excludes i_l2mru_tch_reqs)" 1160 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread that failed due to an address collision conflict with an L2 machine already working on this line (e.g. ld-hit-stq or RC/CO/SN machines)"
1111 }, 1161 },
1112 {, 1162 {,
1113 "EventCode": "0x50B4", 1163 "EventCode": "0x50B4",
@@ -1180,9 +1230,9 @@
1180 "BriefDescription": "Number of stcx instructions finished. This includes instructions in the speculative path of a branch that may be flushed" 1230 "BriefDescription": "Number of stcx instructions finished. This includes instructions in the speculative path of a branch that may be flushed"
1181 }, 1231 },
1182 {, 1232 {,
1183 "EventCode": "0xE0B8", 1233 "EventCode": "0xD8AC",
1184 "EventName": "PM_LS2_TM_DISALLOW", 1234 "EventName": "PM_LWSYNC",
1185 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it" 1235 "BriefDescription": ""
1186 }, 1236 },
1187 {, 1237 {,
1188 "EventCode": "0x2094", 1238 "EventCode": "0x2094",
@@ -1210,6 +1260,11 @@
1210 "BriefDescription": "Ict empty for this thread due to dispatch holds because the History Buffer was full. Could be GPR/VSR/VMR/FPR/CR/XVF; CR; XVF (XER/VSCR/FPSCR)" 1260 "BriefDescription": "Ict empty for this thread due to dispatch holds because the History Buffer was full. Could be GPR/VSR/VMR/FPR/CR/XVF; CR; XVF (XER/VSCR/FPSCR)"
1211 }, 1261 },
1212 {, 1262 {,
1263 "EventCode": "0xC894",
1264 "EventName": "PM_LS1_UNALIGNED_LD",
1265 "BriefDescription": "Load instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the load of that size. If the load wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
1266 },
1267 {,
1213 "EventCode": "0x360A2", 1268 "EventCode": "0x360A2",
1214 "EventName": "PM_L3_L2_CO_HIT", 1269 "EventName": "PM_L3_L2_CO_HIT",
1215 "BriefDescription": "L2 CO hits" 1270 "BriefDescription": "L2 CO hits"
@@ -1292,7 +1347,7 @@
1292 {, 1347 {,
1293 "EventCode": "0xC084", 1348 "EventCode": "0xC084",
1294 "EventName": "PM_LS2_LD_VECTOR_FIN", 1349 "EventName": "PM_LS2_LD_VECTOR_FIN",
1295 "BriefDescription": "" 1350 "BriefDescription": "LS2 finished load vector op"
1296 }, 1351 },
1297 {, 1352 {,
1298 "EventCode": "0x1608E", 1353 "EventCode": "0x1608E",
@@ -1345,6 +1400,11 @@
1345 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running" 1400 "BriefDescription": "Continuous 16 cycle (2to1) window where this signals rotates thru sampling each SN machine busy. PMU uses this wave to then do 16 cyc count to sample total number of machs running"
1346 }, 1401 },
1347 {, 1402 {,
1403 "EventCode": "0x36084",
1404 "EventName": "PM_L2_RCST_DISP",
1405 "BriefDescription": "All D-side store dispatch attempts for this thread"
1406 },
1407 {,
1348 "EventCode": "0x46084", 1408 "EventCode": "0x46084",
1349 "EventName": "PM_L2_RCST_DISP_FAIL_OTHER", 1409 "EventName": "PM_L2_RCST_DISP_FAIL_OTHER",
1350 "BriefDescription": "All D-side store dispatch attempts for this thread that failed due to reason other than address collision" 1410 "BriefDescription": "All D-side store dispatch attempts for this thread that failed due to reason other than address collision"
@@ -1355,11 +1415,6 @@
1355 "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software." 1415 "BriefDescription": "A demand load referenced a line in an active strided prefetch stream. The stream could have been allocated through the hardware prefetch mechanism or through software."
1356 }, 1416 },
1357 {, 1417 {,
1358 "EventCode": "0x36084",
1359 "EventName": "PM_L2_RCST_DISP",
1360 "BriefDescription": "All D-side store dispatch attempts for this thread"
1361 },
1362 {,
1363 "EventCode": "0x45054", 1418 "EventCode": "0x45054",
1364 "EventName": "PM_FMA_CMPL", 1419 "EventName": "PM_FMA_CMPL",
1365 "BriefDescription": "two flops operation completed (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only. " 1420 "BriefDescription": "two flops operation completed (fmadd, fnmadd, fmsub, fnmsub) Scalar instructions only. "
@@ -1372,7 +1427,7 @@
1372 {, 1427 {,
1373 "EventCode": "0x36080", 1428 "EventCode": "0x36080",
1374 "EventName": "PM_L2_INST", 1429 "EventName": "PM_L2_INST",
1375 "BriefDescription": "All successful I-side dispatches for this thread (excludes i_l2mru_tch reqs)" 1430 "BriefDescription": "All successful I-side-instruction-fetch (e.g. i-demand, i-prefetch) dispatches for this thread"
1376 }, 1431 },
1377 {, 1432 {,
1378 "EventCode": "0x3504C", 1433 "EventCode": "0x3504C",
@@ -1387,7 +1442,7 @@
1387 {, 1442 {,
1388 "EventCode": "0x1688A", 1443 "EventCode": "0x1688A",
1389 "EventName": "PM_ISIDE_DISP", 1444 "EventName": "PM_ISIDE_DISP",
1390 "BriefDescription": "All I-side dispatch attempts for this thread (excludes i_l2mru_tch_reqs)" 1445 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread"
1391 }, 1446 },
1392 {, 1447 {,
1393 "EventCode": "0x468AA", 1448 "EventCode": "0x468AA",
@@ -1420,6 +1475,11 @@
1420 "BriefDescription": "Load tm hit in L1" 1475 "BriefDescription": "Load tm hit in L1"
1421 }, 1476 },
1422 {, 1477 {,
1478 "EventCode": "0xE0B8",
1479 "EventName": "PM_LS2_TM_DISALLOW",
1480 "BriefDescription": "A TM-ineligible instruction tries to execute inside a transaction and the LSU disallows it"
1481 },
1482 {,
1423 "EventCode": "0x44044", 1483 "EventCode": "0x44044",
1424 "EventName": "PM_INST_FROM_L31_ECO_MOD", 1484 "EventName": "PM_INST_FROM_L31_ECO_MOD",
1425 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)" 1485 "BriefDescription": "The processor's Instruction cache was reloaded with Modified (M) data from another core's ECO L3 on the same chip due to an instruction fetch (not prefetch)"
@@ -1467,7 +1527,7 @@
1467 {, 1527 {,
1468 "EventCode": "0x36086", 1528 "EventCode": "0x36086",
1469 "EventName": "PM_L2_RC_ST_DONE", 1529 "EventName": "PM_L2_RC_ST_DONE",
1470 "BriefDescription": "RC did store to line that was Tx or Sx" 1530 "BriefDescription": "Read-claim machine did store to line that was in Tx or Sx (Tagged or Shared state)"
1471 }, 1531 },
1472 {, 1532 {,
1473 "EventCode": "0xE8AC", 1533 "EventCode": "0xE8AC",
@@ -1500,6 +1560,11 @@
1500 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a instruction side request" 1560 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a instruction side request"
1501 }, 1561 },
1502 {, 1562 {,
1563 "EventCode": "0x460A6",
1564 "EventName": "PM_RD_FORMING_SC",
1565 "BriefDescription": "Doesn't occur"
1566 },
1567 {,
1503 "EventCode": "0x35042", 1568 "EventCode": "0x35042",
1504 "EventName": "PM_IPTEG_FROM_L3_DISP_CONFLICT", 1569 "EventName": "PM_IPTEG_FROM_L3_DISP_CONFLICT",
1505 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a instruction side request" 1570 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 with dispatch conflict due to a instruction side request"
@@ -1527,7 +1592,7 @@
1527 {, 1592 {,
1528 "EventCode": "0x36882", 1593 "EventCode": "0x36882",
1529 "EventName": "PM_L2_LD_HIT", 1594 "EventName": "PM_L2_LD_HIT",
1530 "BriefDescription": "All successful I-or-D side load dispatches for this thread that were L2 hits (excludes i_l2mru_tch_reqs)" 1595 "BriefDescription": "All successful D-side-Ld or I-side-instruction-fetch dispatches for this thread that were L2 hits"
1531 }, 1596 },
1532 {, 1597 {,
1533 "EventCode": "0x168AC", 1598 "EventCode": "0x168AC",
@@ -1555,11 +1620,6 @@
1555 "BriefDescription": "ProbeNops dispatched" 1620 "BriefDescription": "ProbeNops dispatched"
1556 }, 1621 },
1557 {, 1622 {,
1558 "EventCode": "0x58A8",
1559 "EventName": "PM_DECODE_HOLD_ICT_FULL",
1560 "BriefDescription": "Counts the number of cycles in which the IFU was not able to decode and transmit one or more instructions because all itags were in use. This means the ICT is full for this thread"
1561 },
1562 {,
1563 "EventCode": "0x10052", 1623 "EventCode": "0x10052",
1564 "EventName": "PM_GRP_PUMP_MPRED_RTY", 1624 "EventName": "PM_GRP_PUMP_MPRED_RTY",
1565 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)" 1625 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for all data types excluding data prefetch (demand load,inst prefetch,inst fetch,xlate)"
@@ -1572,7 +1632,7 @@
1572 {, 1632 {,
1573 "EventCode": "0x2688A", 1633 "EventCode": "0x2688A",
1574 "EventName": "PM_ISIDE_DISP_FAIL_OTHER", 1634 "EventName": "PM_ISIDE_DISP_FAIL_OTHER",
1575 "BriefDescription": "All I-side dispatch attempts for this thread that failed due to a reason other than addrs collision (excludes i_l2mru_tch_reqs)" 1635 "BriefDescription": "All I-side-instruction-fetch dispatch attempts for this thread that failed due to reasons other than an address collision conflict with an L2 machine (e.g. no available RC/CO machines)"
1576 }, 1636 },
1577 {, 1637 {,
1578 "EventCode": "0x2001A", 1638 "EventCode": "0x2001A",
@@ -1652,12 +1712,12 @@
1652 {, 1712 {,
1653 "EventCode": "0x46880", 1713 "EventCode": "0x46880",
1654 "EventName": "PM_ISIDE_MRU_TOUCH", 1714 "EventName": "PM_ISIDE_MRU_TOUCH",
1655 "BriefDescription": "I-side L2 MRU touch sent to L2 for this thread" 1715 "BriefDescription": "I-side L2 MRU touch sent to L2 for this thread I-side L2 MRU touch commands sent to the L2 for this thread"
1656 }, 1716 },
1657 {, 1717 {,
1658 "EventCode": "0x1C05C", 1718 "EventCode": "0x508C",
1659 "EventName": "PM_DTLB_MISS_2M", 1719 "EventName": "PM_SHL_CREATED",
1660 "BriefDescription": "Data TLB reload (after a miss) page size 2M. Implies radix translation was used" 1720 "BriefDescription": "Store-Hit-Load Table Entry Created"
1661 }, 1721 },
1662 {, 1722 {,
1663 "EventCode": "0x50B8", 1723 "EventCode": "0x50B8",
@@ -1672,7 +1732,7 @@
1672 {, 1732 {,
1673 "EventCode": "0x268B2", 1733 "EventCode": "0x268B2",
1674 "EventName": "PM_L3_LOC_GUESS_WRONG", 1734 "EventName": "PM_L3_LOC_GUESS_WRONG",
1675 "BriefDescription": "Initial scope=node (LNS) but data from out side local node (near or far or rem). Prediction too Low" 1735 "BriefDescription": "Prefetch scope predictor selected LNS, but was wrong"
1676 }, 1736 },
1677 {, 1737 {,
1678 "EventCode": "0x36088", 1738 "EventCode": "0x36088",
@@ -1685,6 +1745,11 @@
1685 "BriefDescription": "L3 PF received retry port 2, every retry counted" 1745 "BriefDescription": "L3 PF received retry port 2, every retry counted"
1686 }, 1746 },
1687 {, 1747 {,
1748 "EventCode": "0xD8B0",
1749 "EventName": "PM_PTESYNC",
1750 "BriefDescription": ""
1751 },
1752 {,
1688 "EventCode": "0x26086", 1753 "EventCode": "0x26086",
1689 "EventName": "PM_CO_TM_SC_FOOTPRINT", 1754 "EventName": "PM_CO_TM_SC_FOOTPRINT",
1690 "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3) OR L2 TM_store hit dirty HPC line and L3 indicated SC line formed in L3 on RDR bus" 1755 "BriefDescription": "L2 did a cleanifdirty CO to the L3 (ie created an SC line in the L3) OR L2 TM_store hit dirty HPC line and L3 indicated SC line formed in L3 on RDR bus"
@@ -1740,6 +1805,11 @@
1740 "BriefDescription": "All successful D-Side Store dispatches that were an L2 miss for this thread" 1805 "BriefDescription": "All successful D-Side Store dispatches that were an L2 miss for this thread"
1741 }, 1806 },
1742 {, 1807 {,
1808 "EventCode": "0xF8B4",
1809 "EventName": "PM_DC_PREF_XCONS_ALLOC",
1810 "BriefDescription": "Prefetch stream allocated in the Ultra conservative phase by either the hardware prefetch mechanism or software prefetch"
1811 },
1812 {,
1743 "EventCode": "0x35048", 1813 "EventCode": "0x35048",
1744 "EventName": "PM_IPTEG_FROM_DL2L3_SHR", 1814 "EventName": "PM_IPTEG_FROM_DL2L3_SHR",
1745 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request" 1815 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on a different Node or Group (Distant), as this chip due to a instruction side request"
@@ -1782,7 +1852,7 @@
1782 {, 1852 {,
1783 "EventCode": "0x460B2", 1853 "EventCode": "0x460B2",
1784 "EventName": "PM_L3_SYS_GUESS_WRONG", 1854 "EventName": "PM_L3_SYS_GUESS_WRONG",
1785 "BriefDescription": "Initial scope=system (VGS or RNS) but data from local or near. Prediction too high" 1855 "BriefDescription": "Prefetch scope predictor selected VGS or RNS, but was wrong"
1786 }, 1856 },
1787 {, 1857 {,
1788 "EventCode": "0x58B8", 1858 "EventCode": "0x58B8",
@@ -1800,11 +1870,6 @@
1800 "BriefDescription": "Completion time tabortnoncd, tabortcd, treclaim" 1870 "BriefDescription": "Completion time tabortnoncd, tabortcd, treclaim"
1801 }, 1871 },
1802 {, 1872 {,
1803 "EventCode": "0x4C054",
1804 "EventName": "PM_DERAT_MISS_16G",
1805 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16G"
1806 },
1807 {,
1808 "EventCode": "0x268A0", 1873 "EventCode": "0x268A0",
1809 "EventName": "PM_L3_CO_L31", 1874 "EventName": "PM_L3_CO_L31",
1810 "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 (lossy = may undercount if two cresps come in the same cyc)" 1875 "BriefDescription": "L3 CO to L3.1 OR of port 0 and 1 (lossy = may undercount if two cresps come in the same cyc)"
@@ -1862,7 +1927,7 @@
1862 {, 1927 {,
1863 "EventCode": "0x368B2", 1928 "EventCode": "0x368B2",
1864 "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH", 1929 "EventName": "PM_L3_GRP_GUESS_WRONG_HIGH",
1865 "BriefDescription": "Initial scope=group (GS or NNS) but data from local node. Prediction too high" 1930 "BriefDescription": "Prefetch scope predictor selected GS or NNS, but was wrong because scope was VGS or RNS"
1866 }, 1931 },
1867 {, 1932 {,
1868 "EventCode": "0xE8BC", 1933 "EventCode": "0xE8BC",
@@ -1897,7 +1962,7 @@
1897 {, 1962 {,
1898 "EventCode": "0x260B2", 1963 "EventCode": "0x260B2",
1899 "EventName": "PM_L3_SYS_GUESS_CORRECT", 1964 "EventName": "PM_L3_SYS_GUESS_CORRECT",
1900 "BriefDescription": "Initial scope=system (VGS or RNS) and data from outside group (far or rem)(pred successful)" 1965 "BriefDescription": "Prefetch scope predictor selected VGS or RNS and was correct"
1901 }, 1966 },
1902 {, 1967 {,
1903 "EventCode": "0x1D146", 1968 "EventCode": "0x1D146",
@@ -1915,6 +1980,11 @@
1915 "BriefDescription": "RC requests that were on group (aka nodel) pump attempts" 1980 "BriefDescription": "RC requests that were on group (aka nodel) pump attempts"
1916 }, 1981 },
1917 {, 1982 {,
1983 "EventCode": "0xC08C",
1984 "EventName": "PM_LSU_DTLB_MISS_16M_2M",
1985 "BriefDescription": "Data TLB Miss page size 16M (HPT) or 2M (Radix)"
1986 },
1987 {,
1918 "EventCode": "0x16080", 1988 "EventCode": "0x16080",
1919 "EventName": "PM_L2_LD", 1989 "EventName": "PM_L2_LD",
1920 "BriefDescription": "All successful D-side Load dispatches for this thread (L2 miss + L2 hits)" 1990 "BriefDescription": "All successful D-side Load dispatches for this thread (L2 miss + L2 hits)"
@@ -1927,7 +1997,7 @@
1927 {, 1997 {,
1928 "EventCode": "0xC080", 1998 "EventCode": "0xC080",
1929 "EventName": "PM_LS0_LD_VECTOR_FIN", 1999 "EventName": "PM_LS0_LD_VECTOR_FIN",
1930 "BriefDescription": "" 2000 "BriefDescription": "LS0 finished load vector op"
1931 }, 2001 },
1932 {, 2002 {,
1933 "EventCode": "0x368B0", 2003 "EventCode": "0x368B0",
@@ -2000,6 +2070,11 @@
2000 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time" 2070 "BriefDescription": "Conditional Branch Completed in which the HW correctly predicted the direction as taken. Counted at completion time"
2001 }, 2071 },
2002 {, 2072 {,
2073 "EventCode": "0xF0B8",
2074 "EventName": "PM_LS0_UNALIGNED_ST",
2075 "BriefDescription": "Store instructions whose data crosses a double-word boundary, which causes it to require an additional slice than than what normally would be required of the Store of that size. If the Store wraps from slice 3 to slice 0, thee is an additional 3-cycle penalty"
2076 },
2077 {,
2003 "EventCode": "0x20132", 2078 "EventCode": "0x20132",
2004 "EventName": "PM_MRK_DFU_FIN", 2079 "EventName": "PM_MRK_DFU_FIN",
2005 "BriefDescription": "Decimal Unit marked Instruction Finish" 2080 "BriefDescription": "Decimal Unit marked Instruction Finish"
@@ -2007,7 +2082,7 @@
2007 {, 2082 {,
2008 "EventCode": "0x160A6", 2083 "EventCode": "0x160A6",
2009 "EventName": "PM_TM_SC_CO", 2084 "EventName": "PM_TM_SC_CO",
2010 "BriefDescription": "L3 castout TM SC line" 2085 "BriefDescription": "L3 castout of line that was StoreCopy (original value of speculatively written line) in a Transaction"
2011 }, 2086 },
2012 {, 2087 {,
2013 "EventCode": "0xC8B0", 2088 "EventCode": "0xC8B0",
@@ -2017,7 +2092,7 @@
2017 {, 2092 {,
2018 "EventCode": "0x16084", 2093 "EventCode": "0x16084",
2019 "EventName": "PM_L2_RCLD_DISP", 2094 "EventName": "PM_L2_RCLD_DISP",
2020 "BriefDescription": "All I-or-D side load dispatch attempts for this thread (excludes i_l2mru_tch_reqs)" 2095 "BriefDescription": "All D-side-Ld or I-side-instruction-fetch dispatch attempts for this thread"
2021 }, 2096 },
2022 {, 2097 {,
2023 "EventCode": "0x3F150", 2098 "EventCode": "0x3F150",
@@ -2122,12 +2197,12 @@
2122 {, 2197 {,
2123 "EventCode": "0x46082", 2198 "EventCode": "0x46082",
2124 "EventName": "PM_L2_ST_DISP", 2199 "EventName": "PM_L2_ST_DISP",
2125 "BriefDescription": "All successful D-side store dispatches for this thread (L2 miss + L2 hits)" 2200 "BriefDescription": "All successful D-side store dispatches for this thread"
2126 }, 2201 },
2127 {, 2202 {,
2128 "EventCode": "0x36880", 2203 "EventCode": "0x36880",
2129 "EventName": "PM_L2_INST_MISS", 2204 "EventName": "PM_L2_INST_MISS",
2130 "BriefDescription": "All successful I-side dispatches that were an L2 miss for this thread (excludes i_l2mru_tch reqs)" 2205 "BriefDescription": "All successful I-side-instruction-fetch (e.g. i-demand, i-prefetch) dispatches for this thread that were an L2 miss"
2131 }, 2206 },
2132 {, 2207 {,
2133 "EventCode": "0xE084", 2208 "EventCode": "0xE084",
@@ -2217,7 +2292,7 @@
2217 {, 2292 {,
2218 "EventCode": "0xC884", 2293 "EventCode": "0xC884",
2219 "EventName": "PM_LS3_LD_VECTOR_FIN", 2294 "EventName": "PM_LS3_LD_VECTOR_FIN",
2220 "BriefDescription": "" 2295 "BriefDescription": "LS3 finished load vector op"
2221 }, 2296 },
2222 {, 2297 {,
2223 "EventCode": "0x360A8", 2298 "EventCode": "0x360A8",
@@ -2242,7 +2317,7 @@
2242 {, 2317 {,
2243 "EventCode": "0x168B2", 2318 "EventCode": "0x168B2",
2244 "EventName": "PM_L3_GRP_GUESS_CORRECT", 2319 "EventName": "PM_L3_GRP_GUESS_CORRECT",
2245 "BriefDescription": "Initial scope=group (GS or NNS) and data from same group (near) (pred successful)" 2320 "BriefDescription": "Prefetch scope predictor selected GS or NNS and was correct"
2246 }, 2321 },
2247 {, 2322 {,
2248 "EventCode": "0x48A4", 2323 "EventCode": "0x48A4",
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
index 5af1abbe82c4..b4772f54a271 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pipeline.json
@@ -65,11 +65,6 @@
65 "BriefDescription": "Dispatch Held" 65 "BriefDescription": "Dispatch Held"
66 }, 66 },
67 {, 67 {,
68 "EventCode": "0x3D154",
69 "EventName": "PM_MRK_DERAT_MISS_16M",
70 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16M"
71 },
72 {,
73 "EventCode": "0x200F8", 68 "EventCode": "0x200F8",
74 "EventName": "PM_EXT_INT", 69 "EventName": "PM_EXT_INT",
75 "BriefDescription": "external interrupt" 70 "BriefDescription": "external interrupt"
@@ -120,6 +115,11 @@
120 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 115 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L3 without dispatch conflicts hit on Mepf state. due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
121 }, 116 },
122 {, 117 {,
118 "EventCode": "0x4C15C",
119 "EventName": "PM_MRK_DERAT_MISS_16G_1G",
120 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16G (hpt mode) and 1G (radix mode)"
121 },
122 {,
123 "EventCode": "0x10024", 123 "EventCode": "0x10024",
124 "EventName": "PM_PMC5_OVERFLOW", 124 "EventName": "PM_PMC5_OVERFLOW",
125 "BriefDescription": "Overflow from counter 5" 125 "BriefDescription": "Overflow from counter 5"
@@ -155,11 +155,6 @@
155 "BriefDescription": "Ict empty for this thread due to Icache Miss" 155 "BriefDescription": "Ict empty for this thread due to Icache Miss"
156 }, 156 },
157 {, 157 {,
158 "EventCode": "0x3D152",
159 "EventName": "PM_MRK_DERAT_MISS_1G",
160 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 1G. Implies radix translation"
161 },
162 {,
163 "EventCode": "0x4F14A", 158 "EventCode": "0x4F14A",
164 "EventName": "PM_MRK_DPTEG_FROM_OFF_CHIP_CACHE", 159 "EventName": "PM_MRK_DPTEG_FROM_OFF_CHIP_CACHE",
165 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 160 "BriefDescription": "A Page Table Entry was loaded into the TLB either shared or modified data from another core's L2/L3 on a different chip (remote or distant) due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
@@ -185,11 +180,6 @@
185 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 180 "BriefDescription": "A Page Table Entry was loaded into the TLB from local core's L2 without conflict due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
186 }, 181 },
187 {, 182 {,
188 "EventCode": "0x2C05A",
189 "EventName": "PM_DERAT_MISS_1G",
190 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 1G. Implies radix translation"
191 },
192 {,
193 "EventCode": "0x1F058", 183 "EventCode": "0x1F058",
194 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L2", 184 "EventName": "PM_RADIX_PWC_L2_PTE_FROM_L2",
195 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from the core's L2 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation" 185 "BriefDescription": "A Page Table Entry was reloaded to a level 2 page walk cache from the core's L2 data cache. This implies that level 3 and level 4 PWC accesses were not necessary for this translation"
@@ -240,11 +230,6 @@
240 "BriefDescription": "Data PTEG reload" 230 "BriefDescription": "Data PTEG reload"
241 }, 231 },
242 {, 232 {,
243 "EventCode": "0x2D152",
244 "EventName": "PM_MRK_DERAT_MISS_2M",
245 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation"
246 },
247 {,
248 "EventCode": "0x2C046", 233 "EventCode": "0x2C046",
249 "EventName": "PM_DATA_FROM_RL2L3_MOD", 234 "EventName": "PM_DATA_FROM_RL2L3_MOD",
250 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load" 235 "BriefDescription": "The processor's data cache was reloaded with Modified (M) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a demand load"
@@ -290,6 +275,11 @@
290 "BriefDescription": "Finish stall because the NTF instruction was issued to the Decimal Floating Point execution pipe and waiting to finish. Includes decimal floating point instructions + 128 bit binary floating point instructions. Not qualified by multicycle" 275 "BriefDescription": "Finish stall because the NTF instruction was issued to the Decimal Floating Point execution pipe and waiting to finish. Includes decimal floating point instructions + 128 bit binary floating point instructions. Not qualified by multicycle"
291 }, 276 },
292 {, 277 {,
278 "EventCode": "0x3C054",
279 "EventName": "PM_DERAT_MISS_16M_2M",
280 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M (HPT mode) or 2M (Radix mode)"
281 },
282 {,
293 "EventCode": "0x4C04C", 283 "EventCode": "0x4C04C",
294 "EventName": "PM_DATA_FROM_DMEM", 284 "EventName": "PM_DATA_FROM_DMEM",
295 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load" 285 "BriefDescription": "The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load"
@@ -360,11 +350,6 @@
360 "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to an instruction fetch (not prefetch)" 350 "BriefDescription": "The processor's Instruction cache was reloaded from a memory location including L4 from local remote or distant due to an instruction fetch (not prefetch)"
361 }, 351 },
362 {, 352 {,
363 "EventCode": "0x1C05A",
364 "EventName": "PM_DERAT_MISS_2M",
365 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation"
366 },
367 {,
368 "EventCode": "0x30024", 353 "EventCode": "0x30024",
369 "EventName": "PM_PMC6_OVERFLOW", 354 "EventName": "PM_PMC6_OVERFLOW",
370 "BriefDescription": "Overflow from counter 6" 355 "BriefDescription": "Overflow from counter 6"
@@ -375,6 +360,11 @@
375 "BriefDescription": "Branch Instruction Finished" 360 "BriefDescription": "Branch Instruction Finished"
376 }, 361 },
377 {, 362 {,
363 "EventCode": "0x3D154",
364 "EventName": "PM_MRK_DERAT_MISS_16M_2M",
365 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16M (hpt mode) or 2M (radix mode)"
366 },
367 {,
378 "EventCode": "0x30020", 368 "EventCode": "0x30020",
379 "EventName": "PM_PMC2_REWIND", 369 "EventName": "PM_PMC2_REWIND",
380 "BriefDescription": "PMC2 Rewind Event (did not match condition)" 370 "BriefDescription": "PMC2 Rewind Event (did not match condition)"
@@ -410,11 +400,6 @@
410 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included" 400 "BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's L3 on the same chip due to a marked data side request. When using Radix Page Translation, this count excludes PDE reloads. Only PTE reloads are included"
411 }, 401 },
412 {, 402 {,
413 "EventCode": "0x4C15C",
414 "EventName": "PM_MRK_DERAT_MISS_16G",
415 "BriefDescription": "Marked Data ERAT Miss (Data TLB Access) page size 16G"
416 },
417 {,
418 "EventCode": "0x14052", 403 "EventCode": "0x14052",
419 "EventName": "PM_INST_GRP_PUMP_MPRED_RTY", 404 "EventName": "PM_INST_GRP_PUMP_MPRED_RTY",
420 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch" 405 "BriefDescription": "Final Pump Scope (Group) ended up larger than Initial Pump Scope (Chip) for an instruction fetch"
@@ -445,11 +430,6 @@
445 "BriefDescription": "Icache miss demand cycles" 430 "BriefDescription": "Icache miss demand cycles"
446 }, 431 },
447 {, 432 {,
448 "EventCode": "0x3C054",
449 "EventName": "PM_DERAT_MISS_16M",
450 "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M"
451 },
452 {,
453 "EventCode": "0x2D14E", 433 "EventCode": "0x2D14E",
454 "EventName": "PM_MRK_DATA_FROM_L21_SHR", 434 "EventName": "PM_MRK_DATA_FROM_L21_SHR",
455 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a marked load" 435 "BriefDescription": "The processor's data cache was reloaded with Shared (S) data from another core's L2 on the same chip due to a marked load"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
index d0b89f930567..8b3b0f3be664 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/pmc.json
@@ -10,11 +10,6 @@
10 "BriefDescription": "Local memory above threshold for LSU medium" 10 "BriefDescription": "Local memory above threshold for LSU medium"
11 }, 11 },
12 {, 12 {,
13 "EventCode": "0x2C056",
14 "EventName": "PM_DTLB_MISS_4K",
15 "BriefDescription": "Data TLB Miss page size 4k"
16 },
17 {,
18 "EventCode": "0x40118", 13 "EventCode": "0x40118",
19 "EventName": "PM_MRK_DCACHE_RELOAD_INTV", 14 "EventName": "PM_MRK_DCACHE_RELOAD_INTV",
20 "BriefDescription": "Combined Intervention event" 15 "BriefDescription": "Combined Intervention event"
diff --git a/tools/perf/pmu-events/arch/powerpc/power9/translation.json b/tools/perf/pmu-events/arch/powerpc/power9/translation.json
index bc8e03d7a6b0..b27642676244 100644
--- a/tools/perf/pmu-events/arch/powerpc/power9/translation.json
+++ b/tools/perf/pmu-events/arch/powerpc/power9/translation.json
@@ -30,11 +30,6 @@
30 "BriefDescription": "Store finish count. Includes speculative activity" 30 "BriefDescription": "Store finish count. Includes speculative activity"
31 }, 31 },
32 {, 32 {,
33 "EventCode": "0x44042",
34 "EventName": "PM_INST_FROM_L3",
35 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to an instruction fetch (not prefetch)"
36 },
37 {,
38 "EventCode": "0x1504A", 33 "EventCode": "0x1504A",
39 "EventName": "PM_IPTEG_FROM_RL2L3_SHR", 34 "EventName": "PM_IPTEG_FROM_RL2L3_SHR",
40 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request" 35 "BriefDescription": "A Page Table Entry was loaded into the TLB with Shared (S) data from another chip's L2 or L3 on the same Node or Group (Remote), as this chip due to a instruction side request"
@@ -125,6 +120,11 @@
125 "BriefDescription": "PMC1 Rewind Value saved" 120 "BriefDescription": "PMC1 Rewind Value saved"
126 }, 121 },
127 {, 122 {,
123 "EventCode": "0x44042",
124 "EventName": "PM_INST_FROM_L3",
125 "BriefDescription": "The processor's Instruction cache was reloaded from local core's L3 due to an instruction fetch (not prefetch)"
126 },
127 {,
128 "EventCode": "0x200FE", 128 "EventCode": "0x200FE",
129 "EventName": "PM_DATA_FROM_L2MISS", 129 "EventName": "PM_DATA_FROM_L2MISS",
130 "BriefDescription": "Demand LD - L2 Miss (not L2 hit)" 130 "BriefDescription": "Demand LD - L2 Miss (not L2 hit)"
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/basic.json b/tools/perf/pmu-events/arch/s390/cf_z10/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z10/extended.json b/tools/perf/pmu-events/arch/s390/cf_z10/extended.json
new file mode 100644
index 000000000000..0feedb40f30f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z10/extended.json
@@ -0,0 +1,110 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1I_L2_SOURCED_WRITES",
5 "BriefDescription": "L1I L2 Sourced Writes",
6 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from the Level-2 (L1.5) cache"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "L1D_L2_SOURCED_WRITES",
11 "BriefDescription": "L1D L2 Sourced Writes",
12 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from the Level-2 (L1.5) cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "L1I_L3_LOCAL_WRITES",
17 "BriefDescription": "L1I L3 Local Writes",
18 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the installed cache line was sourced from the Level-3 cache that is on the same book as the Instruction cache (Local L2 cache)"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "L1D_L3_LOCAL_WRITES",
23 "BriefDescription": "L1D L3 Local Writes",
24 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installtion cache line was source from the Level-3 cache that is on the same book as the Data cache (Local L2 cache)"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "L1I_L3_REMOTE_WRITES",
29 "BriefDescription": "L1I L3 Remote Writes",
30 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the installed cache line was sourced from a Level-3 cache that is not on the same book as the Instruction cache (Remote L2 cache)"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L3_REMOTE_WRITES",
35 "BriefDescription": "L1D L3 Remote Writes",
36 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from a Level-3 cache that is not on the same book as the Data cache (Remote L2 cache)"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "L1D_LMEM_SOURCED_WRITES",
41 "BriefDescription": "L1D Local Memory Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "L1I_LMEM_SOURCED_WRITES",
47 "BriefDescription": "L1I Local Memory Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 I-Cache where the installed cache line was sourced from memory that is attached to the s ame book as the Instruction cache (Local Memory)"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "L1I_CACHELINE_INVALIDATES",
59 "BriefDescription": "L1I Cacheline Invalidates",
60 "PublicDescription": "A cache line in the Level-1 I-Cache has been invalidated by a store on the same CPU as the Level-1 I-Cache"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "ITLB1_WRITES",
65 "BriefDescription": "ITLB1 Writes",
66 "PublicDescription": "A translation entry has been written into the Level-1 Instruction Translation Lookaside Buffer"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "DTLB1_WRITES",
71 "BriefDescription": "DTLB1 Writes",
72 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TLB2_PTE_WRITES",
77 "BriefDescription": "TLB2 PTE Writes",
78 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TLB2_CRSTE_WRITES",
83 "BriefDescription": "TLB2 CRSTE Writes",
84 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
85 },
86 {
87 "EventCode": "142",
88 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
89 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
90 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
91 },
92 {
93 "EventCode": "145",
94 "EventName": "ITLB1_MISSES",
95 "BriefDescription": "ITLB1 Misses",
96 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle an ITLB1 miss is in progress"
97 },
98 {
99 "EventCode": "146",
100 "EventName": "DTLB1_MISSES",
101 "BriefDescription": "DTLB1 Misses",
102 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle an DTLB1 miss is in progress"
103 },
104 {
105 "EventCode": "147",
106 "EventName": "L2C_STORES_SENT",
107 "BriefDescription": "L2C Stores Sent",
108 "PublicDescription": "Incremented by one for every store sent to Level-2 (L1.5) cache"
109 },
110]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/basic.json b/tools/perf/pmu-events/arch/s390/cf_z13/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z13/extended.json b/tools/perf/pmu-events/arch/s390/cf_z13/extended.json
new file mode 100644
index 000000000000..9a002b6967f1
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z13/extended.json
@@ -0,0 +1,338 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_RO_EXCL_WRITES",
5 "BriefDescription": "L1D Read-only Exclusive Writes",
6 "PublicDescription": "A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line."
7 },
8 {
9 "EventCode": "129",
10 "EventName": "DTLB1_WRITES",
11 "BriefDescription": "DTLB1 Writes",
12 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB1_MISSES",
17 "BriefDescription": "DTLB1 Misses",
18 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
19 },
20 {
21 "EventCode": "131",
22 "EventName": "DTLB1_HPAGE_WRITES",
23 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
24 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "DTLB1_GPAGE_WRITES",
29 "BriefDescription": "DTLB1 Two-Gigabyte Page Writes",
30 "PublicDescription": "Counter:132 Name:DTLB1_GPAGE_WRITES A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L2D_SOURCED_WRITES",
35 "BriefDescription": "L1D L2D Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "ITLB1_WRITES",
41 "BriefDescription": "ITLB1 Writes",
42 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "ITLB1_MISSES",
47 "BriefDescription": "ITLB1 Misses",
48 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle an ITLB1 miss is in progress"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1I_L2I_SOURCED_WRITES",
53 "BriefDescription": "L1I L2I Sourced Writes",
54 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "TLB2_PTE_WRITES",
59 "BriefDescription": "TLB2 PTE Writes",
60 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
65 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
66 "PublicDescription": "A translation entry has been written to the Level-2 TLB Combined Region Segment Table Entry arrays for a one-megabyte large page translation"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "TLB2_CRSTE_WRITES",
71 "BriefDescription": "TLB2 CRSTE Writes",
72 "PublicDescription": "A translation entry has been written to the Level-2 TLB Combined Region Segment Table Entry arrays"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TX_C_TEND",
77 "BriefDescription": "Completed TEND instructions in constrained TX mode",
78 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TX_NC_TEND",
83 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
84 "PublicDescription": "A TEND instruction has completed in a non-constrained transactional-execution mode"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1C_TLB1_MISSES",
89 "BriefDescription": "L1C TLB1 Misses",
90 "PublicDescription": "Increments by one for any cycle where a Level-1 cache or Level-1 TLB miss is in progress."
91 },
92 {
93 "EventCode": "144",
94 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
101 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache with intervention"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "L1D_ONNODE_L4_SOURCED_WRITES",
107 "BriefDescription": "L1D On-Node L4 Sourced Writes",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-4 cache"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "L1D_ONNODE_L3_SOURCED_WRITES_IV",
113 "BriefDescription": "L1D On-Node L3 Sourced Writes with Intervention",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-3 cache with intervention"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "L1D_ONNODE_L3_SOURCED_WRITES",
119 "BriefDescription": "L1D On-Node L3 Sourced Writes",
120 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Node Level-3 cache without intervention"
121 },
122 {
123 "EventCode": "149",
124 "EventName": "L1D_ONDRAWER_L4_SOURCED_WRITES",
125 "BriefDescription": "L1D On-Drawer L4 Sourced Writes",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-4 cache"
127 },
128 {
129 "EventCode": "150",
130 "EventName": "L1D_ONDRAWER_L3_SOURCED_WRITES_IV",
131 "BriefDescription": "L1D On-Drawer L3 Sourced Writes with Intervention",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache with intervention"
133 },
134 {
135 "EventCode": "151",
136 "EventName": "L1D_ONDRAWER_L3_SOURCED_WRITES",
137 "BriefDescription": "L1D On-Drawer L3 Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache without intervention"
139 },
140 {
141 "EventCode": "152",
142 "EventName": "L1D_OFFDRAWER_SCOL_L4_SOURCED_WRITES",
143 "BriefDescription": "L1D Off-Drawer Same-Column L4 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-4 cache"
145 },
146 {
147 "EventCode": "153",
148 "EventName": "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV",
149 "BriefDescription": "L1D Off-Drawer Same-Column L3 Sourced Writes with Intervention",
150 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache with intervention"
151 },
152 {
153 "EventCode": "154",
154 "EventName": "L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES",
155 "BriefDescription": "L1D Off-Drawer Same-Column L3 Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache without intervention"
157 },
158 {
159 "EventCode": "155",
160 "EventName": "L1D_OFFDRAWER_FCOL_L4_SOURCED_WRITES",
161 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes",
162 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-4 cache"
163 },
164 {
165 "EventCode": "156",
166 "EventName": "L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV",
167 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes with Intervention",
168 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache with intervention"
169 },
170 {
171 "EventCode": "157",
172 "EventName": "L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES",
173 "BriefDescription": "L1D Off-Drawer Far-Column L3 Sourced Writes",
174 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache without intervention"
175 },
176 {
177 "EventCode": "158",
178 "EventName": "L1D_ONNODE_MEM_SOURCED_WRITES",
179 "BriefDescription": "L1D On-Node Memory Sourced Writes",
180 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Node memory"
181 },
182 {
183 "EventCode": "159",
184 "EventName": "L1D_ONDRAWER_MEM_SOURCED_WRITES",
185 "BriefDescription": "L1D On-Drawer Memory Sourced Writes",
186 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer memory"
187 },
188 {
189 "EventCode": "160",
190 "EventName": "L1D_OFFDRAWER_MEM_SOURCED_WRITES",
191 "BriefDescription": "L1D Off-Drawer Memory Sourced Writes",
192 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer memory"
193 },
194 {
195 "EventCode": "161",
196 "EventName": "L1D_ONCHIP_MEM_SOURCED_WRITES",
197 "BriefDescription": "L1D On-Chip Memory Sourced Writes",
198 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip memory"
199 },
200 {
201 "EventCode": "162",
202 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
203 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
204 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
205 },
206 {
207 "EventCode": "163",
208 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
209 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
210 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache with intervention"
211 },
212 {
213 "EventCode": "164",
214 "EventName": "L1I_ONNODE_L4_SOURCED_WRITES",
215 "BriefDescription": "L1I On-Chip L4 Sourced Writes",
216 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-4 cache"
217 },
218 {
219 "EventCode": "165",
220 "EventName": "L1I_ONNODE_L3_SOURCED_WRITES_IV",
221 "BriefDescription": "L1I On-Node L3 Sourced Writes with Intervention",
222 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-3 cache with intervention"
223 },
224 {
225 "EventCode": "166",
226 "EventName": "L1I_ONNODE_L3_SOURCED_WRITES",
227 "BriefDescription": "L1I On-Node L3 Sourced Writes",
228 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Node Level-3 cache without intervention"
229 },
230 {
231 "EventCode": "167",
232 "EventName": "L1I_ONDRAWER_L4_SOURCED_WRITES",
233 "BriefDescription": "L1I On-Drawer L4 Sourced Writes",
234 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-4 cache"
235 },
236 {
237 "EventCode": "168",
238 "EventName": "L1I_ONDRAWER_L3_SOURCED_WRITES_IV",
239 "BriefDescription": "L1I On-Drawer L3 Sourced Writes with Intervention",
240 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache with intervention"
241 },
242 {
243 "EventCode": "169",
244 "EventName": "L1I_ONDRAWER_L3_SOURCED_WRITES",
245 "BriefDescription": "L1I On-Drawer L3 Sourced Writes",
246 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Drawer Level-3 cache without intervention"
247 },
248 {
249 "EventCode": "170",
250 "EventName": "L1I_OFFDRAWER_SCOL_L4_SOURCED_WRITES",
251 "BriefDescription": "L1I Off-Drawer Same-Column L4 Sourced Writes",
252 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-4 cache"
253 },
254 {
255 "EventCode": "171",
256 "EventName": "L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV",
257 "BriefDescription": "L1I Off-Drawer Same-Column L3 Sourced Writes with Intervention",
258 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache with intervention"
259 },
260 {
261 "EventCode": "172",
262 "EventName": "L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES",
263 "BriefDescription": "L1I Off-Drawer Same-Column L3 Sourced Writes",
264 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Same-Column Level-3 cache without intervention"
265 },
266 {
267 "EventCode": "173",
268 "EventName": "L1I_OFFDRAWER_FCOL_L4_SOURCED_WRITES",
269 "BriefDescription": "L1I Off-Drawer Far-Column L4 Sourced Writes",
270 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-4 cache"
271 },
272 {
273 "EventCode": "174",
274 "EventName": "L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV",
275 "BriefDescription": "L1I Off-Drawer Far-Column L3 Sourced Writes with Intervention",
276 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache with intervention"
277 },
278 {
279 "EventCode": "175",
280 "EventName": "L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES",
281 "BriefDescription": "L1I Off-Drawer Far-Column L3 Sourced Writes",
282 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Far-Column Level-3 cache without intervention"
283 },
284 {
285 "EventCode": "176",
286 "EventName": "L1I_ONNODE_MEM_SOURCED_WRITES",
287 "BriefDescription": "L1I On-Node Memory Sourced Writes",
288 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Node memory"
289 },
290 {
291 "EventCode": "177",
292 "EventName": "L1I_ONDRAWER_MEM_SOURCED_WRITES",
293 "BriefDescription": "L1I On-Drawer Memory Sourced Writes",
294 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer memory"
295 },
296 {
297 "EventCode": "178",
298 "EventName": "L1I_OFFDRAWER_MEM_SOURCED_WRITES",
299 "BriefDescription": "L1I Off-Drawer Memory Sourced Writes",
300 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer memory"
301 },
302 {
303 "EventCode": "179",
304 "EventName": "L1I_ONCHIP_MEM_SOURCED_WRITES",
305 "BriefDescription": "L1I On-Chip Memory Sourced Writes",
306 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Chip memory"
307 },
308 {
309 "EventCode": "218",
310 "EventName": "TX_NC_TABORT",
311 "BriefDescription": "Aborted transactions in non-constrained TX mode",
312 "PublicDescription": "A transaction abort has occurred in a non-constrained transactional-execution mode"
313 },
314 {
315 "EventCode": "219",
316 "EventName": "TX_C_TABORT_NO_SPECIAL",
317 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
318 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
319 },
320 {
321 "EventCode": "220",
322 "EventName": "TX_C_TABORT_SPECIAL",
323 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
324 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
325 },
326 {
327 "EventCode": "448",
328 "EventName": "MT_DIAG_CYCLES_ONE_THR_ACTIVE",
329 "BriefDescription": "Cycle count with one thread active",
330 "PublicDescription": "Cycle count with one thread active"
331 },
332 {
333 "EventCode": "449",
334 "EventName": "MT_DIAG_CYCLES_TWO_THR_ACTIVE",
335 "BriefDescription": "Cycle count with two threads active",
336 "PublicDescription": "Cycle count with two threads active"
337 },
338]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/basic.json b/tools/perf/pmu-events/arch/s390/cf_z14/basic.json
new file mode 100644
index 000000000000..8f653c9d899d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/basic.json
@@ -0,0 +1,50 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z14/extended.json b/tools/perf/pmu-events/arch/s390/cf_z14/extended.json
new file mode 100644
index 000000000000..aa4dfb46b65b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z14/extended.json
@@ -0,0 +1,320 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_RO_EXCL_WRITES",
5 "BriefDescription": "L1D Read-only Exclusive Writes",
6 "PublicDescription": "Counter:128 Name:L1D_RO_EXCL_WRITES A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "DTLB2_WRITES",
11 "BriefDescription": "DTLB2 Writes",
12 "PublicDescription": "A translation has been written into The Translation Lookaside Buffer 2 (TLB2) and the request was made by the data cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB2_MISSES",
17 "BriefDescription": "DTLB2 Misses",
18 "PublicDescription": "A TLB2 miss is in progress for a request made by the data cache. Incremented by one for every TLB2 miss in progress for the Level-1 Data cache on this cycle"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "DTLB2_HPAGE_WRITES",
23 "BriefDescription": "DTLB2 One-Megabyte Page Writes",
24 "PublicDescription": "A translation entry was written into the Combined Region and Segment Table Entry array in the Level-2 TLB for a one-megabyte page or a Last Host Translation was done"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "DTLB2_GPAGE_WRITES",
29 "BriefDescription": "DTLB2 Two-Gigabyte Page Writes",
30 "PublicDescription": "A translation entry for a two-gigabyte page was written into the Level-2 TLB"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "L1D_L2D_SOURCED_WRITES",
35 "BriefDescription": "L1D L2D Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
37 },
38 {
39 "EventCode": "134",
40 "EventName": "ITLB2_WRITES",
41 "BriefDescription": "ITLB2 Writes",
42 "PublicDescription": "A translation entry has been written into the Translation Lookaside Buffer 2 (TLB2) and the request was made by the instruction cache"
43 },
44 {
45 "EventCode": "135",
46 "EventName": "ITLB2_MISSES",
47 "BriefDescription": "ITLB2 Misses",
48 "PublicDescription": "A TLB2 miss is in progress for a request made by the instruction cache. Incremented by one for every TLB2 miss in progress for the Level-1 Instruction cache in a cycle"
49 },
50 {
51 "EventCode": "136",
52 "EventName": "L1I_L2I_SOURCED_WRITES",
53 "BriefDescription": "L1I L2I Sourced Writes",
54 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
55 },
56 {
57 "EventCode": "137",
58 "EventName": "TLB2_PTE_WRITES",
59 "BriefDescription": "TLB2 PTE Writes",
60 "PublicDescription": "A translation entry was written into the Page Table Entry array in the Level-2 TLB"
61 },
62 {
63 "EventCode": "138",
64 "EventName": "TLB2_CRSTE_WRITES",
65 "BriefDescription": "TLB2 CRSTE Writes",
66 "PublicDescription": "Translation entries were written into the Combined Region and Segment Table Entry array and the Page Table Entry array in the Level-2 TLB"
67 },
68 {
69 "EventCode": "139",
70 "EventName": "TLB2_ENGINES_BUSY",
71 "BriefDescription": "TLB2 Engines Busy",
72 "PublicDescription": "The number of Level-2 TLB translation engines busy in a cycle"
73 },
74 {
75 "EventCode": "140",
76 "EventName": "TX_C_TEND",
77 "BriefDescription": "Completed TEND instructions in constrained TX mode",
78 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
79 },
80 {
81 "EventCode": "141",
82 "EventName": "TX_NC_TEND",
83 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
84 "PublicDescription": "A TEND instruction has completed in a non-constrained transactional-execution mode"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1C_TLB2_MISSES",
89 "BriefDescription": "L1C TLB2 Misses",
90 "PublicDescription": "Increments by one for any cycle where a level-1 cache or level-2 TLB miss is in progress"
91 },
92 {
93 "EventCode": "144",
94 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "L1D_ONCHIP_MEMORY_SOURCED_WRITES",
101 "BriefDescription": "L1D On-Chip Memory Sourced Writes",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip memory"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
107 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Chip Level-3 cache with intervention"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "L1D_ONCLUSTER_L3_SOURCED_WRITES",
113 "BriefDescription": "L1D On-Cluster L3 Sourced Writes",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Cluster Level-3 cache withountervention"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "L1D_ONCLUSTER_MEMORY_SOURCED_WRITES",
119 "BriefDescription": "L1D On-Cluster Memory Sourced Writes",
120 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Cluster memory"
121 },
122 {
123 "EventCode": "149",
124 "EventName": "L1D_ONCLUSTER_L3_SOURCED_WRITES_IV",
125 "BriefDescription": "L1D On-Cluster L3 Sourced Writes with Intervention",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On-Cluster Level-3 cache with intervention"
127 },
128 {
129 "EventCode": "150",
130 "EventName": "L1D_OFFCLUSTER_L3_SOURCED_WRITES",
131 "BriefDescription": "L1D Off-Cluster L3 Sourced Writes",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache without intervention"
133 },
134 {
135 "EventCode": "151",
136 "EventName": "L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES",
137 "BriefDescription": "L1D Off-Cluster Memory Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Cluster memory"
139 },
140 {
141 "EventCode": "152",
142 "EventName": "L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV",
143 "BriefDescription": "L1D Off-Cluster L3 Sourced Writes with Intervention",
144 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache with intervention"
145 },
146 {
147 "EventCode": "153",
148 "EventName": "L1D_OFFDRAWER_L3_SOURCED_WRITES",
149 "BriefDescription": "L1D Off-Drawer L3 Sourced Writes",
150 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache without intervention"
151 },
152 {
153 "EventCode": "154",
154 "EventName": "L1D_OFFDRAWER_MEMORY_SOURCED_WRITES",
155 "BriefDescription": "L1D Off-Drawer Memory Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Drawer memory"
157 },
158 {
159 "EventCode": "155",
160 "EventName": "L1D_OFFDRAWER_L3_SOURCED_WRITES_IV",
161 "BriefDescription": "L1D Off-Drawer L3 Sourced Writes with Intervention",
162 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache with intervention"
163 },
164 {
165 "EventCode": "156",
166 "EventName": "L1D_ONDRAWER_L4_SOURCED_WRITES",
167 "BriefDescription": "L1D On-Drawer L4 Sourced Writes",
168 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Drawer Level-4 cache"
169 },
170 {
171 "EventCode": "157",
172 "EventName": "L1D_OFFDRAWER_L4_SOURCED_WRITES",
173 "BriefDescription": "L1D Off-Drawer L4 Sourced Writes",
174 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from Off-Drawer Level-4 cache"
175 },
176 {
177 "EventCode": "158",
178 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_RO",
179 "BriefDescription": "L1D On-Chip L3 Sourced Writes read-only",
180 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from On-Chip L3 but a read-only invalidate was done to remove other copies of the cache line"
181 },
182 {
183 "EventCode": "162",
184 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
185 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
186 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from an On-Chip Level-3 cache without intervention"
187 },
188 {
189 "EventCode": "163",
190 "EventName": "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
191 "BriefDescription": "L1I On-Chip Memory Sourced Writes",
192 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from On-Chip memory"
193 },
194 {
195 "EventCode": "164",
196 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
197 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
198 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache ine was sourced from an On-Chip Level-3 cache with intervention"
199 },
200 {
201 "EventCode": "165",
202 "EventName": "L1I_ONCLUSTER_L3_SOURCED_WRITES",
203 "BriefDescription": "L1I On-Cluster L3 Sourced Writes",
204 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Cluster Level-3 cache without intervention"
205 },
206 {
207 "EventCode": "166",
208 "EventName": "L1I_ONCLUSTER_MEMORY_SOURCED_WRITES",
209 "BriefDescription": "L1I On-Cluster Memory Sourced Writes",
210 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On-Cluster memory"
211 },
212 {
213 "EventCode": "167",
214 "EventName": "L1I_ONCLUSTER_L3_SOURCED_WRITES_IV",
215 "BriefDescription": "L1I On-Cluster L3 Sourced Writes with Intervention",
216 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Cluster Level-3 cache with intervention"
217 },
218 {
219 "EventCode": "168",
220 "EventName": "L1I_OFFCLUSTER_L3_SOURCED_WRITES",
221 "BriefDescription": "L1I Off-Cluster L3 Sourced Writes",
222 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache without intervention"
223 },
224 {
225 "EventCode": "169",
226 "EventName": "L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES",
227 "BriefDescription": "L1I Off-Cluster Memory Sourced Writes",
228 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Cluster memory"
229 },
230 {
231 "EventCode": "170",
232 "EventName": "L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV",
233 "BriefDescription": "L1I Off-Cluster L3 Sourced Writes with Intervention",
234 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Cluster Level-3 cache with intervention"
235 },
236 {
237 "EventCode": "171",
238 "EventName": "L1I_OFFDRAWER_L3_SOURCED_WRITES",
239 "BriefDescription": "L1I Off-Drawer L3 Sourced Writes",
240 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache without intervention"
241 },
242 {
243 "EventCode": "172",
244 "EventName": "L1I_OFFDRAWER_MEMORY_SOURCED_WRITES",
245 "BriefDescription": "L1I Off-Drawer Memory Sourced Writes",
246 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Drawer memory"
247 },
248 {
249 "EventCode": "173",
250 "EventName": "L1I_OFFDRAWER_L3_SOURCED_WRITES_IV",
251 "BriefDescription": "L1I Off-Drawer L3 Sourced Writes with Intervention",
252 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off-Drawer Level-3 cache with intervention"
253 },
254 {
255 "EventCode": "174",
256 "EventName": "L1I_ONDRAWER_L4_SOURCED_WRITES",
257 "BriefDescription": "L1I On-Drawer L4 Sourced Writes",
258 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from On-Drawer Level-4 cache"
259 },
260 {
261 "EventCode": "175",
262 "EventName": "L1I_OFFDRAWER_L4_SOURCED_WRITES",
263 "BriefDescription": "L1I Off-Drawer L4 Sourced Writes",
264 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from Off-Drawer Level-4 cache"
265 },
266 {
267 "EventCode": "224",
268 "EventName": "BCD_DFP_EXECUTION_SLOTS",
269 "BriefDescription": "BCD DFP Execution Slots",
270 "PublicDescription": "Count of floating point execution slots used for finished Binary Coded Decimal to Decimal Floating Point conversions. Instructions: CDZT, CXZT, CZDT, CZXT"
271 },
272 {
273 "EventCode": "225",
274 "EventName": "VX_BCD_EXECUTION_SLOTS",
275 "BriefDescription": "VX BCD Execution Slots",
276 "PublicDescription": "Count of floating point execution slots used for finished vector arithmetic Binary Coded Decimal instructions. Instructions: VAP, VSP, VMPVMSP, VDP, VSDP, VRP, VLIP, VSRP, VPSOPVCP, VTP, VPKZ, VUPKZ, VCVB, VCVBG, VCVDVCVDG"
277 },
278 {
279 "EventCode": "226",
280 "EventName": "DECIMAL_INSTRUCTIONS",
281 "BriefDescription": "Decimal Instructions",
282 "PublicDescription": "Decimal instructions dispatched. Instructions: CVB, CVD, AP, CP, DP, ED, EDMK, MP, SRP, SP, ZAP"
283 },
284 {
285 "EventCode": "232",
286 "EventName": "LAST_HOST_TRANSLATIONS",
287 "BriefDescription": "Last host translation done",
288 "PublicDescription": "Last Host Translation done"
289 },
290 {
291 "EventCode": "243",
292 "EventName": "TX_NC_TABORT",
293 "BriefDescription": "Aborted transactions in non-constrained TX mode",
294 "PublicDescription": "A transaction abort has occurred in a non-constrained transactional-execution mode"
295 },
296 {
297 "EventCode": "244",
298 "EventName": "TX_C_TABORT_NO_SPECIAL",
299 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
300 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
301 },
302 {
303 "EventCode": "245",
304 "EventName": "TX_C_TABORT_SPECIAL",
305 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
306 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
307 },
308 {
309 "EventCode": "448",
310 "EventName": "MT_DIAG_CYCLES_ONE_THR_ACTIVE",
311 "BriefDescription": "Cycle count with one thread active",
312 "PublicDescription": "Cycle count with one thread active"
313 },
314 {
315 "EventCode": "449",
316 "EventName": "MT_DIAG_CYCLES_TWO_THR_ACTIVE",
317 "BriefDescription": "Cycle count with two threads active",
318 "PublicDescription": "Cycle count with two threads active"
319 },
320]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/basic.json b/tools/perf/pmu-events/arch/s390/cf_z196/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json b/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_z196/extended.json b/tools/perf/pmu-events/arch/s390/cf_z196/extended.json
new file mode 100644
index 000000000000..b6d7fec7c2e7
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_z196/extended.json
@@ -0,0 +1,146 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "L1D_L2_SOURCED_WRITES",
5 "BriefDescription": "L1D L2 Sourced Writes",
6 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from the Level-2 cache"
7 },
8 {
9 "EventCode": "129",
10 "EventName": "L1I_L2_SOURCED_WRITES",
11 "BriefDescription": "L1I L2 Sourced Writes",
12 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from the Level-2 cache"
13 },
14 {
15 "EventCode": "130",
16 "EventName": "DTLB1_MISSES",
17 "BriefDescription": "DTLB1 Misses",
18 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
19 },
20 {
21 "EventCode": "131",
22 "EventName": "ITLB1_MISSES",
23 "BriefDescription": "ITLB1 Misses",
24 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle a ITLB1 miss is in progress."
25 },
26 {
27 "EventCode": "133",
28 "EventName": "L2C_STORES_SENT",
29 "BriefDescription": "L2C Stores Sent",
30 "PublicDescription": "Incremented by one for every store sent to Level-2 cache"
31 },
32 {
33 "EventCode": "134",
34 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES",
35 "BriefDescription": "L1D Off-Book L3 Sourced Writes",
36 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Book Level-3 cache"
37 },
38 {
39 "EventCode": "135",
40 "EventName": "L1D_ONBOOK_L4_SOURCED_WRITES",
41 "BriefDescription": "L1D On-Book L4 Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an On Book Level-4 cache"
43 },
44 {
45 "EventCode": "136",
46 "EventName": "L1I_ONBOOK_L4_SOURCED_WRITES",
47 "BriefDescription": "L1I On-Book L4 Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an On Book Level-4 cache"
49 },
50 {
51 "EventCode": "137",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "138",
58 "EventName": "L1D_OFFBOOK_L4_SOURCED_WRITES",
59 "BriefDescription": "L1D Off-Book L4 Sourced Writes",
60 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
61 },
62 {
63 "EventCode": "139",
64 "EventName": "L1I_OFFBOOK_L4_SOURCED_WRITES",
65 "BriefDescription": "L1I Off-Book L4 Sourced Writes",
66 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
67 },
68 {
69 "EventCode": "140",
70 "EventName": "DTLB1_HPAGE_WRITES",
71 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
72 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
73 },
74 {
75 "EventCode": "141",
76 "EventName": "L1D_LMEM_SOURCED_WRITES",
77 "BriefDescription": "L1D Local Memory Sourced Writes",
78 "PublicDescription": "A directory write to the Level-1 D-Cache where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
79 },
80 {
81 "EventCode": "142",
82 "EventName": "L1I_LMEM_SOURCED_WRITES",
83 "BriefDescription": "L1I Local Memory Sourced Writes",
84 "PublicDescription": "A directory write to the Level-1 I-Cache where the installed cache line was sourced from memory that is attached to the same book as the Instruction cache (Local Memory)"
85 },
86 {
87 "EventCode": "143",
88 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES",
89 "BriefDescription": "L1I Off-Book L3 Sourced Writes",
90 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Book Level-3 cache"
91 },
92 {
93 "EventCode": "144",
94 "EventName": "DTLB1_WRITES",
95 "BriefDescription": "DTLB1 Writes",
96 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
97 },
98 {
99 "EventCode": "145",
100 "EventName": "ITLB1_WRITES",
101 "BriefDescription": "ITLB1 Writes",
102 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
103 },
104 {
105 "EventCode": "146",
106 "EventName": "TLB2_PTE_WRITES",
107 "BriefDescription": "TLB2 PTE Writes",
108 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
109 },
110 {
111 "EventCode": "147",
112 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
113 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
114 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
115 },
116 {
117 "EventCode": "148",
118 "EventName": "TLB2_CRSTE_WRITES",
119 "BriefDescription": "TLB2 CRSTE Writes",
120 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
121 },
122 {
123 "EventCode": "150",
124 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
125 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
126 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an On Chip Level-3 cache"
127 },
128 {
129 "EventCode": "152",
130 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES",
131 "BriefDescription": "L1D Off-Chip L3 Sourced Writes",
132 "PublicDescription": "A directory write to the Level-1 D-Cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache"
133 },
134 {
135 "EventCode": "153",
136 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
137 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
138 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an On Chip Level-3 cache"
139 },
140 {
141 "EventCode": "155",
142 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES",
143 "BriefDescription": "L1I Off-Chip L3 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 I-Cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache"
145 },
146]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json b/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json
new file mode 100644
index 000000000000..8bf16759ca53
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/basic.json
@@ -0,0 +1,74 @@
1[
2 {
3 "EventCode": "0",
4 "EventName": "CPU_CYCLES",
5 "BriefDescription": "CPU Cycles",
6 "PublicDescription": "Cycle Count"
7 },
8 {
9 "EventCode": "1",
10 "EventName": "INSTRUCTIONS",
11 "BriefDescription": "Instructions",
12 "PublicDescription": "Instruction Count"
13 },
14 {
15 "EventCode": "2",
16 "EventName": "L1I_DIR_WRITES",
17 "BriefDescription": "L1I Directory Writes",
18 "PublicDescription": "Level-1 I-Cache Directory Write Count"
19 },
20 {
21 "EventCode": "3",
22 "EventName": "L1I_PENALTY_CYCLES",
23 "BriefDescription": "L1I Penalty Cycles",
24 "PublicDescription": "Level-1 I-Cache Penalty Cycle Count"
25 },
26 {
27 "EventCode": "4",
28 "EventName": "L1D_DIR_WRITES",
29 "BriefDescription": "L1D Directory Writes",
30 "PublicDescription": "Level-1 D-Cache Directory Write Count"
31 },
32 {
33 "EventCode": "5",
34 "EventName": "L1D_PENALTY_CYCLES",
35 "BriefDescription": "L1D Penalty Cycles",
36 "PublicDescription": "Level-1 D-Cache Penalty Cycle Count"
37 },
38 {
39 "EventCode": "32",
40 "EventName": "PROBLEM_STATE_CPU_CYCLES",
41 "BriefDescription": "Problem-State CPU Cycles",
42 "PublicDescription": "Problem-State Cycle Count"
43 },
44 {
45 "EventCode": "33",
46 "EventName": "PROBLEM_STATE_INSTRUCTIONS",
47 "BriefDescription": "Problem-State Instructions",
48 "PublicDescription": "Problem-State Instruction Count"
49 },
50 {
51 "EventCode": "34",
52 "EventName": "PROBLEM_STATE_L1I_DIR_WRITES",
53 "BriefDescription": "Problem-State L1I Directory Writes",
54 "PublicDescription": "Problem-State Level-1 I-Cache Directory Write Count"
55 },
56 {
57 "EventCode": "35",
58 "EventName": "PROBLEM_STATE_L1I_PENALTY_CYCLES",
59 "BriefDescription": "Problem-State L1I Penalty Cycles",
60 "PublicDescription": "Problem-State Level-1 I-Cache Penalty Cycle Count"
61 },
62 {
63 "EventCode": "36",
64 "EventName": "PROBLEM_STATE_L1D_DIR_WRITES",
65 "BriefDescription": "Problem-State L1D Directory Writes",
66 "PublicDescription": "Problem-State Level-1 D-Cache Directory Write Count"
67 },
68 {
69 "EventCode": "37",
70 "EventName": "PROBLEM_STATE_L1D_PENALTY_CYCLES",
71 "BriefDescription": "Problem-State L1D Penalty Cycles",
72 "PublicDescription": "Problem-State Level-1 D-Cache Penalty Cycle Count"
73 },
74]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json b/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json
new file mode 100644
index 000000000000..7e5b72492141
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/crypto.json
@@ -0,0 +1,98 @@
1[
2 {
3 "EventCode": "64",
4 "EventName": "PRNG_FUNCTIONS",
5 "BriefDescription": "PRNG Functions",
6 "PublicDescription": "Total number of the PRNG functions issued by the CPU"
7 },
8 {
9 "EventCode": "65",
10 "EventName": "PRNG_CYCLES",
11 "BriefDescription": "PRNG Cycles",
12 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing PRNG functions issued by the CPU"
13 },
14 {
15 "EventCode": "66",
16 "EventName": "PRNG_BLOCKED_FUNCTIONS",
17 "BriefDescription": "PRNG Blocked Functions",
18 "PublicDescription": "Total number of the PRNG functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
19 },
20 {
21 "EventCode": "67",
22 "EventName": "PRNG_BLOCKED_CYCLES",
23 "BriefDescription": "PRNG Blocked Cycles",
24 "PublicDescription": "Total number of CPU cycles blocked for the PRNG functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
25 },
26 {
27 "EventCode": "68",
28 "EventName": "SHA_FUNCTIONS",
29 "BriefDescription": "SHA Functions",
30 "PublicDescription": "Total number of SHA functions issued by the CPU"
31 },
32 {
33 "EventCode": "69",
34 "EventName": "SHA_CYCLES",
35 "BriefDescription": "SHA Cycles",
36 "PublicDescription": "Total number of CPU cycles when the SHA coprocessor is busy performing the SHA functions issued by the CPU"
37 },
38 {
39 "EventCode": "70",
40 "EventName": "SHA_BLOCKED_FUNCTIONS",
41 "BriefDescription": "SHA Blocked Functions",
42 "PublicDescription": "Total number of the SHA functions that are issued by the CPU and are blocked because the SHA coprocessor is busy performing a function issued by another CPU"
43 },
44 {
45 "EventCode": "71",
46 "EventName": "SHA_BLOCKED_CYCLES",
47 "BriefDescription": "SHA Bloced Cycles",
48 "PublicDescription": "Total number of CPU cycles blocked for the SHA functions issued by the CPU because the SHA coprocessor is busy performing a function issued by another CPU"
49 },
50 {
51 "EventCode": "72",
52 "EventName": "DEA_FUNCTIONS",
53 "BriefDescription": "DEA Functions",
54 "PublicDescription": "Total number of the DEA functions issued by the CPU"
55 },
56 {
57 "EventCode": "73",
58 "EventName": "DEA_CYCLES",
59 "BriefDescription": "DEA Cycles",
60 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the DEA functions issued by the CPU"
61 },
62 {
63 "EventCode": "74",
64 "EventName": "DEA_BLOCKED_FUNCTIONS",
65 "BriefDescription": "DEA Blocked Functions",
66 "PublicDescription": "Total number of the DEA functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
67 },
68 {
69 "EventCode": "75",
70 "EventName": "DEA_BLOCKED_CYCLES",
71 "BriefDescription": "DEA Blocked Cycles",
72 "PublicDescription": "Total number of CPU cycles blocked for the DEA functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
73 },
74 {
75 "EventCode": "76",
76 "EventName": "AES_FUNCTIONS",
77 "BriefDescription": "AES Functions",
78 "PublicDescription": "Total number of AES functions issued by the CPU"
79 },
80 {
81 "EventCode": "77",
82 "EventName": "AES_CYCLES",
83 "BriefDescription": "AES Cycles",
84 "PublicDescription": "Total number of CPU cycles when the DEA/AES coprocessor is busy performing the AES functions issued by the CPU"
85 },
86 {
87 "EventCode": "78",
88 "EventName": "AES_BLOCKED_FUNCTIONS",
89 "BriefDescription": "AES Blocked Functions",
90 "PublicDescription": "Total number of AES functions that are issued by the CPU and are blocked because the DEA/AES coprocessor is busy performing a function issued by another CPU"
91 },
92 {
93 "EventCode": "79",
94 "EventName": "AES_BLOCKED_CYCLES",
95 "BriefDescription": "AES Blocked Cycles",
96 "PublicDescription": "Total number of CPU cycles blocked for the AES functions issued by the CPU because the DEA/AES coprocessor is busy performing a function issued by another CPU"
97 },
98]
diff --git a/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json b/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json
new file mode 100644
index 000000000000..8682126aabb2
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/cf_zec12/extended.json
@@ -0,0 +1,212 @@
1[
2 {
3 "EventCode": "128",
4 "EventName": "DTLB1_MISSES",
5 "BriefDescription": "DTLB1 Misses",
6 "PublicDescription": "Level-1 Data TLB miss in progress. Incremented by one for every cycle a DTLB1 miss is in progress."
7 },
8 {
9 "EventCode": "129",
10 "EventName": "ITLB1_MISSES",
11 "BriefDescription": "ITLB1 Misses",
12 "PublicDescription": "Level-1 Instruction TLB miss in progress. Incremented by one for every cycle a ITLB1 miss is in progress."
13 },
14 {
15 "EventCode": "130",
16 "EventName": "L1D_L2I_SOURCED_WRITES",
17 "BriefDescription": "L1D L2I Sourced Writes",
18 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
19 },
20 {
21 "EventCode": "131",
22 "EventName": "L1I_L2I_SOURCED_WRITES",
23 "BriefDescription": "L1I L2I Sourced Writes",
24 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from the Level-2 Instruction cache"
25 },
26 {
27 "EventCode": "132",
28 "EventName": "L1D_L2D_SOURCED_WRITES",
29 "BriefDescription": "L1D L2D Sourced Writes",
30 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from the Level-2 Data cache"
31 },
32 {
33 "EventCode": "133",
34 "EventName": "DTLB1_WRITES",
35 "BriefDescription": "DTLB1 Writes",
36 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer"
37 },
38 {
39 "EventCode": "135",
40 "EventName": "L1D_LMEM_SOURCED_WRITES",
41 "BriefDescription": "L1D Local Memory Sourced Writes",
42 "PublicDescription": "A directory write to the Level-1 Data cache where the installed cache line was sourced from memory that is attached to the same book as the Data cache (Local Memory)"
43 },
44 {
45 "EventCode": "137",
46 "EventName": "L1I_LMEM_SOURCED_WRITES",
47 "BriefDescription": "L1I Local Memory Sourced Writes",
48 "PublicDescription": "A directory write to the Level-1 Instruction cache where the installed cache line was sourced from memory that is attached to the same book as the Instruction cache (Local Memory)"
49 },
50 {
51 "EventCode": "138",
52 "EventName": "L1D_RO_EXCL_WRITES",
53 "BriefDescription": "L1D Read-only Exclusive Writes",
54 "PublicDescription": "A directory write to the Level-1 D-Cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
55 },
56 {
57 "EventCode": "139",
58 "EventName": "DTLB1_HPAGE_WRITES",
59 "BriefDescription": "DTLB1 One-Megabyte Page Writes",
60 "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a one-megabyte page"
61 },
62 {
63 "EventCode": "140",
64 "EventName": "ITLB1_WRITES",
65 "BriefDescription": "ITLB1 Writes",
66 "PublicDescription": "A translation entry has been written to the Level-1 Instruction Translation Lookaside Buffer"
67 },
68 {
69 "EventCode": "141",
70 "EventName": "TLB2_PTE_WRITES",
71 "BriefDescription": "TLB2 PTE Writes",
72 "PublicDescription": "A translation entry has been written to the Level-2 TLB Page Table Entry arrays"
73 },
74 {
75 "EventCode": "142",
76 "EventName": "TLB2_CRSTE_HPAGE_WRITES",
77 "BriefDescription": "TLB2 CRSTE One-Megabyte Page Writes",
78 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays for a one-megabyte large page translation"
79 },
80 {
81 "EventCode": "143",
82 "EventName": "TLB2_CRSTE_WRITES",
83 "BriefDescription": "TLB2 CRSTE Writes",
84 "PublicDescription": "A translation entry has been written to the Level-2 TLB Common Region Segment Table Entry arrays"
85 },
86 {
87 "EventCode": "144",
88 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES",
89 "BriefDescription": "L1D On-Chip L3 Sourced Writes",
90 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On Chip Level-3 cache without intervention"
91 },
92 {
93 "EventCode": "145",
94 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES",
95 "BriefDescription": "L1D Off-Chip L3 Sourced Writes",
96 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache without intervention"
97 },
98 {
99 "EventCode": "146",
100 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES",
101 "BriefDescription": "L1D Off-Book L3 Sourced Writes",
102 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-3 cache without intervention"
103 },
104 {
105 "EventCode": "147",
106 "EventName": "L1D_ONBOOK_L4_SOURCED_WRITES",
107 "BriefDescription": "L1D On-Book L4 Sourced Writes",
108 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an On Book Level-4 cache"
109 },
110 {
111 "EventCode": "148",
112 "EventName": "L1D_OFFBOOK_L4_SOURCED_WRITES",
113 "BriefDescription": "L1D Off-Book L4 Sourced Writes",
114 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
115 },
116 {
117 "EventCode": "149",
118 "EventName": "TX_NC_TEND",
119 "BriefDescription": "Completed TEND instructions in non-constrained TX mode",
120 "PublicDescription": "A TEND instruction has completed in a nonconstrained transactional-execution mode"
121 },
122 {
123 "EventCode": "150",
124 "EventName": "L1D_ONCHIP_L3_SOURCED_WRITES_IV",
125 "BriefDescription": "L1D On-Chip L3 Sourced Writes with Intervention",
126 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from a On Chip Level-3 cache with intervention"
127 },
128 {
129 "EventCode": "151",
130 "EventName": "L1D_OFFCHIP_L3_SOURCED_WRITES_IV",
131 "BriefDescription": "L1D Off-Chip L3 Sourced Writes with Intervention",
132 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache with intervention"
133 },
134 {
135 "EventCode": "152",
136 "EventName": "L1D_OFFBOOK_L3_SOURCED_WRITES_IV",
137 "BriefDescription": "L1D Off-Book L3 Sourced Writes with Intervention",
138 "PublicDescription": "A directory write to the Level-1 Data cache directory where the returned cache line was sourced from an Off Book Level-3 cache with intervention"
139 },
140 {
141 "EventCode": "153",
142 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES",
143 "BriefDescription": "L1I On-Chip L3 Sourced Writes",
144 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache without intervention"
145 },
146 {
147 "EventCode": "154",
148 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES",
149 "BriefDescription": "L1I Off-Chip L3 Sourced Writes",
150 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache without intervention"
151 },
152 {
153 "EventCode": "155",
154 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES",
155 "BriefDescription": "L1I Off-Book L3 Sourced Writes",
156 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-3 cache without intervention"
157 },
158 {
159 "EventCode": "156",
160 "EventName": "L1I_ONBOOK_L4_SOURCED_WRITES",
161 "BriefDescription": "L1I On-Book L4 Sourced Writes",
162 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Book Level-4 cache"
163 },
164 {
165 "EventCode": "157",
166 "EventName": "L1I_OFFBOOK_L4_SOURCED_WRITES",
167 "BriefDescription": "L1I Off-Book L4 Sourced Writes",
168 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-4 cache"
169 },
170 {
171 "EventCode": "158",
172 "EventName": "TX_C_TEND",
173 "BriefDescription": "Completed TEND instructions in constrained TX mode",
174 "PublicDescription": "A TEND instruction has completed in a constrained transactional-execution mode"
175 },
176 {
177 "EventCode": "159",
178 "EventName": "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
179 "BriefDescription": "L1I On-Chip L3 Sourced Writes with Intervention",
180 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an On Chip Level-3 cache with intervention"
181 },
182 {
183 "EventCode": "160",
184 "EventName": "L1I_OFFCHIP_L3_SOURCED_WRITES_IV",
185 "BriefDescription": "L1I Off-Chip L3 Sourced Writes with Intervention",
186 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Chip/On Book Level-3 cache with intervention"
187 },
188 {
189 "EventCode": "161",
190 "EventName": "L1I_OFFBOOK_L3_SOURCED_WRITES_IV",
191 "BriefDescription": "L1I Off-Book L3 Sourced Writes with Intervention",
192 "PublicDescription": "A directory write to the Level-1 Instruction cache directory where the returned cache line was sourced from an Off Book Level-3 cache with intervention"
193 },
194 {
195 "EventCode": "177",
196 "EventName": "TX_NC_TABORT",
197 "BriefDescription": "Aborted transactions in non-constrained TX mode",
198 "PublicDescription": "A transaction abort has occurred in a nonconstrained transactional-execution mode"
199 },
200 {
201 "EventCode": "178",
202 "EventName": "TX_C_TABORT_NO_SPECIAL",
203 "BriefDescription": "Aborted transactions in constrained TX mode not using special completion logic",
204 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is not using any special logic to allow the transaction to complete"
205 },
206 {
207 "EventCode": "179",
208 "EventName": "TX_C_TABORT_SPECIAL",
209 "BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
210 "PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
211 },
212]
diff --git a/tools/perf/pmu-events/arch/s390/mapfile.csv b/tools/perf/pmu-events/arch/s390/mapfile.csv
new file mode 100644
index 000000000000..ca7682748a4b
--- /dev/null
+++ b/tools/perf/pmu-events/arch/s390/mapfile.csv
@@ -0,0 +1,6 @@
1Family-model,Version,Filename,EventType
2209[78],1,cf_z10,core
3281[78],1,cf_z196,core
4282[78],1,cf_zec12,core
5296[45],1,cf_z13,core
63906,3,cf_z14,core
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
index b578aa26e375..db3a594ee1e4 100644
--- a/tools/perf/pmu-events/jevents.c
+++ b/tools/perf/pmu-events/jevents.c
@@ -39,11 +39,13 @@
39#include <unistd.h> 39#include <unistd.h>
40#include <stdarg.h> 40#include <stdarg.h>
41#include <libgen.h> 41#include <libgen.h>
42#include <limits.h>
42#include <dirent.h> 43#include <dirent.h>
43#include <sys/time.h> /* getrlimit */ 44#include <sys/time.h> /* getrlimit */
44#include <sys/resource.h> /* getrlimit */ 45#include <sys/resource.h> /* getrlimit */
45#include <ftw.h> 46#include <ftw.h>
46#include <sys/stat.h> 47#include <sys/stat.h>
48#include <linux/list.h>
47#include "jsmn.h" 49#include "jsmn.h"
48#include "json.h" 50#include "json.h"
49#include "jevents.h" 51#include "jevents.h"
@@ -249,31 +251,25 @@ static const char *field_to_perf(struct map *table, char *map, jsmntok_t *val)
249 jsmntok_t *loc = (t); \ 251 jsmntok_t *loc = (t); \
250 if (!(t)->start && (t) > tokens) \ 252 if (!(t)->start && (t) > tokens) \
251 loc = (t) - 1; \ 253 loc = (t) - 1; \
252 pr_err("%s:%d: " m ", got %s\n", fn, \ 254 pr_err("%s:%d: " m ", got %s\n", fn, \
253 json_line(map, loc), \ 255 json_line(map, loc), \
254 json_name(t)); \ 256 json_name(t)); \
257 err = -EIO; \
255 goto out_free; \ 258 goto out_free; \
256} } while (0) 259} } while (0)
257 260
258#define TOPIC_DEPTH 256 261static char *topic;
259static char *topic_array[TOPIC_DEPTH];
260static int topic_level;
261 262
262static char *get_topic(void) 263static char *get_topic(void)
263{ 264{
264 char *tp_old, *tp = NULL; 265 char *tp;
265 int i; 266 int i;
266 267
267 for (i = 0; i < topic_level + 1; i++) { 268 /* tp is free'd in process_one_file() */
268 int n; 269 i = asprintf(&tp, "%s", topic);
269 270 if (i < 0) {
270 tp_old = tp; 271 pr_info("%s: asprintf() error %s\n", prog);
271 n = asprintf(&tp, "%s%s", tp ?: "", topic_array[i]); 272 return NULL;
272 if (n < 0) {
273 pr_info("%s: asprintf() error %s\n", prog);
274 return NULL;
275 }
276 free(tp_old);
277 } 273 }
278 274
279 for (i = 0; i < (int) strlen(tp); i++) { 275 for (i = 0; i < (int) strlen(tp); i++) {
@@ -290,25 +286,15 @@ static char *get_topic(void)
290 return tp; 286 return tp;
291} 287}
292 288
293static int add_topic(int level, char *bname) 289static int add_topic(char *bname)
294{ 290{
295 char *topic; 291 free(topic);
296
297 level -= 2;
298
299 if (level >= TOPIC_DEPTH)
300 return -EINVAL;
301
302 topic = strdup(bname); 292 topic = strdup(bname);
303 if (!topic) { 293 if (!topic) {
304 pr_info("%s: strdup() error %s for file %s\n", prog, 294 pr_info("%s: strdup() error %s for file %s\n", prog,
305 strerror(errno), bname); 295 strerror(errno), bname);
306 return -ENOMEM; 296 return -ENOMEM;
307 } 297 }
308
309 free(topic_array[topic_level]);
310 topic_array[topic_level] = topic;
311 topic_level = level;
312 return 0; 298 return 0;
313} 299}
314 300
@@ -366,6 +352,81 @@ static int print_events_table_entry(void *data, char *name, char *event,
366 return 0; 352 return 0;
367} 353}
368 354
355struct event_struct {
356 struct list_head list;
357 char *name;
358 char *event;
359 char *desc;
360 char *long_desc;
361 char *pmu;
362 char *unit;
363 char *perpkg;
364 char *metric_expr;
365 char *metric_name;
366 char *metric_group;
367};
368
369#define ADD_EVENT_FIELD(field) do { if (field) { \
370 es->field = strdup(field); \
371 if (!es->field) \
372 goto out_free; \
373} } while (0)
374
375#define FREE_EVENT_FIELD(field) free(es->field)
376
377#define TRY_FIXUP_FIELD(field) do { if (es->field && !*field) {\
378 *field = strdup(es->field); \
379 if (!*field) \
380 return -ENOMEM; \
381} } while (0)
382
383#define FOR_ALL_EVENT_STRUCT_FIELDS(op) do { \
384 op(name); \
385 op(event); \
386 op(desc); \
387 op(long_desc); \
388 op(pmu); \
389 op(unit); \
390 op(perpkg); \
391 op(metric_expr); \
392 op(metric_name); \
393 op(metric_group); \
394} while (0)
395
396static LIST_HEAD(arch_std_events);
397
398static void free_arch_std_events(void)
399{
400 struct event_struct *es, *next;
401
402 list_for_each_entry_safe(es, next, &arch_std_events, list) {
403 FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
404 list_del(&es->list);
405 free(es);
406 }
407}
408
409static int save_arch_std_events(void *data, char *name, char *event,
410 char *desc, char *long_desc, char *pmu,
411 char *unit, char *perpkg, char *metric_expr,
412 char *metric_name, char *metric_group)
413{
414 struct event_struct *es;
415 struct stat *sb = data;
416
417 es = malloc(sizeof(*es));
418 if (!es)
419 return -ENOMEM;
420 memset(es, 0, sizeof(*es));
421 FOR_ALL_EVENT_STRUCT_FIELDS(ADD_EVENT_FIELD);
422 list_add_tail(&es->list, &arch_std_events);
423 return 0;
424out_free:
425 FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD);
426 free(es);
427 return -ENOMEM;
428}
429
369static void print_events_table_suffix(FILE *outfp) 430static void print_events_table_suffix(FILE *outfp)
370{ 431{
371 fprintf(outfp, "{\n"); 432 fprintf(outfp, "{\n");
@@ -407,6 +468,32 @@ static char *real_event(const char *name, char *event)
407 return event; 468 return event;
408} 469}
409 470
471static int
472try_fixup(const char *fn, char *arch_std, char **event, char **desc,
473 char **name, char **long_desc, char **pmu, char **filter,
474 char **perpkg, char **unit, char **metric_expr, char **metric_name,
475 char **metric_group, unsigned long long eventcode)
476{
477 /* try to find matching event from arch standard values */
478 struct event_struct *es;
479
480 list_for_each_entry(es, &arch_std_events, list) {
481 if (!strcmp(arch_std, es->name)) {
482 if (!eventcode && es->event) {
483 /* allow EventCode to be overridden */
484 free(*event);
485 *event = NULL;
486 }
487 FOR_ALL_EVENT_STRUCT_FIELDS(TRY_FIXUP_FIELD);
488 return 0;
489 }
490 }
491
492 pr_err("%s: could not find matching %s for %s\n",
493 prog, arch_std, fn);
494 return -1;
495}
496
410/* Call func with each event in the json file */ 497/* Call func with each event in the json file */
411int json_events(const char *fn, 498int json_events(const char *fn,
412 int (*func)(void *data, char *name, char *event, char *desc, 499 int (*func)(void *data, char *name, char *event, char *desc,
@@ -416,7 +503,7 @@ int json_events(const char *fn,
416 char *metric_name, char *metric_group), 503 char *metric_name, char *metric_group),
417 void *data) 504 void *data)
418{ 505{
419 int err = -EIO; 506 int err;
420 size_t size; 507 size_t size;
421 jsmntok_t *tokens, *tok; 508 jsmntok_t *tokens, *tok;
422 int i, j, len; 509 int i, j, len;
@@ -442,6 +529,7 @@ int json_events(const char *fn,
442 char *metric_expr = NULL; 529 char *metric_expr = NULL;
443 char *metric_name = NULL; 530 char *metric_name = NULL;
444 char *metric_group = NULL; 531 char *metric_group = NULL;
532 char *arch_std = NULL;
445 unsigned long long eventcode = 0; 533 unsigned long long eventcode = 0;
446 struct msrmap *msr = NULL; 534 struct msrmap *msr = NULL;
447 jsmntok_t *msrval = NULL; 535 jsmntok_t *msrval = NULL;
@@ -527,6 +615,10 @@ int json_events(const char *fn,
527 addfield(map, &metric_expr, "", "", val); 615 addfield(map, &metric_expr, "", "", val);
528 for (s = metric_expr; *s; s++) 616 for (s = metric_expr; *s; s++)
529 *s = tolower(*s); 617 *s = tolower(*s);
618 } else if (json_streq(map, field, "ArchStdEvent")) {
619 addfield(map, &arch_std, "", "", val);
620 for (s = arch_std; *s; s++)
621 *s = tolower(*s);
530 } 622 }
531 /* ignore unknown fields */ 623 /* ignore unknown fields */
532 } 624 }
@@ -551,8 +643,21 @@ int json_events(const char *fn,
551 if (name) 643 if (name)
552 fixname(name); 644 fixname(name);
553 645
646 if (arch_std) {
647 /*
648 * An arch standard event is referenced, so try to
649 * fixup any unassigned values.
650 */
651 err = try_fixup(fn, arch_std, &event, &desc, &name,
652 &long_desc, &pmu, &filter, &perpkg,
653 &unit, &metric_expr, &metric_name,
654 &metric_group, eventcode);
655 if (err)
656 goto free_strings;
657 }
554 err = func(data, name, real_event(name, event), desc, long_desc, 658 err = func(data, name, real_event(name, event), desc, long_desc,
555 pmu, unit, perpkg, metric_expr, metric_name, metric_group); 659 pmu, unit, perpkg, metric_expr, metric_name, metric_group);
660free_strings:
556 free(event); 661 free(event);
557 free(desc); 662 free(desc);
558 free(name); 663 free(name);
@@ -565,6 +670,8 @@ int json_events(const char *fn,
565 free(metric_expr); 670 free(metric_expr);
566 free(metric_name); 671 free(metric_name);
567 free(metric_group); 672 free(metric_group);
673 free(arch_std);
674
568 if (err) 675 if (err)
569 break; 676 break;
570 tok += j; 677 tok += j;
@@ -588,7 +695,7 @@ static char *file_name_to_table_name(char *fname)
588 * Derive rest of table name from basename of the JSON file, 695 * Derive rest of table name from basename of the JSON file,
589 * replacing hyphens and stripping out .json suffix. 696 * replacing hyphens and stripping out .json suffix.
590 */ 697 */
591 n = asprintf(&tblname, "pme_%s", basename(fname)); 698 n = asprintf(&tblname, "pme_%s", fname);
592 if (n < 0) { 699 if (n < 0) {
593 pr_info("%s: asprintf() error %s for file %s\n", prog, 700 pr_info("%s: asprintf() error %s for file %s\n", prog,
594 strerror(errno), fname); 701 strerror(errno), fname);
@@ -598,7 +705,7 @@ static char *file_name_to_table_name(char *fname)
598 for (i = 0; i < strlen(tblname); i++) { 705 for (i = 0; i < strlen(tblname); i++) {
599 c = tblname[i]; 706 c = tblname[i];
600 707
601 if (c == '-') 708 if (c == '-' || c == '/')
602 tblname[i] = '_'; 709 tblname[i] = '_';
603 else if (c == '.') { 710 else if (c == '.') {
604 tblname[i] = '\0'; 711 tblname[i] = '\0';
@@ -755,25 +862,106 @@ static int get_maxfds(void)
755static FILE *eventsfp; 862static FILE *eventsfp;
756static char *mapfile; 863static char *mapfile;
757 864
865static int is_leaf_dir(const char *fpath)
866{
867 DIR *d;
868 struct dirent *dir;
869 int res = 1;
870
871 d = opendir(fpath);
872 if (!d)
873 return 0;
874
875 while ((dir = readdir(d)) != NULL) {
876 if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
877 continue;
878
879 if (dir->d_type == DT_DIR) {
880 res = 0;
881 break;
882 } else if (dir->d_type == DT_UNKNOWN) {
883 char path[PATH_MAX];
884 struct stat st;
885
886 sprintf(path, "%s/%s", fpath, dir->d_name);
887 if (stat(path, &st))
888 break;
889
890 if (S_ISDIR(st.st_mode)) {
891 res = 0;
892 break;
893 }
894 }
895 }
896
897 closedir(d);
898
899 return res;
900}
901
902static int is_json_file(const char *name)
903{
904 const char *suffix;
905
906 if (strlen(name) < 5)
907 return 0;
908
909 suffix = name + strlen(name) - 5;
910
911 if (strncmp(suffix, ".json", 5) == 0)
912 return 1;
913 return 0;
914}
915
916static int preprocess_arch_std_files(const char *fpath, const struct stat *sb,
917 int typeflag, struct FTW *ftwbuf)
918{
919 int level = ftwbuf->level;
920 int is_file = typeflag == FTW_F;
921
922 if (level == 1 && is_file && is_json_file(fpath))
923 return json_events(fpath, save_arch_std_events, (void *)sb);
924
925 return 0;
926}
927
758static int process_one_file(const char *fpath, const struct stat *sb, 928static int process_one_file(const char *fpath, const struct stat *sb,
759 int typeflag, struct FTW *ftwbuf) 929 int typeflag, struct FTW *ftwbuf)
760{ 930{
761 char *tblname, *bname = (char *) fpath + ftwbuf->base; 931 char *tblname, *bname;
762 int is_dir = typeflag == FTW_D; 932 int is_dir = typeflag == FTW_D;
763 int is_file = typeflag == FTW_F; 933 int is_file = typeflag == FTW_F;
764 int level = ftwbuf->level; 934 int level = ftwbuf->level;
765 int err = 0; 935 int err = 0;
766 936
937 if (level == 2 && is_dir) {
938 /*
939 * For level 2 directory, bname will include parent name,
940 * like vendor/platform. So search back from platform dir
941 * to find this.
942 */
943 bname = (char *) fpath + ftwbuf->base - 2;
944 for (;;) {
945 if (*bname == '/')
946 break;
947 bname--;
948 }
949 bname++;
950 } else
951 bname = (char *) fpath + ftwbuf->base;
952
767 pr_debug("%s %d %7jd %-20s %s\n", 953 pr_debug("%s %d %7jd %-20s %s\n",
768 is_file ? "f" : is_dir ? "d" : "x", 954 is_file ? "f" : is_dir ? "d" : "x",
769 level, sb->st_size, bname, fpath); 955 level, sb->st_size, bname, fpath);
770 956
771 /* base dir */ 957 /* base dir or too deep */
772 if (level == 0) 958 if (level == 0 || level > 3)
773 return 0; 959 return 0;
774 960
961
775 /* model directory, reset topic */ 962 /* model directory, reset topic */
776 if (level == 1 && is_dir) { 963 if ((level == 1 && is_dir && is_leaf_dir(fpath)) ||
964 (level == 2 && is_dir)) {
777 if (close_table) 965 if (close_table)
778 print_events_table_suffix(eventsfp); 966 print_events_table_suffix(eventsfp);
779 967
@@ -798,16 +986,10 @@ static int process_one_file(const char *fpath, const struct stat *sb,
798 * after processing all JSON files (so we can write out the 986 * after processing all JSON files (so we can write out the
799 * mapping table after all PMU events tables). 987 * mapping table after all PMU events tables).
800 * 988 *
801 * TODO: Allow for multiple mapfiles? Punt for now.
802 */ 989 */
803 if (level == 1 && is_file) { 990 if (level == 1 && is_file) {
804 if (!strncmp(bname, "mapfile.csv", 11)) { 991 if (!strcmp(bname, "mapfile.csv")) {
805 if (mapfile) { 992 mapfile = strdup(fpath);
806 pr_info("%s: Many mapfiles? Using %s, ignoring %s\n",
807 prog, mapfile, fpath);
808 } else {
809 mapfile = strdup(fpath);
810 }
811 return 0; 993 return 0;
812 } 994 }
813 995
@@ -820,16 +1002,14 @@ static int process_one_file(const char *fpath, const struct stat *sb,
820 * ignore it. It could be a readme.txt for instance. 1002 * ignore it. It could be a readme.txt for instance.
821 */ 1003 */
822 if (is_file) { 1004 if (is_file) {
823 char *suffix = bname + strlen(bname) - 5; 1005 if (!is_json_file(bname)) {
824
825 if (strncmp(suffix, ".json", 5)) {
826 pr_info("%s: Ignoring file without .json suffix %s\n", prog, 1006 pr_info("%s: Ignoring file without .json suffix %s\n", prog,
827 fpath); 1007 fpath);
828 return 0; 1008 return 0;
829 } 1009 }
830 } 1010 }
831 1011
832 if (level > 1 && add_topic(level, bname)) 1012 if (level > 1 && add_topic(bname))
833 return -ENOMEM; 1013 return -ENOMEM;
834 1014
835 /* 1015 /*
@@ -928,12 +1108,26 @@ int main(int argc, char *argv[])
928 1108
929 maxfds = get_maxfds(); 1109 maxfds = get_maxfds();
930 mapfile = NULL; 1110 mapfile = NULL;
1111 rc = nftw(ldirname, preprocess_arch_std_files, maxfds, 0);
1112 if (rc && verbose) {
1113 pr_info("%s: Error preprocessing arch standard files %s\n",
1114 prog, ldirname);
1115 goto empty_map;
1116 } else if (rc < 0) {
1117 /* Make build fail */
1118 free_arch_std_events();
1119 return 1;
1120 } else if (rc) {
1121 goto empty_map;
1122 }
1123
931 rc = nftw(ldirname, process_one_file, maxfds, 0); 1124 rc = nftw(ldirname, process_one_file, maxfds, 0);
932 if (rc && verbose) { 1125 if (rc && verbose) {
933 pr_info("%s: Error walking file tree %s\n", prog, ldirname); 1126 pr_info("%s: Error walking file tree %s\n", prog, ldirname);
934 goto empty_map; 1127 goto empty_map;
935 } else if (rc < 0) { 1128 } else if (rc < 0) {
936 /* Make build fail */ 1129 /* Make build fail */
1130 free_arch_std_events();
937 return 1; 1131 return 1;
938 } else if (rc) { 1132 } else if (rc) {
939 goto empty_map; 1133 goto empty_map;
@@ -958,5 +1152,6 @@ int main(int argc, char *argv[])
958empty_map: 1152empty_map:
959 fclose(eventsfp); 1153 fclose(eventsfp);
960 create_empty_mapping(output_file); 1154 create_empty_mapping(output_file);
1155 free_arch_std_events();
961 return 0; 1156 return 0;
962} 1157}
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
index c235c22b107a..0a29c5c3079f 100755
--- a/tools/perf/python/twatch.py
+++ b/tools/perf/python/twatch.py
@@ -42,10 +42,10 @@ def main(context_switch = 0, thread = -1):
42 event = evlist.read_on_cpu(cpu) 42 event = evlist.read_on_cpu(cpu)
43 if not event: 43 if not event:
44 continue 44 continue
45 print "cpu: %2d, pid: %4d, tid: %4d" % (event.sample_cpu, 45 print("cpu: {0}, pid: {1}, tid: {2} {3}".format(event.sample_cpu,
46 event.sample_pid, 46 event.sample_pid,
47 event.sample_tid), 47 event.sample_tid,
48 print event 48 event))
49 49
50if __name__ == '__main__': 50if __name__ == '__main__':
51 """ 51 """
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index fcd1dd667906..1a0d27757eec 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -23,7 +23,17 @@
23#include "../../../perf.h" 23#include "../../../perf.h"
24#include "../../../util/trace-event.h" 24#include "../../../util/trace-event.h"
25 25
26#if PY_MAJOR_VERSION < 3
27#define _PyCapsule_GetPointer(arg1, arg2) \
28 PyCObject_AsVoidPtr(arg1)
29
26PyMODINIT_FUNC initperf_trace_context(void); 30PyMODINIT_FUNC initperf_trace_context(void);
31#else
32#define _PyCapsule_GetPointer(arg1, arg2) \
33 PyCapsule_GetPointer((arg1), (arg2))
34
35PyMODINIT_FUNC PyInit_perf_trace_context(void);
36#endif
27 37
28static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) 38static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
29{ 39{
@@ -34,7 +44,7 @@ static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
34 if (!PyArg_ParseTuple(args, "O", &context)) 44 if (!PyArg_ParseTuple(args, "O", &context))
35 return NULL; 45 return NULL;
36 46
37 scripting_context = PyCObject_AsVoidPtr(context); 47 scripting_context = _PyCapsule_GetPointer(context, NULL);
38 retval = common_pc(scripting_context); 48 retval = common_pc(scripting_context);
39 49
40 return Py_BuildValue("i", retval); 50 return Py_BuildValue("i", retval);
@@ -50,7 +60,7 @@ static PyObject *perf_trace_context_common_flags(PyObject *obj,
50 if (!PyArg_ParseTuple(args, "O", &context)) 60 if (!PyArg_ParseTuple(args, "O", &context))
51 return NULL; 61 return NULL;
52 62
53 scripting_context = PyCObject_AsVoidPtr(context); 63 scripting_context = _PyCapsule_GetPointer(context, NULL);
54 retval = common_flags(scripting_context); 64 retval = common_flags(scripting_context);
55 65
56 return Py_BuildValue("i", retval); 66 return Py_BuildValue("i", retval);
@@ -66,7 +76,7 @@ static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
66 if (!PyArg_ParseTuple(args, "O", &context)) 76 if (!PyArg_ParseTuple(args, "O", &context))
67 return NULL; 77 return NULL;
68 78
69 scripting_context = PyCObject_AsVoidPtr(context); 79 scripting_context = _PyCapsule_GetPointer(context, NULL);
70 retval = common_lock_depth(scripting_context); 80 retval = common_lock_depth(scripting_context);
71 81
72 return Py_BuildValue("i", retval); 82 return Py_BuildValue("i", retval);
@@ -82,7 +92,25 @@ static PyMethodDef ContextMethods[] = {
82 { NULL, NULL, 0, NULL} 92 { NULL, NULL, 0, NULL}
83}; 93};
84 94
95#if PY_MAJOR_VERSION < 3
85PyMODINIT_FUNC initperf_trace_context(void) 96PyMODINIT_FUNC initperf_trace_context(void)
86{ 97{
87 (void) Py_InitModule("perf_trace_context", ContextMethods); 98 (void) Py_InitModule("perf_trace_context", ContextMethods);
88} 99}
100#else
101PyMODINIT_FUNC PyInit_perf_trace_context(void)
102{
103 static struct PyModuleDef moduledef = {
104 PyModuleDef_HEAD_INIT,
105 "perf_trace_context", /* m_name */
106 "", /* m_doc */
107 -1, /* m_size */
108 ContextMethods, /* m_methods */
109 NULL, /* m_reload */
110 NULL, /* m_traverse */
111 NULL, /* m_clear */
112 NULL, /* m_free */
113 };
114 return PyModule_Create(&moduledef);
115}
116#endif
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 87bf3edb037c..6c108fa79ae3 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -20,6 +20,7 @@ perf-y += hists_cumulate.o
20perf-y += python-use.o 20perf-y += python-use.o
21perf-y += bp_signal.o 21perf-y += bp_signal.o
22perf-y += bp_signal_overflow.o 22perf-y += bp_signal_overflow.o
23perf-y += bp_account.o
23perf-y += task-exit.o 24perf-y += task-exit.o
24perf-y += sw-clock.o 25perf-y += sw-clock.o
25perf-y += mmap-thread-lookup.o 26perf-y += mmap-thread-lookup.o
@@ -47,6 +48,7 @@ perf-y += bitmap.o
47perf-y += perf-hooks.o 48perf-y += perf-hooks.o
48perf-y += clang.o 49perf-y += clang.o
49perf-y += unit_number__scnprintf.o 50perf-y += unit_number__scnprintf.o
51perf-y += mem2node.o
50 52
51$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 53$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
52 $(call rule_mkdir) 54 $(call rule_mkdir)
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
index 97f64ad7fa08..05dfe11c2f9e 100644
--- a/tools/perf/tests/attr.c
+++ b/tools/perf/tests/attr.c
@@ -170,8 +170,8 @@ static int run_dir(const char *d, const char *perf)
170 if (verbose > 0) 170 if (verbose > 0)
171 vcnt++; 171 vcnt++;
172 172
173 snprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s", 173 scnprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s",
174 d, d, perf, vcnt, v); 174 d, d, perf, vcnt, v);
175 175
176 return system(cmd) ? TEST_FAIL : TEST_OK; 176 return system(cmd) ? TEST_FAIL : TEST_OK;
177} 177}
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index e0b1b414d466..6d598cc071ae 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -33,10 +33,9 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
33 for (i = 0; i < evlist->nr_mmaps; i++) { 33 for (i = 0; i < evlist->nr_mmaps; i++) {
34 struct perf_mmap *map = &evlist->overwrite_mmap[i]; 34 struct perf_mmap *map = &evlist->overwrite_mmap[i];
35 union perf_event *event; 35 union perf_event *event;
36 u64 start, end;
37 36
38 perf_mmap__read_init(map, true, &start, &end); 37 perf_mmap__read_init(map);
39 while ((event = perf_mmap__read_event(map, true, &start, end)) != NULL) { 38 while ((event = perf_mmap__read_event(map)) != NULL) {
40 const u32 type = event->header.type; 39 const u32 type = event->header.type;
41 40
42 switch (type) { 41 switch (type) {
diff --git a/tools/perf/tests/bp_account.c b/tools/perf/tests/bp_account.c
new file mode 100644
index 000000000000..a20cbc445426
--- /dev/null
+++ b/tools/perf/tests/bp_account.c
@@ -0,0 +1,193 @@
1/*
2 * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select
3 * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu.
4 */
5#define __SANE_USERSPACE_TYPES__
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <unistd.h>
10#include <string.h>
11#include <sys/ioctl.h>
12#include <time.h>
13#include <fcntl.h>
14#include <signal.h>
15#include <sys/mman.h>
16#include <linux/compiler.h>
17#include <linux/hw_breakpoint.h>
18#include <sys/ioctl.h>
19
20#include "tests.h"
21#include "debug.h"
22#include "perf.h"
23#include "cloexec.h"
24
25volatile long the_var;
26
27static noinline int test_function(void)
28{
29 return 0;
30}
31
32static int __event(bool is_x, void *addr, struct perf_event_attr *attr)
33{
34 int fd;
35
36 memset(attr, 0, sizeof(struct perf_event_attr));
37 attr->type = PERF_TYPE_BREAKPOINT;
38 attr->size = sizeof(struct perf_event_attr);
39
40 attr->config = 0;
41 attr->bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
42 attr->bp_addr = (unsigned long) addr;
43 attr->bp_len = sizeof(long);
44
45 attr->sample_period = 1;
46 attr->sample_type = PERF_SAMPLE_IP;
47
48 attr->exclude_kernel = 1;
49 attr->exclude_hv = 1;
50
51 fd = sys_perf_event_open(attr, -1, 0, -1,
52 perf_event_open_cloexec_flag());
53 if (fd < 0) {
54 pr_debug("failed opening event %llx\n", attr->config);
55 return TEST_FAIL;
56 }
57
58 return fd;
59}
60
61static int wp_event(void *addr, struct perf_event_attr *attr)
62{
63 return __event(false, addr, attr);
64}
65
66static int bp_event(void *addr, struct perf_event_attr *attr)
67{
68 return __event(true, addr, attr);
69}
70
71static int bp_accounting(int wp_cnt, int share)
72{
73 struct perf_event_attr attr, attr_mod, attr_new;
74 int i, fd[wp_cnt], fd_wp, ret;
75
76 for (i = 0; i < wp_cnt; i++) {
77 fd[i] = wp_event((void *)&the_var, &attr);
78 TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
79 pr_debug("wp %d created\n", i);
80 }
81
82 attr_mod = attr;
83 attr_mod.bp_type = HW_BREAKPOINT_X;
84 attr_mod.bp_addr = (unsigned long) test_function;
85
86 ret = ioctl(fd[0], PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr_mod);
87 TEST_ASSERT_VAL("failed to modify wp\n", ret == 0);
88
89 pr_debug("wp 0 modified to bp\n");
90
91 if (!share) {
92 fd_wp = wp_event((void *)&the_var, &attr_new);
93 TEST_ASSERT_VAL("failed to create max wp\n", fd_wp != -1);
94 pr_debug("wp max created\n");
95 }
96
97 for (i = 0; i < wp_cnt; i++)
98 close(fd[i]);
99
100 return 0;
101}
102
103static int detect_cnt(bool is_x)
104{
105 struct perf_event_attr attr;
106 void *addr = is_x ? (void *)test_function : (void *)&the_var;
107 int fd[100], cnt = 0, i;
108
109 while (1) {
110 if (cnt == 100) {
111 pr_debug("way too many debug registers, fix the test\n");
112 return 0;
113 }
114 fd[cnt] = __event(is_x, addr, &attr);
115
116 if (fd[cnt] < 0)
117 break;
118 cnt++;
119 }
120
121 for (i = 0; i < cnt; i++)
122 close(fd[i]);
123
124 return cnt;
125}
126
127static int detect_ioctl(void)
128{
129 struct perf_event_attr attr;
130 int fd, ret = 1;
131
132 fd = wp_event((void *) &the_var, &attr);
133 if (fd > 0) {
134 ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr);
135 close(fd);
136 }
137
138 return ret ? 0 : 1;
139}
140
141static int detect_share(int wp_cnt, int bp_cnt)
142{
143 struct perf_event_attr attr;
144 int i, fd[wp_cnt + bp_cnt], ret;
145
146 for (i = 0; i < wp_cnt; i++) {
147 fd[i] = wp_event((void *)&the_var, &attr);
148 TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1);
149 }
150
151 for (; i < (bp_cnt + wp_cnt); i++) {
152 fd[i] = bp_event((void *)test_function, &attr);
153 if (fd[i] == -1)
154 break;
155 }
156
157 ret = i != (bp_cnt + wp_cnt);
158
159 while (i--)
160 close(fd[i]);
161
162 return ret;
163}
164
165/*
166 * This test does following:
167 * - detects the number of watch/break-points,
168 * skip test if any is missing
169 * - detects PERF_EVENT_IOC_MODIFY_ATTRIBUTES ioctl,
170 * skip test if it's missing
171 * - detects if watchpoints and breakpoints share
172 * same slots
173 * - create all possible watchpoints on cpu 0
174 * - change one of it to breakpoint
175 * - in case wp and bp do not share slots,
176 * we create another watchpoint to ensure
177 * the slot accounting is correct
178 */
179int test__bp_accounting(struct test *test __maybe_unused, int subtest __maybe_unused)
180{
181 int has_ioctl = detect_ioctl();
182 int wp_cnt = detect_cnt(false);
183 int bp_cnt = detect_cnt(true);
184 int share = detect_share(wp_cnt, bp_cnt);
185
186 pr_debug("watchpoints count %d, breakpoints count %d, has_ioctl %d, share %d\n",
187 wp_cnt, bp_cnt, has_ioctl, share);
188
189 if (!wp_cnt || !bp_cnt || !has_ioctl)
190 return TEST_SKIP;
191
192 return bp_accounting(wp_cnt, share);
193}
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index e8399beca62b..79b54f8ddebf 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -176,13 +176,19 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
176 176
177 for (i = 0; i < evlist->nr_mmaps; i++) { 177 for (i = 0; i < evlist->nr_mmaps; i++) {
178 union perf_event *event; 178 union perf_event *event;
179 struct perf_mmap *md;
179 180
180 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 181 md = &evlist->mmap[i];
182 if (perf_mmap__read_init(md) < 0)
183 continue;
184
185 while ((event = perf_mmap__read_event(md)) != NULL) {
181 const u32 type = event->header.type; 186 const u32 type = event->header.type;
182 187
183 if (type == PERF_RECORD_SAMPLE) 188 if (type == PERF_RECORD_SAMPLE)
184 count ++; 189 count ++;
185 } 190 }
191 perf_mmap__read_done(md);
186 } 192 }
187 193
188 if (count != expect) { 194 if (count != expect) {
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index fafa014240cd..625f5a6772af 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -116,6 +116,10 @@ static struct test generic_tests[] = {
116 .is_supported = test__bp_signal_is_supported, 116 .is_supported = test__bp_signal_is_supported,
117 }, 117 },
118 { 118 {
119 .desc = "Breakpoint accounting",
120 .func = test__bp_accounting,
121 },
122 {
119 .desc = "Number of exit events of a simple workload", 123 .desc = "Number of exit events of a simple workload",
120 .func = test__task_exit, 124 .func = test__task_exit,
121 }, 125 },
@@ -271,6 +275,10 @@ static struct test generic_tests[] = {
271 .func = test__unit_number__scnprint, 275 .func = test__unit_number__scnprint,
272 }, 276 },
273 { 277 {
278 .desc = "mem2node",
279 .func = test__mem2node,
280 },
281 {
274 .func = NULL, 282 .func = NULL,
275 }, 283 },
276}; 284};
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 3bf7b145b826..99936352df4f 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -409,15 +409,21 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist,
409 struct state *state) 409 struct state *state)
410{ 410{
411 union perf_event *event; 411 union perf_event *event;
412 struct perf_mmap *md;
412 int i, ret; 413 int i, ret;
413 414
414 for (i = 0; i < evlist->nr_mmaps; i++) { 415 for (i = 0; i < evlist->nr_mmaps; i++) {
415 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 416 md = &evlist->mmap[i];
417 if (perf_mmap__read_init(md) < 0)
418 continue;
419
420 while ((event = perf_mmap__read_event(md)) != NULL) {
416 ret = process_event(machine, evlist, event, state); 421 ret = process_event(machine, evlist, event, state);
417 perf_evlist__mmap_consume(evlist, i); 422 perf_mmap__consume(md);
418 if (ret < 0) 423 if (ret < 0)
419 return ret; 424 return ret;
420 } 425 }
426 perf_mmap__read_done(md);
421 } 427 }
422 return 0; 428 return 0;
423} 429}
@@ -482,6 +488,34 @@ static void fs_something(void)
482 } 488 }
483} 489}
484 490
491static const char *do_determine_event(bool excl_kernel)
492{
493 const char *event = excl_kernel ? "cycles:u" : "cycles";
494
495#ifdef __s390x__
496 char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
497 unsigned int family;
498 int ret, cpum_cf_a;
499
500 if (get_cpuid(cpuid, sizeof(cpuid)))
501 goto out_clocks;
502 ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
503 model, cpum_cf_v, &cpum_cf_a);
504 if (ret != 5) /* Not available */
505 goto out_clocks;
506 if (excl_kernel && (cpum_cf_a & 4))
507 return event;
508 if (!excl_kernel && (cpum_cf_a & 2))
509 return event;
510
511 /* Fall through: missing authorization */
512out_clocks:
513 event = excl_kernel ? "cpu-clock:u" : "cpu-clock";
514
515#endif
516 return event;
517}
518
485static void do_something(void) 519static void do_something(void)
486{ 520{
487 fs_something(); 521 fs_something();
@@ -592,10 +626,7 @@ static int do_test_code_reading(bool try_kcore)
592 626
593 perf_evlist__set_maps(evlist, cpus, threads); 627 perf_evlist__set_maps(evlist, cpus, threads);
594 628
595 if (excl_kernel) 629 str = do_determine_event(excl_kernel);
596 str = "cycles:u";
597 else
598 str = "cycles";
599 pr_debug("Parsing event '%s'\n", str); 630 pr_debug("Parsing event '%s'\n", str);
600 ret = parse_events(evlist, str, NULL); 631 ret = parse_events(evlist, str, NULL);
601 if (ret < 0) { 632 if (ret < 0) {
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 260418969120..2f008067d989 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -37,6 +37,19 @@ static int init_live_machine(struct machine *machine)
37 mmap_handler, machine, true, 500); 37 mmap_handler, machine, true, 500);
38} 38}
39 39
40/*
41 * We need to keep these functions global, despite the
42 * fact that they are used only locally in this object,
43 * in order to keep them around even if the binary is
44 * stripped. If they are gone, the unwind check for
45 * symbol fails.
46 */
47int test_dwarf_unwind__thread(struct thread *thread);
48int test_dwarf_unwind__compare(void *p1, void *p2);
49int test_dwarf_unwind__krava_3(struct thread *thread);
50int test_dwarf_unwind__krava_2(struct thread *thread);
51int test_dwarf_unwind__krava_1(struct thread *thread);
52
40#define MAX_STACK 8 53#define MAX_STACK 8
41 54
42static int unwind_entry(struct unwind_entry *entry, void *arg) 55static int unwind_entry(struct unwind_entry *entry, void *arg)
@@ -45,12 +58,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
45 char *symbol = entry->sym ? entry->sym->name : NULL; 58 char *symbol = entry->sym ? entry->sym->name : NULL;
46 static const char *funcs[MAX_STACK] = { 59 static const char *funcs[MAX_STACK] = {
47 "test__arch_unwind_sample", 60 "test__arch_unwind_sample",
48 "unwind_thread", 61 "test_dwarf_unwind__thread",
49 "compare", 62 "test_dwarf_unwind__compare",
50 "bsearch", 63 "bsearch",
51 "krava_3", 64 "test_dwarf_unwind__krava_3",
52 "krava_2", 65 "test_dwarf_unwind__krava_2",
53 "krava_1", 66 "test_dwarf_unwind__krava_1",
54 "test__dwarf_unwind" 67 "test__dwarf_unwind"
55 }; 68 };
56 /* 69 /*
@@ -77,7 +90,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
77 return strcmp((const char *) symbol, funcs[idx]); 90 return strcmp((const char *) symbol, funcs[idx]);
78} 91}
79 92
80static noinline int unwind_thread(struct thread *thread) 93noinline int test_dwarf_unwind__thread(struct thread *thread)
81{ 94{
82 struct perf_sample sample; 95 struct perf_sample sample;
83 unsigned long cnt = 0; 96 unsigned long cnt = 0;
@@ -108,7 +121,7 @@ static noinline int unwind_thread(struct thread *thread)
108 121
109static int global_unwind_retval = -INT_MAX; 122static int global_unwind_retval = -INT_MAX;
110 123
111static noinline int compare(void *p1, void *p2) 124noinline int test_dwarf_unwind__compare(void *p1, void *p2)
112{ 125{
113 /* Any possible value should be 'thread' */ 126 /* Any possible value should be 'thread' */
114 struct thread *thread = *(struct thread **)p1; 127 struct thread *thread = *(struct thread **)p1;
@@ -117,17 +130,17 @@ static noinline int compare(void *p1, void *p2)
117 /* Call unwinder twice for both callchain orders. */ 130 /* Call unwinder twice for both callchain orders. */
118 callchain_param.order = ORDER_CALLER; 131 callchain_param.order = ORDER_CALLER;
119 132
120 global_unwind_retval = unwind_thread(thread); 133 global_unwind_retval = test_dwarf_unwind__thread(thread);
121 if (!global_unwind_retval) { 134 if (!global_unwind_retval) {
122 callchain_param.order = ORDER_CALLEE; 135 callchain_param.order = ORDER_CALLEE;
123 global_unwind_retval = unwind_thread(thread); 136 global_unwind_retval = test_dwarf_unwind__thread(thread);
124 } 137 }
125 } 138 }
126 139
127 return p1 - p2; 140 return p1 - p2;
128} 141}
129 142
130static noinline int krava_3(struct thread *thread) 143noinline int test_dwarf_unwind__krava_3(struct thread *thread)
131{ 144{
132 struct thread *array[2] = {thread, thread}; 145 struct thread *array[2] = {thread, thread};
133 void *fp = &bsearch; 146 void *fp = &bsearch;
@@ -141,18 +154,19 @@ static noinline int krava_3(struct thread *thread)
141 size_t, int (*)(void *, void *)); 154 size_t, int (*)(void *, void *));
142 155
143 _bsearch = fp; 156 _bsearch = fp;
144 _bsearch(array, &thread, 2, sizeof(struct thread **), compare); 157 _bsearch(array, &thread, 2, sizeof(struct thread **),
158 test_dwarf_unwind__compare);
145 return global_unwind_retval; 159 return global_unwind_retval;
146} 160}
147 161
148static noinline int krava_2(struct thread *thread) 162noinline int test_dwarf_unwind__krava_2(struct thread *thread)
149{ 163{
150 return krava_3(thread); 164 return test_dwarf_unwind__krava_3(thread);
151} 165}
152 166
153static noinline int krava_1(struct thread *thread) 167noinline int test_dwarf_unwind__krava_1(struct thread *thread)
154{ 168{
155 return krava_2(thread); 169 return test_dwarf_unwind__krava_2(thread);
156} 170}
157 171
158int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused) 172int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused)
@@ -189,7 +203,7 @@ int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unu
189 goto out; 203 goto out;
190 } 204 }
191 205
192 err = krava_1(thread); 206 err = test_dwarf_unwind__krava_1(thread);
193 thread__put(thread); 207 thread__put(thread);
194 208
195 out: 209 out:
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index c46530918938..17c46f3e6f1e 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -27,18 +27,23 @@
27static int find_comm(struct perf_evlist *evlist, const char *comm) 27static int find_comm(struct perf_evlist *evlist, const char *comm)
28{ 28{
29 union perf_event *event; 29 union perf_event *event;
30 struct perf_mmap *md;
30 int i, found; 31 int i, found;
31 32
32 found = 0; 33 found = 0;
33 for (i = 0; i < evlist->nr_mmaps; i++) { 34 for (i = 0; i < evlist->nr_mmaps; i++) {
34 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 35 md = &evlist->mmap[i];
36 if (perf_mmap__read_init(md) < 0)
37 continue;
38 while ((event = perf_mmap__read_event(md)) != NULL) {
35 if (event->header.type == PERF_RECORD_COMM && 39 if (event->header.type == PERF_RECORD_COMM &&
36 (pid_t)event->comm.pid == getpid() && 40 (pid_t)event->comm.pid == getpid() &&
37 (pid_t)event->comm.tid == getpid() && 41 (pid_t)event->comm.tid == getpid() &&
38 strcmp(event->comm.comm, comm) == 0) 42 strcmp(event->comm.comm, comm) == 0)
39 found += 1; 43 found += 1;
40 perf_evlist__mmap_consume(evlist, i); 44 perf_mmap__consume(md);
41 } 45 }
46 perf_mmap__read_done(md);
42 } 47 }
43 return found; 48 return found;
44} 49}
diff --git a/tools/perf/tests/mem.c b/tools/perf/tests/mem.c
index 21952e1e6e6d..0f82ee9fd3f7 100644
--- a/tools/perf/tests/mem.c
+++ b/tools/perf/tests/mem.c
@@ -16,7 +16,7 @@ static int check(union perf_mem_data_src data_src,
16 16
17 n = perf_mem__snp_scnprintf(out, sizeof out, &mi); 17 n = perf_mem__snp_scnprintf(out, sizeof out, &mi);
18 n += perf_mem__lvl_scnprintf(out + n, sizeof out - n, &mi); 18 n += perf_mem__lvl_scnprintf(out + n, sizeof out - n, &mi);
19 snprintf(failure, sizeof failure, "unexpected %s", out); 19 scnprintf(failure, sizeof failure, "unexpected %s", out);
20 TEST_ASSERT_VAL(failure, !strcmp(string, out)); 20 TEST_ASSERT_VAL(failure, !strcmp(string, out));
21 return 0; 21 return 0;
22} 22}
diff --git a/tools/perf/tests/mem2node.c b/tools/perf/tests/mem2node.c
new file mode 100644
index 000000000000..0c3c87f86e03
--- /dev/null
+++ b/tools/perf/tests/mem2node.c
@@ -0,0 +1,75 @@
1#include <linux/compiler.h>
2#include <linux/bitmap.h>
3#include "cpumap.h"
4#include "mem2node.h"
5#include "tests.h"
6
7static struct node {
8 int node;
9 const char *map;
10} test_nodes[] = {
11 { .node = 0, .map = "0" },
12 { .node = 1, .map = "1-2" },
13 { .node = 3, .map = "5-7,9" },
14};
15
16#define T TEST_ASSERT_VAL
17
18static unsigned long *get_bitmap(const char *str, int nbits)
19{
20 struct cpu_map *map = cpu_map__new(str);
21 unsigned long *bm = NULL;
22 int i;
23
24 bm = bitmap_alloc(nbits);
25
26 if (map && bm) {
27 bitmap_zero(bm, nbits);
28
29 for (i = 0; i < map->nr; i++) {
30 set_bit(map->map[i], bm);
31 }
32 }
33
34 if (map)
35 cpu_map__put(map);
36 else
37 free(bm);
38
39 return bm && map ? bm : NULL;
40}
41
42int test__mem2node(struct test *t __maybe_unused, int subtest __maybe_unused)
43{
44 struct mem2node map;
45 struct memory_node nodes[3];
46 struct perf_env env = {
47 .memory_nodes = (struct memory_node *) &nodes[0],
48 .nr_memory_nodes = ARRAY_SIZE(nodes),
49 .memory_bsize = 0x100,
50 };
51 unsigned int i;
52
53 for (i = 0; i < ARRAY_SIZE(nodes); i++) {
54 nodes[i].node = test_nodes[i].node;
55 nodes[i].size = 10;
56
57 T("failed: alloc bitmap",
58 (nodes[i].set = get_bitmap(test_nodes[i].map, 10)));
59 }
60
61 T("failed: mem2node__init", !mem2node__init(&map, &env));
62 T("failed: mem2node__node", 0 == mem2node__node(&map, 0x50));
63 T("failed: mem2node__node", 1 == mem2node__node(&map, 0x100));
64 T("failed: mem2node__node", 1 == mem2node__node(&map, 0x250));
65 T("failed: mem2node__node", 3 == mem2node__node(&map, 0x500));
66 T("failed: mem2node__node", 3 == mem2node__node(&map, 0x650));
67 T("failed: mem2node__node", -1 == mem2node__node(&map, 0x450));
68 T("failed: mem2node__node", -1 == mem2node__node(&map, 0x1050));
69
70 for (i = 0; i < ARRAY_SIZE(nodes); i++)
71 free(nodes[i].set);
72
73 mem2node__exit(&map);
74 return 0;
75}
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index c0e971da965c..bb8e6bcb0d96 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -38,6 +38,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
38 expected_nr_events[nsyscalls], i, j; 38 expected_nr_events[nsyscalls], i, j;
39 struct perf_evsel *evsels[nsyscalls], *evsel; 39 struct perf_evsel *evsels[nsyscalls], *evsel;
40 char sbuf[STRERR_BUFSIZE]; 40 char sbuf[STRERR_BUFSIZE];
41 struct perf_mmap *md;
41 42
42 threads = thread_map__new(-1, getpid(), UINT_MAX); 43 threads = thread_map__new(-1, getpid(), UINT_MAX);
43 if (threads == NULL) { 44 if (threads == NULL) {
@@ -106,7 +107,11 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
106 ++foo; 107 ++foo;
107 } 108 }
108 109
109 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 110 md = &evlist->mmap[0];
111 if (perf_mmap__read_init(md) < 0)
112 goto out_init;
113
114 while ((event = perf_mmap__read_event(md)) != NULL) {
110 struct perf_sample sample; 115 struct perf_sample sample;
111 116
112 if (event->header.type != PERF_RECORD_SAMPLE) { 117 if (event->header.type != PERF_RECORD_SAMPLE) {
@@ -129,9 +134,11 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
129 goto out_delete_evlist; 134 goto out_delete_evlist;
130 } 135 }
131 nr_events[evsel->idx]++; 136 nr_events[evsel->idx]++;
132 perf_evlist__mmap_consume(evlist, 0); 137 perf_mmap__consume(md);
133 } 138 }
139 perf_mmap__read_done(md);
134 140
141out_init:
135 err = 0; 142 err = 0;
136 evlist__for_each_entry(evlist, evsel) { 143 evlist__for_each_entry(evlist, evsel) {
137 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 144 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 43519267b93b..344dc3ac2469 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -86,8 +86,13 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
86 86
87 for (i = 0; i < evlist->nr_mmaps; i++) { 87 for (i = 0; i < evlist->nr_mmaps; i++) {
88 union perf_event *event; 88 union perf_event *event;
89 struct perf_mmap *md;
89 90
90 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 91 md = &evlist->mmap[i];
92 if (perf_mmap__read_init(md) < 0)
93 continue;
94
95 while ((event = perf_mmap__read_event(md)) != NULL) {
91 const u32 type = event->header.type; 96 const u32 type = event->header.type;
92 int tp_flags; 97 int tp_flags;
93 struct perf_sample sample; 98 struct perf_sample sample;
@@ -95,7 +100,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
95 ++nr_events; 100 ++nr_events;
96 101
97 if (type != PERF_RECORD_SAMPLE) { 102 if (type != PERF_RECORD_SAMPLE) {
98 perf_evlist__mmap_consume(evlist, i); 103 perf_mmap__consume(md);
99 continue; 104 continue;
100 } 105 }
101 106
@@ -115,6 +120,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest
115 120
116 goto out_ok; 121 goto out_ok;
117 } 122 }
123 perf_mmap__read_done(md);
118 } 124 }
119 125
120 if (nr_events == before) 126 if (nr_events == before)
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 0afafab85238..34394cc05077 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -164,8 +164,13 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
164 164
165 for (i = 0; i < evlist->nr_mmaps; i++) { 165 for (i = 0; i < evlist->nr_mmaps; i++) {
166 union perf_event *event; 166 union perf_event *event;
167 struct perf_mmap *md;
167 168
168 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 169 md = &evlist->mmap[i];
170 if (perf_mmap__read_init(md) < 0)
171 continue;
172
173 while ((event = perf_mmap__read_event(md)) != NULL) {
169 const u32 type = event->header.type; 174 const u32 type = event->header.type;
170 const char *name = perf_event__name(type); 175 const char *name = perf_event__name(type);
171 176
@@ -266,8 +271,9 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus
266 ++errs; 271 ++errs;
267 } 272 }
268 273
269 perf_evlist__mmap_consume(evlist, i); 274 perf_mmap__consume(md);
270 } 275 }
276 perf_mmap__read_done(md);
271 } 277 }
272 278
273 /* 279 /*
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 9abca267afa9..7bedf8608fdd 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -98,7 +98,7 @@ static char *test_format_dir_get(void)
98 struct test_format *format = &test_formats[i]; 98 struct test_format *format = &test_formats[i];
99 FILE *file; 99 FILE *file;
100 100
101 snprintf(name, PATH_MAX, "%s/%s", dir, format->name); 101 scnprintf(name, PATH_MAX, "%s/%s", dir, format->name);
102 102
103 file = fopen(name, "w"); 103 file = fopen(name, "w");
104 if (!file) 104 if (!file)
diff --git a/tools/perf/tests/shell/lib/probe_vfs_getname.sh b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
index 30a950c9d407..1c16e56cd93e 100644
--- a/tools/perf/tests/shell/lib/probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/lib/probe_vfs_getname.sh
@@ -5,7 +5,7 @@ had_vfs_getname=$?
5 5
6cleanup_probe_vfs_getname() { 6cleanup_probe_vfs_getname() {
7 if [ $had_vfs_getname -eq 1 ] ; then 7 if [ $had_vfs_getname -eq 1 ] ; then
8 perf probe -q -d probe:vfs_getname 8 perf probe -q -d probe:vfs_getname*
9 fi 9 fi
10} 10}
11 11
diff --git a/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index c446c894b297..1ecc1f0ff84a 100755
--- a/tools/perf/tests/shell/trace+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -15,30 +15,28 @@ nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254
15 15
16trace_libc_inet_pton_backtrace() { 16trace_libc_inet_pton_backtrace() {
17 idx=0 17 idx=0
18 expected[0]="PING.*bytes" 18 expected[0]="ping[][0-9 \.:]+probe_libc:inet_pton: \([[:xdigit:]]+\)"
19 expected[1]="64 bytes from ::1.*" 19 expected[1]=".*inet_pton[[:space:]]\($libc\)$"
20 expected[2]=".*ping statistics.*"
21 expected[3]=".*packets transmitted.*"
22 expected[4]="rtt min.*"
23 expected[5]="[0-9]+\.[0-9]+[[:space:]]+probe_libc:inet_pton:\([[:xdigit:]]+\)"
24 expected[6]=".*inet_pton[[:space:]]\($libc\)$"
25 case "$(uname -m)" in 20 case "$(uname -m)" in
26 s390x) 21 s390x)
27 eventattr='call-graph=dwarf' 22 eventattr='call-graph=dwarf'
28 expected[7]="gaih_inet[[:space:]]\(inlined\)$" 23 expected[2]="gaih_inet.*[[:space:]]\($libc|inlined\)$"
29 expected[8]="__GI_getaddrinfo[[:space:]]\(inlined\)$" 24 expected[3]="__GI_getaddrinfo[[:space:]]\($libc|inlined\)$"
30 expected[9]="main[[:space:]]\(.*/bin/ping.*\)$" 25 expected[4]="main[[:space:]]\(.*/bin/ping.*\)$"
31 expected[10]="__libc_start_main[[:space:]]\($libc\)$" 26 expected[5]="__libc_start_main[[:space:]]\($libc\)$"
32 expected[11]="_start[[:space:]]\(.*/bin/ping.*\)$" 27 expected[6]="_start[[:space:]]\(.*/bin/ping.*\)$"
33 ;; 28 ;;
34 *) 29 *)
35 eventattr='max-stack=3' 30 eventattr='max-stack=3'
36 expected[7]="getaddrinfo[[:space:]]\($libc\)$" 31 expected[2]="getaddrinfo[[:space:]]\($libc\)$"
37 expected[8]=".*\(.*/bin/ping.*\)$" 32 expected[3]=".*\(.*/bin/ping.*\)$"
38 ;; 33 ;;
39 esac 34 esac
40 35
41 perf trace --no-syscalls -e probe_libc:inet_pton/$eventattr/ ping -6 -c 1 ::1 2>&1 | grep -v ^$ | while read line ; do 36 file=`mktemp -u /tmp/perf.data.XXX`
37
38 perf record -e probe_libc:inet_pton/$eventattr/ -o $file ping -6 -c 1 ::1 > /dev/null 2>&1
39 perf script -i $file | while read line ; do
42 echo $line 40 echo $line
43 echo "$line" | egrep -q "${expected[$idx]}" 41 echo "$line" | egrep -q "${expected[$idx]}"
44 if [ $? -ne 0 ] ; then 42 if [ $? -ne 0 ] ; then
@@ -48,6 +46,11 @@ trace_libc_inet_pton_backtrace() {
48 let idx+=1 46 let idx+=1
49 [ -z "${expected[$idx]}" ] && break 47 [ -z "${expected[$idx]}" ] && break
50 done 48 done
49
50 # If any statements are executed from this point onwards,
51 # the exit code of the last among these will be reflected
52 # in err below. If the exit code is 0, the test will pass
53 # even if the perf script output does not match.
51} 54}
52 55
53# Check for IPv6 interface existence 56# Check for IPv6 interface existence
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index f6c72f915d48..f9490b237893 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -39,6 +39,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
39 }; 39 };
40 struct cpu_map *cpus; 40 struct cpu_map *cpus;
41 struct thread_map *threads; 41 struct thread_map *threads;
42 struct perf_mmap *md;
42 43
43 attr.sample_freq = 500; 44 attr.sample_freq = 500;
44 45
@@ -93,7 +94,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
93 94
94 perf_evlist__disable(evlist); 95 perf_evlist__disable(evlist);
95 96
96 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 97 md = &evlist->mmap[0];
98 if (perf_mmap__read_init(md) < 0)
99 goto out_init;
100
101 while ((event = perf_mmap__read_event(md)) != NULL) {
97 struct perf_sample sample; 102 struct perf_sample sample;
98 103
99 if (event->header.type != PERF_RECORD_SAMPLE) 104 if (event->header.type != PERF_RECORD_SAMPLE)
@@ -108,9 +113,11 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
108 total_periods += sample.period; 113 total_periods += sample.period;
109 nr_samples++; 114 nr_samples++;
110next_event: 115next_event:
111 perf_evlist__mmap_consume(evlist, 0); 116 perf_mmap__consume(md);
112 } 117 }
118 perf_mmap__read_done(md);
113 119
120out_init:
114 if ((u64) nr_samples == total_periods) { 121 if ((u64) nr_samples == total_periods) {
115 pr_debug("All (%d) samples have period value of 1!\n", 122 pr_debug("All (%d) samples have period value of 1!\n",
116 nr_samples); 123 nr_samples);
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 33e00295a972..9b5be51e5e7b 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -258,16 +258,22 @@ static int process_events(struct perf_evlist *evlist,
258 unsigned pos, cnt = 0; 258 unsigned pos, cnt = 0;
259 LIST_HEAD(events); 259 LIST_HEAD(events);
260 struct event_node *events_array, *node; 260 struct event_node *events_array, *node;
261 struct perf_mmap *md;
261 int i, ret; 262 int i, ret;
262 263
263 for (i = 0; i < evlist->nr_mmaps; i++) { 264 for (i = 0; i < evlist->nr_mmaps; i++) {
264 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 265 md = &evlist->mmap[i];
266 if (perf_mmap__read_init(md) < 0)
267 continue;
268
269 while ((event = perf_mmap__read_event(md)) != NULL) {
265 cnt += 1; 270 cnt += 1;
266 ret = add_event(evlist, &events, event); 271 ret = add_event(evlist, &events, event);
267 perf_evlist__mmap_consume(evlist, i); 272 perf_mmap__consume(md);
268 if (ret < 0) 273 if (ret < 0)
269 goto out_free_nodes; 274 goto out_free_nodes;
270 } 275 }
276 perf_mmap__read_done(md);
271 } 277 }
272 278
273 events_array = calloc(cnt, sizeof(struct event_node)); 279 events_array = calloc(cnt, sizeof(struct event_node));
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 01b62b81751b..e92fa6029ac7 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -47,6 +47,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
47 char sbuf[STRERR_BUFSIZE]; 47 char sbuf[STRERR_BUFSIZE];
48 struct cpu_map *cpus; 48 struct cpu_map *cpus;
49 struct thread_map *threads; 49 struct thread_map *threads;
50 struct perf_mmap *md;
50 51
51 signal(SIGCHLD, sig_handler); 52 signal(SIGCHLD, sig_handler);
52 53
@@ -110,13 +111,19 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
110 perf_evlist__start_workload(evlist); 111 perf_evlist__start_workload(evlist);
111 112
112retry: 113retry:
113 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { 114 md = &evlist->mmap[0];
115 if (perf_mmap__read_init(md) < 0)
116 goto out_init;
117
118 while ((event = perf_mmap__read_event(md)) != NULL) {
114 if (event->header.type == PERF_RECORD_EXIT) 119 if (event->header.type == PERF_RECORD_EXIT)
115 nr_exit++; 120 nr_exit++;
116 121
117 perf_evlist__mmap_consume(evlist, 0); 122 perf_mmap__consume(md);
118 } 123 }
124 perf_mmap__read_done(md);
119 125
126out_init:
120 if (!exited || !nr_exit) { 127 if (!exited || !nr_exit) {
121 perf_evlist__poll(evlist, -1); 128 perf_evlist__poll(evlist, -1);
122 goto retry; 129 goto retry;
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 2862b80bc288..a9760e790563 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -58,6 +58,7 @@ int test__hists_link(struct test *test, int subtest);
58int test__python_use(struct test *test, int subtest); 58int test__python_use(struct test *test, int subtest);
59int test__bp_signal(struct test *test, int subtest); 59int test__bp_signal(struct test *test, int subtest);
60int test__bp_signal_overflow(struct test *test, int subtest); 60int test__bp_signal_overflow(struct test *test, int subtest);
61int test__bp_accounting(struct test *test, int subtest);
61int test__task_exit(struct test *test, int subtest); 62int test__task_exit(struct test *test, int subtest);
62int test__mem(struct test *test, int subtest); 63int test__mem(struct test *test, int subtest);
63int test__sw_clock_freq(struct test *test, int subtest); 64int test__sw_clock_freq(struct test *test, int subtest);
@@ -102,6 +103,7 @@ int test__clang(struct test *test, int subtest);
102const char *test__clang_subtest_get_desc(int subtest); 103const char *test__clang_subtest_get_desc(int subtest);
103int test__clang_subtest_get_nr(void); 104int test__clang_subtest_get_nr(void);
104int test__unit_number__scnprint(struct test *test, int subtest); 105int test__unit_number__scnprint(struct test *test, int subtest);
106int test__mem2node(struct test *t, int subtest);
105 107
106bool test__bp_signal_is_supported(void); 108bool test__bp_signal_is_supported(void);
107 109
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index f6789fb029d6..1e5adb65632a 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -56,7 +56,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
56 * be compacted against the list of modules found in the "vmlinux" 56 * be compacted against the list of modules found in the "vmlinux"
57 * code and with the one got from /proc/modules from the "kallsyms" code. 57 * code and with the one got from /proc/modules from the "kallsyms" code.
58 */ 58 */
59 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true) <= 0) { 59 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type) <= 0) {
60 pr_debug("dso__load_kallsyms "); 60 pr_debug("dso__load_kallsyms ");
61 goto out; 61 goto out;
62 } 62 }
@@ -125,7 +125,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
125 125
126 if (pair && UM(pair->start) == mem_start) { 126 if (pair && UM(pair->start) == mem_start) {
127next_pair: 127next_pair:
128 if (strcmp(sym->name, pair->name) == 0) { 128 if (arch__compare_symbol_names(sym->name, pair->name) == 0) {
129 /* 129 /*
130 * kallsyms don't have the symbol end, so we 130 * kallsyms don't have the symbol end, so we
131 * set that by using the next symbol start - 1, 131 * set that by using the next symbol start - 1,
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index 63399af3049f..9f6ce29b83b4 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -56,12 +56,17 @@ void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const
56 slsmg_write_nstring(msg, width); 56 slsmg_write_nstring(msg, width);
57} 57}
58 58
59void ui_browser__vprintf(struct ui_browser *browser __maybe_unused, const char *fmt, va_list args)
60{
61 slsmg_vprintf(fmt, args);
62}
63
59void ui_browser__printf(struct ui_browser *browser __maybe_unused, const char *fmt, ...) 64void ui_browser__printf(struct ui_browser *browser __maybe_unused, const char *fmt, ...)
60{ 65{
61 va_list args; 66 va_list args;
62 67
63 va_start(args, fmt); 68 va_start(args, fmt);
64 slsmg_vprintf(fmt, args); 69 ui_browser__vprintf(browser, fmt, args);
65 va_end(args); 70 va_end(args);
66} 71}
67 72
@@ -779,6 +784,4 @@ void ui_browser__init(void)
779 struct ui_browser_colorset *c = &ui_browser__colorsets[i++]; 784 struct ui_browser_colorset *c = &ui_browser__colorsets[i++];
780 sltt_set_color(c->colorset, c->name, c->fg, c->bg); 785 sltt_set_color(c->colorset, c->name, c->fg, c->bg);
781 } 786 }
782
783 annotate_browser__init();
784} 787}
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 03e1734412b9..70057178ee34 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -3,6 +3,7 @@
3#define _PERF_UI_BROWSER_H_ 1 3#define _PERF_UI_BROWSER_H_ 1
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <stdarg.h>
6 7
7#define HE_COLORSET_TOP 50 8#define HE_COLORSET_TOP 50
8#define HE_COLORSET_MEDIUM 51 9#define HE_COLORSET_MEDIUM 51
@@ -40,6 +41,7 @@ void ui_browser__reset_index(struct ui_browser *browser);
40void ui_browser__gotorc(struct ui_browser *browser, int y, int x); 41void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
41void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, 42void ui_browser__write_nstring(struct ui_browser *browser, const char *msg,
42 unsigned int width); 43 unsigned int width);
44void ui_browser__vprintf(struct ui_browser *browser, const char *fmt, va_list args);
43void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...); 45void ui_browser__printf(struct ui_browser *browser, const char *fmt, ...);
44void ui_browser__write_graph(struct ui_browser *browser, int graph); 46void ui_browser__write_graph(struct ui_browser *browser, int graph);
45void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, 47void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
@@ -77,5 +79,4 @@ void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int wh
77unsigned int ui_browser__list_head_refresh(struct ui_browser *browser); 79unsigned int ui_browser__list_head_refresh(struct ui_browser *browser);
78 80
79void ui_browser__init(void); 81void ui_browser__init(void);
80void annotate_browser__init(void);
81#endif /* _PERF_UI_BROWSER_H_ */ 82#endif /* _PERF_UI_BROWSER_H_ */
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 286427975112..c02fb437ac8e 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -9,7 +9,6 @@
9#include "../../util/sort.h" 9#include "../../util/sort.h"
10#include "../../util/symbol.h" 10#include "../../util/symbol.h"
11#include "../../util/evsel.h" 11#include "../../util/evsel.h"
12#include "../../util/config.h"
13#include "../../util/evlist.h" 12#include "../../util/evlist.h"
14#include <inttypes.h> 13#include <inttypes.h>
15#include <pthread.h> 14#include <pthread.h>
@@ -22,28 +21,6 @@ struct disasm_line_samples {
22 struct sym_hist_entry he; 21 struct sym_hist_entry he;
23}; 22};
24 23
25#define IPC_WIDTH 6
26#define CYCLES_WIDTH 6
27
28struct browser_line {
29 u32 idx;
30 int idx_asm;
31 int jump_sources;
32};
33
34static struct annotate_browser_opt {
35 bool hide_src_code,
36 use_offset,
37 jump_arrows,
38 show_linenr,
39 show_nr_jumps,
40 show_nr_samples,
41 show_total_period;
42} annotate_browser__opts = {
43 .use_offset = true,
44 .jump_arrows = true,
45};
46
47struct arch; 24struct arch;
48 25
49struct annotate_browser { 26struct annotate_browser {
@@ -51,245 +28,98 @@ struct annotate_browser {
51 struct rb_root entries; 28 struct rb_root entries;
52 struct rb_node *curr_hot; 29 struct rb_node *curr_hot;
53 struct annotation_line *selection; 30 struct annotation_line *selection;
54 struct annotation_line **offsets;
55 struct arch *arch; 31 struct arch *arch;
56 int nr_events;
57 u64 start;
58 int nr_asm_entries;
59 int nr_entries;
60 int max_jump_sources;
61 int nr_jumps;
62 bool searching_backwards; 32 bool searching_backwards;
63 bool have_cycles;
64 u8 addr_width;
65 u8 jumps_width;
66 u8 target_width;
67 u8 min_addr_width;
68 u8 max_addr_width;
69 char search_bf[128]; 33 char search_bf[128];
70}; 34};
71 35
72static inline struct browser_line *browser_line(struct annotation_line *al) 36static inline struct annotation *browser__annotation(struct ui_browser *browser)
73{ 37{
74 void *ptr = al; 38 struct map_symbol *ms = browser->priv;
75 39 return symbol__annotation(ms->sym);
76 ptr = container_of(al, struct disasm_line, al);
77 return ptr - sizeof(struct browser_line);
78} 40}
79 41
80static bool disasm_line__filter(struct ui_browser *browser __maybe_unused, 42static bool disasm_line__filter(struct ui_browser *browser, void *entry)
81 void *entry)
82{ 43{
83 if (annotate_browser__opts.hide_src_code) { 44 struct annotation *notes = browser__annotation(browser);
84 struct annotation_line *al = list_entry(entry, struct annotation_line, node); 45 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
85 46 return annotation_line__filter(al, notes);
86 return al->offset == -1;
87 }
88
89 return false;
90} 47}
91 48
92static int annotate_browser__jumps_percent_color(struct annotate_browser *browser, 49static int ui_browser__jumps_percent_color(struct ui_browser *browser, int nr, bool current)
93 int nr, bool current)
94{ 50{
95 if (current && (!browser->b.use_navkeypressed || browser->b.navkeypressed)) 51 struct annotation *notes = browser__annotation(browser);
52
53 if (current && (!browser->use_navkeypressed || browser->navkeypressed))
96 return HE_COLORSET_SELECTED; 54 return HE_COLORSET_SELECTED;
97 if (nr == browser->max_jump_sources) 55 if (nr == notes->max_jump_sources)
98 return HE_COLORSET_TOP; 56 return HE_COLORSET_TOP;
99 if (nr > 1) 57 if (nr > 1)
100 return HE_COLORSET_MEDIUM; 58 return HE_COLORSET_MEDIUM;
101 return HE_COLORSET_NORMAL; 59 return HE_COLORSET_NORMAL;
102} 60}
103 61
104static int annotate_browser__set_jumps_percent_color(struct annotate_browser *browser, 62static int ui_browser__set_jumps_percent_color(void *browser, int nr, bool current)
105 int nr, bool current)
106{ 63{
107 int color = annotate_browser__jumps_percent_color(browser, nr, current); 64 int color = ui_browser__jumps_percent_color(browser, nr, current);
108 return ui_browser__set_color(&browser->b, color); 65 return ui_browser__set_color(browser, color);
109} 66}
110 67
111static int annotate_browser__pcnt_width(struct annotate_browser *ab) 68static int annotate_browser__set_color(void *browser, int color)
112{ 69{
113 return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events; 70 return ui_browser__set_color(browser, color);
114} 71}
115 72
116static int annotate_browser__cycles_width(struct annotate_browser *ab) 73static void annotate_browser__write_graph(void *browser, int graph)
117{ 74{
118 return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0; 75 ui_browser__write_graph(browser, graph);
119} 76}
120 77
121static void disasm_line__write(struct disasm_line *dl, struct ui_browser *browser, 78static void annotate_browser__set_percent_color(void *browser, double percent, bool current)
122 char *bf, size_t size)
123{ 79{
124 if (dl->ins.ops && dl->ins.ops->scnprintf) { 80 ui_browser__set_percent_color(browser, percent, current);
125 if (ins__is_jump(&dl->ins)) { 81}
126 bool fwd = dl->ops.target.offset > dl->al.offset;
127
128 ui_browser__write_graph(browser, fwd ? SLSMG_DARROW_CHAR :
129 SLSMG_UARROW_CHAR);
130 SLsmg_write_char(' ');
131 } else if (ins__is_call(&dl->ins)) {
132 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
133 SLsmg_write_char(' ');
134 } else if (ins__is_ret(&dl->ins)) {
135 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
136 SLsmg_write_char(' ');
137 } else {
138 ui_browser__write_nstring(browser, " ", 2);
139 }
140 } else {
141 ui_browser__write_nstring(browser, " ", 2);
142 }
143 82
144 disasm_line__scnprintf(dl, bf, size, !annotate_browser__opts.use_offset); 83static void annotate_browser__printf(void *browser, const char *fmt, ...)
84{
85 va_list args;
86
87 va_start(args, fmt);
88 ui_browser__vprintf(browser, fmt, args);
89 va_end(args);
145} 90}
146 91
147static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 92static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
148{ 93{
149 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 94 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
95 struct annotation *notes = browser__annotation(browser);
150 struct annotation_line *al = list_entry(entry, struct annotation_line, node); 96 struct annotation_line *al = list_entry(entry, struct annotation_line, node);
151 struct browser_line *bl = browser_line(al); 97 struct annotation_write_ops ops = {
152 bool current_entry = ui_browser__is_current_entry(browser, row); 98 .first_line = row == 0,
153 bool change_color = (!annotate_browser__opts.hide_src_code && 99 .current_entry = ui_browser__is_current_entry(browser, row),
154 (!current_entry || (browser->use_navkeypressed && 100 .change_color = (!notes->options->hide_src_code &&
155 !browser->navkeypressed))); 101 (!ops.current_entry ||
156 int width = browser->width, printed; 102 (browser->use_navkeypressed &&
157 int i, pcnt_width = annotate_browser__pcnt_width(ab), 103 !browser->navkeypressed))),
158 cycles_width = annotate_browser__cycles_width(ab); 104 .width = browser->width,
159 double percent_max = 0.0; 105 .obj = browser,
160 char bf[256]; 106 .set_color = annotate_browser__set_color,
161 bool show_title = false; 107 .set_percent_color = annotate_browser__set_percent_color,
162 108 .set_jumps_percent_color = ui_browser__set_jumps_percent_color,
163 for (i = 0; i < ab->nr_events; i++) { 109 .printf = annotate_browser__printf,
164 if (al->samples[i].percent > percent_max) 110 .write_graph = annotate_browser__write_graph,
165 percent_max = al->samples[i].percent; 111 };
166 }
167
168 if ((row == 0) && (al->offset == -1 || percent_max == 0.0)) {
169 if (ab->have_cycles) {
170 if (al->ipc == 0.0 && al->cycles == 0)
171 show_title = true;
172 } else
173 show_title = true;
174 }
175
176 if (al->offset != -1 && percent_max != 0.0) {
177 for (i = 0; i < ab->nr_events; i++) {
178 ui_browser__set_percent_color(browser,
179 al->samples[i].percent,
180 current_entry);
181 if (annotate_browser__opts.show_total_period) {
182 ui_browser__printf(browser, "%11" PRIu64 " ",
183 al->samples[i].he.period);
184 } else if (annotate_browser__opts.show_nr_samples) {
185 ui_browser__printf(browser, "%6" PRIu64 " ",
186 al->samples[i].he.nr_samples);
187 } else {
188 ui_browser__printf(browser, "%6.2f ",
189 al->samples[i].percent);
190 }
191 }
192 } else {
193 ui_browser__set_percent_color(browser, 0, current_entry);
194
195 if (!show_title)
196 ui_browser__write_nstring(browser, " ", pcnt_width);
197 else {
198 ui_browser__printf(browser, "%*s", pcnt_width,
199 annotate_browser__opts.show_total_period ? "Period" :
200 annotate_browser__opts.show_nr_samples ? "Samples" : "Percent");
201 }
202 }
203 if (ab->have_cycles) {
204 if (al->ipc)
205 ui_browser__printf(browser, "%*.2f ", IPC_WIDTH - 1, al->ipc);
206 else if (!show_title)
207 ui_browser__write_nstring(browser, " ", IPC_WIDTH);
208 else
209 ui_browser__printf(browser, "%*s ", IPC_WIDTH - 1, "IPC");
210
211 if (al->cycles)
212 ui_browser__printf(browser, "%*" PRIu64 " ",
213 CYCLES_WIDTH - 1, al->cycles);
214 else if (!show_title)
215 ui_browser__write_nstring(browser, " ", CYCLES_WIDTH);
216 else
217 ui_browser__printf(browser, "%*s ", CYCLES_WIDTH - 1, "Cycle");
218 }
219
220 SLsmg_write_char(' ');
221 112
222 /* The scroll bar isn't being used */ 113 /* The scroll bar isn't being used */
223 if (!browser->navkeypressed) 114 if (!browser->navkeypressed)
224 width += 1; 115 ops.width += 1;
225
226 if (!*al->line)
227 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
228 else if (al->offset == -1) {
229 if (al->line_nr && annotate_browser__opts.show_linenr)
230 printed = scnprintf(bf, sizeof(bf), "%-*d ",
231 ab->addr_width + 1, al->line_nr);
232 else
233 printed = scnprintf(bf, sizeof(bf), "%*s ",
234 ab->addr_width, " ");
235 ui_browser__write_nstring(browser, bf, printed);
236 ui_browser__write_nstring(browser, al->line, width - printed - pcnt_width - cycles_width + 1);
237 } else {
238 u64 addr = al->offset;
239 int color = -1;
240
241 if (!annotate_browser__opts.use_offset)
242 addr += ab->start;
243
244 if (!annotate_browser__opts.use_offset) {
245 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
246 } else {
247 if (bl->jump_sources) {
248 if (annotate_browser__opts.show_nr_jumps) {
249 int prev;
250 printed = scnprintf(bf, sizeof(bf), "%*d ",
251 ab->jumps_width,
252 bl->jump_sources);
253 prev = annotate_browser__set_jumps_percent_color(ab, bl->jump_sources,
254 current_entry);
255 ui_browser__write_nstring(browser, bf, printed);
256 ui_browser__set_color(browser, prev);
257 }
258
259 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
260 ab->target_width, addr);
261 } else {
262 printed = scnprintf(bf, sizeof(bf), "%*s ",
263 ab->addr_width, " ");
264 }
265 }
266
267 if (change_color)
268 color = ui_browser__set_color(browser, HE_COLORSET_ADDR);
269 ui_browser__write_nstring(browser, bf, printed);
270 if (change_color)
271 ui_browser__set_color(browser, color);
272 116
273 disasm_line__write(disasm_line(al), browser, bf, sizeof(bf)); 117 annotation_line__write(al, notes, &ops);
274 118
275 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed); 119 if (ops.current_entry)
276 }
277
278 if (current_entry)
279 ab->selection = al; 120 ab->selection = al;
280} 121}
281 122
282static bool disasm_line__is_valid_jump(struct disasm_line *dl, struct symbol *sym)
283{
284 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins)
285 || !disasm_line__has_offset(dl)
286 || dl->ops.target.offset < 0
287 || dl->ops.target.offset >= (s64)symbol__size(sym))
288 return false;
289
290 return true;
291}
292
293static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor) 123static bool is_fused(struct annotate_browser *ab, struct disasm_line *cursor)
294{ 124{
295 struct disasm_line *pos = list_prev_entry(cursor, al.node); 125 struct disasm_line *pos = list_prev_entry(cursor, al.node);
@@ -314,39 +144,65 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
314 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 144 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
315 struct disasm_line *cursor = disasm_line(ab->selection); 145 struct disasm_line *cursor = disasm_line(ab->selection);
316 struct annotation_line *target; 146 struct annotation_line *target;
317 struct browser_line *btarget, *bcursor;
318 unsigned int from, to; 147 unsigned int from, to;
319 struct map_symbol *ms = ab->b.priv; 148 struct map_symbol *ms = ab->b.priv;
320 struct symbol *sym = ms->sym; 149 struct symbol *sym = ms->sym;
321 u8 pcnt_width = annotate_browser__pcnt_width(ab); 150 struct annotation *notes = symbol__annotation(sym);
151 u8 pcnt_width = annotation__pcnt_width(notes);
152 int width;
322 153
323 /* PLT symbols contain external offsets */ 154 /* PLT symbols contain external offsets */
324 if (strstr(sym->name, "@plt")) 155 if (strstr(sym->name, "@plt"))
325 return; 156 return;
326 157
327 if (!disasm_line__is_valid_jump(cursor, sym)) 158 if (!disasm_line__is_valid_local_jump(cursor, sym))
328 return; 159 return;
329 160
330 target = ab->offsets[cursor->ops.target.offset]; 161 /*
331 162 * This first was seen with a gcc function, _cpp_lex_token, that
332 bcursor = browser_line(&cursor->al); 163 * has the usual jumps:
333 btarget = browser_line(target); 164 *
165 * │1159e6c: ↓ jne 115aa32 <_cpp_lex_token@@Base+0xf92>
166 *
167 * I.e. jumps to a label inside that function (_cpp_lex_token), and
168 * those works, but also this kind:
169 *
170 * │1159e8b: ↓ jne c469be <cpp_named_operator2name@@Base+0xa72>
171 *
172 * I.e. jumps to another function, outside _cpp_lex_token, which
173 * are not being correctly handled generating as a side effect references
174 * to ab->offset[] entries that are set to NULL, so to make this code
175 * more robust, check that here.
176 *
177 * A proper fix for will be put in place, looking at the function
178 * name right after the '<' token and probably treating this like a
179 * 'call' instruction.
180 */
181 target = notes->offsets[cursor->ops.target.offset];
182 if (target == NULL) {
183 ui_helpline__printf("WARN: jump target inconsistency, press 'o', notes->offsets[%#x] = NULL\n",
184 cursor->ops.target.offset);
185 return;
186 }
334 187
335 if (annotate_browser__opts.hide_src_code) { 188 if (notes->options->hide_src_code) {
336 from = bcursor->idx_asm; 189 from = cursor->al.idx_asm;
337 to = btarget->idx_asm; 190 to = target->idx_asm;
338 } else { 191 } else {
339 from = (u64)bcursor->idx; 192 from = (u64)cursor->al.idx;
340 to = (u64)btarget->idx; 193 to = (u64)target->idx;
341 } 194 }
342 195
196 width = annotation__cycles_width(notes);
197
343 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); 198 ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
344 __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, 199 __ui_browser__line_arrow(browser,
200 pcnt_width + 2 + notes->widths.addr + width,
345 from, to); 201 from, to);
346 202
347 if (is_fused(ab, cursor)) { 203 if (is_fused(ab, cursor)) {
348 ui_browser__mark_fused(browser, 204 ui_browser__mark_fused(browser,
349 pcnt_width + 3 + ab->addr_width, 205 pcnt_width + 3 + notes->widths.addr + width,
350 from - 1, 206 from - 1,
351 to > from ? true : false); 207 to > from ? true : false);
352 } 208 }
@@ -354,11 +210,11 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
354 210
355static unsigned int annotate_browser__refresh(struct ui_browser *browser) 211static unsigned int annotate_browser__refresh(struct ui_browser *browser)
356{ 212{
357 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); 213 struct annotation *notes = browser__annotation(browser);
358 int ret = ui_browser__list_head_refresh(browser); 214 int ret = ui_browser__list_head_refresh(browser);
359 int pcnt_width = annotate_browser__pcnt_width(ab); 215 int pcnt_width = annotation__pcnt_width(notes);
360 216
361 if (annotate_browser__opts.jump_arrows) 217 if (notes->options->jump_arrows)
362 annotate_browser__draw_current_jump(browser); 218 annotate_browser__draw_current_jump(browser);
363 219
364 ui_browser__set_color(browser, HE_COLORSET_NORMAL); 220 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
@@ -400,6 +256,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line
400static void annotate_browser__set_top(struct annotate_browser *browser, 256static void annotate_browser__set_top(struct annotate_browser *browser,
401 struct annotation_line *pos, u32 idx) 257 struct annotation_line *pos, u32 idx)
402{ 258{
259 struct annotation *notes = browser__annotation(&browser->b);
403 unsigned back; 260 unsigned back;
404 261
405 ui_browser__refresh_dimensions(&browser->b); 262 ui_browser__refresh_dimensions(&browser->b);
@@ -409,7 +266,7 @@ static void annotate_browser__set_top(struct annotate_browser *browser,
409 while (browser->b.top_idx != 0 && back != 0) { 266 while (browser->b.top_idx != 0 && back != 0) {
410 pos = list_entry(pos->node.prev, struct annotation_line, node); 267 pos = list_entry(pos->node.prev, struct annotation_line, node);
411 268
412 if (disasm_line__filter(&browser->b, &pos->node)) 269 if (annotation_line__filter(pos, notes))
413 continue; 270 continue;
414 271
415 --browser->b.top_idx; 272 --browser->b.top_idx;
@@ -423,16 +280,12 @@ static void annotate_browser__set_top(struct annotate_browser *browser,
423static void annotate_browser__set_rb_top(struct annotate_browser *browser, 280static void annotate_browser__set_rb_top(struct annotate_browser *browser,
424 struct rb_node *nd) 281 struct rb_node *nd)
425{ 282{
426 struct browser_line *bpos; 283 struct annotation *notes = browser__annotation(&browser->b);
427 struct annotation_line *pos; 284 struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node);
428 u32 idx; 285 u32 idx = pos->idx;
429 286
430 pos = rb_entry(nd, struct annotation_line, rb_node); 287 if (notes->options->hide_src_code)
431 bpos = browser_line(pos); 288 idx = pos->idx_asm;
432
433 idx = bpos->idx;
434 if (annotate_browser__opts.hide_src_code)
435 idx = bpos->idx_asm;
436 annotate_browser__set_top(browser, pos, idx); 289 annotate_browser__set_top(browser, pos, idx);
437 browser->curr_hot = nd; 290 browser->curr_hot = nd;
438} 291}
@@ -480,47 +333,47 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
480 333
481static bool annotate_browser__toggle_source(struct annotate_browser *browser) 334static bool annotate_browser__toggle_source(struct annotate_browser *browser)
482{ 335{
336 struct annotation *notes = browser__annotation(&browser->b);
483 struct annotation_line *al; 337 struct annotation_line *al;
484 struct browser_line *bl;
485 off_t offset = browser->b.index - browser->b.top_idx; 338 off_t offset = browser->b.index - browser->b.top_idx;
486 339
487 browser->b.seek(&browser->b, offset, SEEK_CUR); 340 browser->b.seek(&browser->b, offset, SEEK_CUR);
488 al = list_entry(browser->b.top, struct annotation_line, node); 341 al = list_entry(browser->b.top, struct annotation_line, node);
489 bl = browser_line(al);
490 342
491 if (annotate_browser__opts.hide_src_code) { 343 if (notes->options->hide_src_code) {
492 if (bl->idx_asm < offset) 344 if (al->idx_asm < offset)
493 offset = bl->idx; 345 offset = al->idx;
494 346
495 browser->b.nr_entries = browser->nr_entries; 347 browser->b.nr_entries = notes->nr_entries;
496 annotate_browser__opts.hide_src_code = false; 348 notes->options->hide_src_code = false;
497 browser->b.seek(&browser->b, -offset, SEEK_CUR); 349 browser->b.seek(&browser->b, -offset, SEEK_CUR);
498 browser->b.top_idx = bl->idx - offset; 350 browser->b.top_idx = al->idx - offset;
499 browser->b.index = bl->idx; 351 browser->b.index = al->idx;
500 } else { 352 } else {
501 if (bl->idx_asm < 0) { 353 if (al->idx_asm < 0) {
502 ui_helpline__puts("Only available for assembly lines."); 354 ui_helpline__puts("Only available for assembly lines.");
503 browser->b.seek(&browser->b, -offset, SEEK_CUR); 355 browser->b.seek(&browser->b, -offset, SEEK_CUR);
504 return false; 356 return false;
505 } 357 }
506 358
507 if (bl->idx_asm < offset) 359 if (al->idx_asm < offset)
508 offset = bl->idx_asm; 360 offset = al->idx_asm;
509 361
510 browser->b.nr_entries = browser->nr_asm_entries; 362 browser->b.nr_entries = notes->nr_asm_entries;
511 annotate_browser__opts.hide_src_code = true; 363 notes->options->hide_src_code = true;
512 browser->b.seek(&browser->b, -offset, SEEK_CUR); 364 browser->b.seek(&browser->b, -offset, SEEK_CUR);
513 browser->b.top_idx = bl->idx_asm - offset; 365 browser->b.top_idx = al->idx_asm - offset;
514 browser->b.index = bl->idx_asm; 366 browser->b.index = al->idx_asm;
515 } 367 }
516 368
517 return true; 369 return true;
518} 370}
519 371
520static void annotate_browser__init_asm_mode(struct annotate_browser *browser) 372static void ui_browser__init_asm_mode(struct ui_browser *browser)
521{ 373{
522 ui_browser__reset_index(&browser->b); 374 struct annotation *notes = browser__annotation(browser);
523 browser->b.nr_entries = browser->nr_asm_entries; 375 ui_browser__reset_index(browser);
376 browser->nr_entries = notes->nr_asm_entries;
524} 377}
525 378
526#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) 379#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
@@ -531,6 +384,15 @@ static int sym_title(struct symbol *sym, struct map *map, char *title,
531 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); 384 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name);
532} 385}
533 386
387/*
388 * This can be called from external jumps, i.e. jumps from one functon
389 * to another, like from the kernel's entry_SYSCALL_64 function to the
390 * swapgs_restore_regs_and_return_to_usermode() function.
391 *
392 * So all we check here is that dl->ops.target.sym is set, if it is, just
393 * go to that function and when exiting from its disassembly, come back
394 * to the calling function.
395 */
534static bool annotate_browser__callq(struct annotate_browser *browser, 396static bool annotate_browser__callq(struct annotate_browser *browser,
535 struct perf_evsel *evsel, 397 struct perf_evsel *evsel,
536 struct hist_browser_timer *hbt) 398 struct hist_browser_timer *hbt)
@@ -538,35 +400,25 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
538 struct map_symbol *ms = browser->b.priv; 400 struct map_symbol *ms = browser->b.priv;
539 struct disasm_line *dl = disasm_line(browser->selection); 401 struct disasm_line *dl = disasm_line(browser->selection);
540 struct annotation *notes; 402 struct annotation *notes;
541 struct addr_map_symbol target = {
542 .map = ms->map,
543 .addr = map__objdump_2mem(ms->map, dl->ops.target.addr),
544 };
545 char title[SYM_TITLE_MAX_SIZE]; 403 char title[SYM_TITLE_MAX_SIZE];
546 404
547 if (!ins__is_call(&dl->ins)) 405 if (!dl->ops.target.sym) {
548 return false;
549
550 if (map_groups__find_ams(&target) ||
551 map__rip_2objdump(target.map, target.map->map_ip(target.map,
552 target.addr)) !=
553 dl->ops.target.addr) {
554 ui_helpline__puts("The called function was not found."); 406 ui_helpline__puts("The called function was not found.");
555 return true; 407 return true;
556 } 408 }
557 409
558 notes = symbol__annotation(target.sym); 410 notes = symbol__annotation(dl->ops.target.sym);
559 pthread_mutex_lock(&notes->lock); 411 pthread_mutex_lock(&notes->lock);
560 412
561 if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) { 413 if (notes->src == NULL && symbol__alloc_hist(dl->ops.target.sym) < 0) {
562 pthread_mutex_unlock(&notes->lock); 414 pthread_mutex_unlock(&notes->lock);
563 ui__warning("Not enough memory for annotating '%s' symbol!\n", 415 ui__warning("Not enough memory for annotating '%s' symbol!\n",
564 target.sym->name); 416 dl->ops.target.sym->name);
565 return true; 417 return true;
566 } 418 }
567 419
568 pthread_mutex_unlock(&notes->lock); 420 pthread_mutex_unlock(&notes->lock);
569 symbol__tui_annotate(target.sym, target.map, evsel, hbt); 421 symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt);
570 sym_title(ms->sym, ms->map, title, sizeof(title)); 422 sym_title(ms->sym, ms->map, title, sizeof(title));
571 ui_browser__show_title(&browser->b, title); 423 ui_browser__show_title(&browser->b, title);
572 return true; 424 return true;
@@ -576,23 +428,23 @@ static
576struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser, 428struct disasm_line *annotate_browser__find_offset(struct annotate_browser *browser,
577 s64 offset, s64 *idx) 429 s64 offset, s64 *idx)
578{ 430{
579 struct map_symbol *ms = browser->b.priv; 431 struct annotation *notes = browser__annotation(&browser->b);
580 struct symbol *sym = ms->sym;
581 struct annotation *notes = symbol__annotation(sym);
582 struct disasm_line *pos; 432 struct disasm_line *pos;
583 433
584 *idx = 0; 434 *idx = 0;
585 list_for_each_entry(pos, &notes->src->source, al.node) { 435 list_for_each_entry(pos, &notes->src->source, al.node) {
586 if (pos->al.offset == offset) 436 if (pos->al.offset == offset)
587 return pos; 437 return pos;
588 if (!disasm_line__filter(&browser->b, &pos->al.node)) 438 if (!annotation_line__filter(&pos->al, notes))
589 ++*idx; 439 ++*idx;
590 } 440 }
591 441
592 return NULL; 442 return NULL;
593} 443}
594 444
595static bool annotate_browser__jump(struct annotate_browser *browser) 445static bool annotate_browser__jump(struct annotate_browser *browser,
446 struct perf_evsel *evsel,
447 struct hist_browser_timer *hbt)
596{ 448{
597 struct disasm_line *dl = disasm_line(browser->selection); 449 struct disasm_line *dl = disasm_line(browser->selection);
598 u64 offset; 450 u64 offset;
@@ -601,6 +453,11 @@ static bool annotate_browser__jump(struct annotate_browser *browser)
601 if (!ins__is_jump(&dl->ins)) 453 if (!ins__is_jump(&dl->ins))
602 return false; 454 return false;
603 455
456 if (dl->ops.target.outside) {
457 annotate_browser__callq(browser, evsel, hbt);
458 return true;
459 }
460
604 offset = dl->ops.target.offset; 461 offset = dl->ops.target.offset;
605 dl = annotate_browser__find_offset(browser, offset, &idx); 462 dl = annotate_browser__find_offset(browser, offset, &idx);
606 if (dl == NULL) { 463 if (dl == NULL) {
@@ -617,14 +474,12 @@ static
617struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser, 474struct annotation_line *annotate_browser__find_string(struct annotate_browser *browser,
618 char *s, s64 *idx) 475 char *s, s64 *idx)
619{ 476{
620 struct map_symbol *ms = browser->b.priv; 477 struct annotation *notes = browser__annotation(&browser->b);
621 struct symbol *sym = ms->sym;
622 struct annotation *notes = symbol__annotation(sym);
623 struct annotation_line *al = browser->selection; 478 struct annotation_line *al = browser->selection;
624 479
625 *idx = browser->b.index; 480 *idx = browser->b.index;
626 list_for_each_entry_continue(al, &notes->src->source, node) { 481 list_for_each_entry_continue(al, &notes->src->source, node) {
627 if (disasm_line__filter(&browser->b, &al->node)) 482 if (annotation_line__filter(al, notes))
628 continue; 483 continue;
629 484
630 ++*idx; 485 ++*idx;
@@ -656,14 +511,12 @@ static
656struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser, 511struct annotation_line *annotate_browser__find_string_reverse(struct annotate_browser *browser,
657 char *s, s64 *idx) 512 char *s, s64 *idx)
658{ 513{
659 struct map_symbol *ms = browser->b.priv; 514 struct annotation *notes = browser__annotation(&browser->b);
660 struct symbol *sym = ms->sym;
661 struct annotation *notes = symbol__annotation(sym);
662 struct annotation_line *al = browser->selection; 515 struct annotation_line *al = browser->selection;
663 516
664 *idx = browser->b.index; 517 *idx = browser->b.index;
665 list_for_each_entry_continue_reverse(al, &notes->src->source, node) { 518 list_for_each_entry_continue_reverse(al, &notes->src->source, node) {
666 if (disasm_line__filter(&browser->b, &al->node)) 519 if (annotation_line__filter(al, notes))
667 continue; 520 continue;
668 521
669 --*idx; 522 --*idx;
@@ -739,19 +592,6 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
739 return __annotate_browser__search_reverse(browser); 592 return __annotate_browser__search_reverse(browser);
740} 593}
741 594
742static void annotate_browser__update_addr_width(struct annotate_browser *browser)
743{
744 if (annotate_browser__opts.use_offset)
745 browser->target_width = browser->min_addr_width;
746 else
747 browser->target_width = browser->max_addr_width;
748
749 browser->addr_width = browser->target_width;
750
751 if (annotate_browser__opts.show_nr_jumps)
752 browser->addr_width += browser->jumps_width + 1;
753}
754
755static int annotate_browser__run(struct annotate_browser *browser, 595static int annotate_browser__run(struct annotate_browser *browser,
756 struct perf_evsel *evsel, 596 struct perf_evsel *evsel,
757 struct hist_browser_timer *hbt) 597 struct hist_browser_timer *hbt)
@@ -759,6 +599,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
759 struct rb_node *nd = NULL; 599 struct rb_node *nd = NULL;
760 struct map_symbol *ms = browser->b.priv; 600 struct map_symbol *ms = browser->b.priv;
761 struct symbol *sym = ms->sym; 601 struct symbol *sym = ms->sym;
602 struct annotation *notes = symbol__annotation(ms->sym);
762 const char *help = "Press 'h' for help on key bindings"; 603 const char *help = "Press 'h' for help on key bindings";
763 int delay_secs = hbt ? hbt->refresh : 0; 604 int delay_secs = hbt ? hbt->refresh : 0;
764 int key; 605 int key;
@@ -833,6 +674,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
833 "t Circulate percent, total period, samples view\n" 674 "t Circulate percent, total period, samples view\n"
834 "/ Search string\n" 675 "/ Search string\n"
835 "k Toggle line numbers\n" 676 "k Toggle line numbers\n"
677 "P Print to [symbol_name].annotation file.\n"
836 "r Run available scripts\n" 678 "r Run available scripts\n"
837 "? Search string backwards\n"); 679 "? Search string backwards\n");
838 continue; 680 continue;
@@ -842,8 +684,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
842 continue; 684 continue;
843 } 685 }
844 case 'k': 686 case 'k':
845 annotate_browser__opts.show_linenr = 687 notes->options->show_linenr = !notes->options->show_linenr;
846 !annotate_browser__opts.show_linenr;
847 break; 688 break;
848 case 'H': 689 case 'H':
849 nd = browser->curr_hot; 690 nd = browser->curr_hot;
@@ -853,15 +694,15 @@ static int annotate_browser__run(struct annotate_browser *browser,
853 ui_helpline__puts(help); 694 ui_helpline__puts(help);
854 continue; 695 continue;
855 case 'o': 696 case 'o':
856 annotate_browser__opts.use_offset = !annotate_browser__opts.use_offset; 697 notes->options->use_offset = !notes->options->use_offset;
857 annotate_browser__update_addr_width(browser); 698 annotation__update_column_widths(notes);
858 continue; 699 continue;
859 case 'j': 700 case 'j':
860 annotate_browser__opts.jump_arrows = !annotate_browser__opts.jump_arrows; 701 notes->options->jump_arrows = !notes->options->jump_arrows;
861 continue; 702 continue;
862 case 'J': 703 case 'J':
863 annotate_browser__opts.show_nr_jumps = !annotate_browser__opts.show_nr_jumps; 704 notes->options->show_nr_jumps = !notes->options->show_nr_jumps;
864 annotate_browser__update_addr_width(browser); 705 annotation__update_column_widths(notes);
865 continue; 706 continue;
866 case '/': 707 case '/':
867 if (annotate_browser__search(browser, delay_secs)) { 708 if (annotate_browser__search(browser, delay_secs)) {
@@ -887,7 +728,7 @@ show_help:
887 browser->b.height, 728 browser->b.height,
888 browser->b.index, 729 browser->b.index,
889 browser->b.top_idx, 730 browser->b.top_idx,
890 browser->nr_asm_entries); 731 notes->nr_asm_entries);
891 } 732 }
892 continue; 733 continue;
893 case K_ENTER: 734 case K_ENTER:
@@ -903,22 +744,25 @@ show_help:
903 goto show_sup_ins; 744 goto show_sup_ins;
904 else if (ins__is_ret(&dl->ins)) 745 else if (ins__is_ret(&dl->ins))
905 goto out; 746 goto out;
906 else if (!(annotate_browser__jump(browser) || 747 else if (!(annotate_browser__jump(browser, evsel, hbt) ||
907 annotate_browser__callq(browser, evsel, hbt))) { 748 annotate_browser__callq(browser, evsel, hbt))) {
908show_sup_ins: 749show_sup_ins:
909 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); 750 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
910 } 751 }
911 continue; 752 continue;
912 } 753 }
754 case 'P':
755 map_symbol__annotation_dump(ms, evsel);
756 continue;
913 case 't': 757 case 't':
914 if (annotate_browser__opts.show_total_period) { 758 if (notes->options->show_total_period) {
915 annotate_browser__opts.show_total_period = false; 759 notes->options->show_total_period = false;
916 annotate_browser__opts.show_nr_samples = true; 760 notes->options->show_nr_samples = true;
917 } else if (annotate_browser__opts.show_nr_samples) 761 } else if (notes->options->show_nr_samples)
918 annotate_browser__opts.show_nr_samples = false; 762 notes->options->show_nr_samples = false;
919 else 763 else
920 annotate_browser__opts.show_total_period = true; 764 notes->options->show_total_period = true;
921 annotate_browser__update_addr_width(browser); 765 annotation__update_column_widths(notes);
922 continue; 766 continue;
923 case K_LEFT: 767 case K_LEFT:
924 case K_ESC: 768 case K_ESC:
@@ -940,12 +784,6 @@ out:
940int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, 784int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
941 struct hist_browser_timer *hbt) 785 struct hist_browser_timer *hbt)
942{ 786{
943 /* Set default value for show_total_period and show_nr_samples */
944 annotate_browser__opts.show_total_period =
945 symbol_conf.show_total_period;
946 annotate_browser__opts.show_nr_samples =
947 symbol_conf.show_nr_samples;
948
949 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); 787 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
950} 788}
951 789
@@ -959,129 +797,11 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
959 return map_symbol__tui_annotate(&he->ms, evsel, hbt); 797 return map_symbol__tui_annotate(&he->ms, evsel, hbt);
960} 798}
961 799
962
963static unsigned count_insn(struct annotate_browser *browser, u64 start, u64 end)
964{
965 unsigned n_insn = 0;
966 u64 offset;
967
968 for (offset = start; offset <= end; offset++) {
969 if (browser->offsets[offset])
970 n_insn++;
971 }
972 return n_insn;
973}
974
975static void count_and_fill(struct annotate_browser *browser, u64 start, u64 end,
976 struct cyc_hist *ch)
977{
978 unsigned n_insn;
979 u64 offset;
980
981 n_insn = count_insn(browser, start, end);
982 if (n_insn && ch->num && ch->cycles) {
983 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
984
985 /* Hide data when there are too many overlaps. */
986 if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
987 return;
988
989 for (offset = start; offset <= end; offset++) {
990 struct annotation_line *al = browser->offsets[offset];
991
992 if (al)
993 al->ipc = ipc;
994 }
995 }
996}
997
998/*
999 * This should probably be in util/annotate.c to share with the tty
1000 * annotate, but right now we need the per byte offsets arrays,
1001 * which are only here.
1002 */
1003static void annotate__compute_ipc(struct annotate_browser *browser, size_t size,
1004 struct symbol *sym)
1005{
1006 u64 offset;
1007 struct annotation *notes = symbol__annotation(sym);
1008
1009 if (!notes->src || !notes->src->cycles_hist)
1010 return;
1011
1012 pthread_mutex_lock(&notes->lock);
1013 for (offset = 0; offset < size; ++offset) {
1014 struct cyc_hist *ch;
1015
1016 ch = &notes->src->cycles_hist[offset];
1017 if (ch && ch->cycles) {
1018 struct annotation_line *al;
1019
1020 if (ch->have_start)
1021 count_and_fill(browser, ch->start, offset, ch);
1022 al = browser->offsets[offset];
1023 if (al && ch->num_aggr)
1024 al->cycles = ch->cycles_aggr / ch->num_aggr;
1025 browser->have_cycles = true;
1026 }
1027 }
1028 pthread_mutex_unlock(&notes->lock);
1029}
1030
1031static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
1032 size_t size)
1033{
1034 u64 offset;
1035 struct map_symbol *ms = browser->b.priv;
1036 struct symbol *sym = ms->sym;
1037
1038 /* PLT symbols contain external offsets */
1039 if (strstr(sym->name, "@plt"))
1040 return;
1041
1042 for (offset = 0; offset < size; ++offset) {
1043 struct annotation_line *al = browser->offsets[offset];
1044 struct disasm_line *dl;
1045 struct browser_line *blt;
1046
1047 dl = disasm_line(al);
1048
1049 if (!disasm_line__is_valid_jump(dl, sym))
1050 continue;
1051
1052 al = browser->offsets[dl->ops.target.offset];
1053
1054 /*
1055 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
1056 * have to adjust to the previous offset?
1057 */
1058 if (al == NULL)
1059 continue;
1060
1061 blt = browser_line(al);
1062 if (++blt->jump_sources > browser->max_jump_sources)
1063 browser->max_jump_sources = blt->jump_sources;
1064
1065 ++browser->nr_jumps;
1066 }
1067}
1068
1069static inline int width_jumps(int n)
1070{
1071 if (n >= 100)
1072 return 5;
1073 if (n / 10)
1074 return 2;
1075 return 1;
1076}
1077
1078int symbol__tui_annotate(struct symbol *sym, struct map *map, 800int symbol__tui_annotate(struct symbol *sym, struct map *map,
1079 struct perf_evsel *evsel, 801 struct perf_evsel *evsel,
1080 struct hist_browser_timer *hbt) 802 struct hist_browser_timer *hbt)
1081{ 803{
1082 struct annotation_line *al; 804 struct annotation *notes = symbol__annotation(sym);
1083 struct annotation *notes;
1084 size_t size;
1085 struct map_symbol ms = { 805 struct map_symbol ms = {
1086 .map = map, 806 .map = map,
1087 .sym = sym, 807 .sym = sym,
@@ -1097,26 +817,14 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1097 }, 817 },
1098 }; 818 };
1099 int ret = -1, err; 819 int ret = -1, err;
1100 int nr_pcnt = 1;
1101 820
1102 if (sym == NULL) 821 if (sym == NULL)
1103 return -1; 822 return -1;
1104 823
1105 size = symbol__size(sym);
1106
1107 if (map->dso->annotate_warned) 824 if (map->dso->annotate_warned)
1108 return -1; 825 return -1;
1109 826
1110 browser.offsets = zalloc(size * sizeof(struct annotation_line *)); 827 err = symbol__annotate2(sym, map, evsel, &annotation__default_options, &browser.arch);
1111 if (browser.offsets == NULL) {
1112 ui__error("Not enough memory!");
1113 return -1;
1114 }
1115
1116 if (perf_evsel__is_group_event(evsel))
1117 nr_pcnt = evsel->nr_members;
1118
1119 err = symbol__annotate(sym, map, evsel, sizeof(struct browser_line), &browser.arch);
1120 if (err) { 828 if (err) {
1121 char msg[BUFSIZ]; 829 char msg[BUFSIZ];
1122 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); 830 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
@@ -1124,110 +832,21 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1124 goto out_free_offsets; 832 goto out_free_offsets;
1125 } 833 }
1126 834
1127 symbol__calc_percent(sym, evsel);
1128
1129 ui_helpline__push("Press ESC to exit"); 835 ui_helpline__push("Press ESC to exit");
1130 836
1131 notes = symbol__annotation(sym); 837 browser.b.width = notes->max_line_len;
1132 browser.start = map__rip_2objdump(map, sym->start); 838 browser.b.nr_entries = notes->nr_entries;
1133
1134 list_for_each_entry(al, &notes->src->source, node) {
1135 struct browser_line *bpos;
1136 size_t line_len = strlen(al->line);
1137
1138 if (browser.b.width < line_len)
1139 browser.b.width = line_len;
1140 bpos = browser_line(al);
1141 bpos->idx = browser.nr_entries++;
1142 if (al->offset != -1) {
1143 bpos->idx_asm = browser.nr_asm_entries++;
1144 /*
1145 * FIXME: short term bandaid to cope with assembly
1146 * routines that comes with labels in the same column
1147 * as the address in objdump, sigh.
1148 *
1149 * E.g. copy_user_generic_unrolled
1150 */
1151 if (al->offset < (s64)size)
1152 browser.offsets[al->offset] = al;
1153 } else
1154 bpos->idx_asm = -1;
1155 }
1156
1157 annotate_browser__mark_jump_targets(&browser, size);
1158 annotate__compute_ipc(&browser, size, sym);
1159
1160 browser.addr_width = browser.target_width = browser.min_addr_width = hex_width(size);
1161 browser.max_addr_width = hex_width(sym->end);
1162 browser.jumps_width = width_jumps(browser.max_jump_sources);
1163 browser.nr_events = nr_pcnt;
1164 browser.b.nr_entries = browser.nr_entries;
1165 browser.b.entries = &notes->src->source, 839 browser.b.entries = &notes->src->source,
1166 browser.b.width += 18; /* Percentage */ 840 browser.b.width += 18; /* Percentage */
1167 841
1168 if (annotate_browser__opts.hide_src_code) 842 if (notes->options->hide_src_code)
1169 annotate_browser__init_asm_mode(&browser); 843 ui_browser__init_asm_mode(&browser.b);
1170
1171 annotate_browser__update_addr_width(&browser);
1172 844
1173 ret = annotate_browser__run(&browser, evsel, hbt); 845 ret = annotate_browser__run(&browser, evsel, hbt);
1174 846
1175 annotated_source__purge(notes->src); 847 annotated_source__purge(notes->src);
1176 848
1177out_free_offsets: 849out_free_offsets:
1178 free(browser.offsets); 850 zfree(&notes->offsets);
1179 return ret; 851 return ret;
1180} 852}
1181
1182#define ANNOTATE_CFG(n) \
1183 { .name = #n, .value = &annotate_browser__opts.n, }
1184
1185/*
1186 * Keep the entries sorted, they are bsearch'ed
1187 */
1188static struct annotate_config {
1189 const char *name;
1190 bool *value;
1191} annotate__configs[] = {
1192 ANNOTATE_CFG(hide_src_code),
1193 ANNOTATE_CFG(jump_arrows),
1194 ANNOTATE_CFG(show_linenr),
1195 ANNOTATE_CFG(show_nr_jumps),
1196 ANNOTATE_CFG(show_nr_samples),
1197 ANNOTATE_CFG(show_total_period),
1198 ANNOTATE_CFG(use_offset),
1199};
1200
1201#undef ANNOTATE_CFG
1202
1203static int annotate_config__cmp(const void *name, const void *cfgp)
1204{
1205 const struct annotate_config *cfg = cfgp;
1206
1207 return strcmp(name, cfg->name);
1208}
1209
1210static int annotate__config(const char *var, const char *value,
1211 void *data __maybe_unused)
1212{
1213 struct annotate_config *cfg;
1214 const char *name;
1215
1216 if (!strstarts(var, "annotate."))
1217 return 0;
1218
1219 name = var + 9;
1220 cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs),
1221 sizeof(struct annotate_config), annotate_config__cmp);
1222
1223 if (cfg == NULL)
1224 ui__warning("%s variable unknown, ignoring...", var);
1225 else
1226 *cfg->value = perf_config_bool(name, value);
1227 return 0;
1228}
1229
1230void annotate_browser__init(void)
1231{
1232 perf_config(annotate__config, NULL);
1233}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 6495ee55d9c3..8b4e82548f8e 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -2223,7 +2223,7 @@ static int perf_evsel_browser_title(struct hist_browser *browser,
2223 u64 nr_events = hists->stats.total_period; 2223 u64 nr_events = hists->stats.total_period;
2224 struct perf_evsel *evsel = hists_to_evsel(hists); 2224 struct perf_evsel *evsel = hists_to_evsel(hists);
2225 const char *ev_name = perf_evsel__name(evsel); 2225 const char *ev_name = perf_evsel__name(evsel);
2226 char buf[512]; 2226 char buf[512], sample_freq_str[64] = "";
2227 size_t buflen = sizeof(buf); 2227 size_t buflen = sizeof(buf);
2228 char ref[30] = " show reference callgraph, "; 2228 char ref[30] = " show reference callgraph, ";
2229 bool enable_ref = false; 2229 bool enable_ref = false;
@@ -2255,10 +2255,15 @@ static int perf_evsel_browser_title(struct hist_browser *browser,
2255 if (symbol_conf.show_ref_callgraph && 2255 if (symbol_conf.show_ref_callgraph &&
2256 strstr(ev_name, "call-graph=no")) 2256 strstr(ev_name, "call-graph=no"))
2257 enable_ref = true; 2257 enable_ref = true;
2258
2259 if (!is_report_browser(hbt))
2260 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2261
2258 nr_samples = convert_unit(nr_samples, &unit); 2262 nr_samples = convert_unit(nr_samples, &unit);
2259 printed = scnprintf(bf, size, 2263 printed = scnprintf(bf, size,
2260 "Samples: %lu%c of event '%s',%sEvent count (approx.): %" PRIu64, 2264 "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2261 nr_samples, unit, ev_name, enable_ref ? ref : " ", nr_events); 2265 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2266 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2262 2267
2263 2268
2264 if (hists->uid_filter_str) 2269 if (hists->uid_filter_str)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 25dd1e0ecc58..6832fcb2e6ff 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -840,15 +840,11 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp)
840 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 840 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
841 const char *name; 841 const char *name;
842 842
843 if (stats->nr_events[i] == 0)
844 continue;
845
846 name = perf_event__name(i); 843 name = perf_event__name(i);
847 if (!strcmp(name, "UNKNOWN")) 844 if (!strcmp(name, "UNKNOWN"))
848 continue; 845 continue;
849 846
850 ret += fprintf(fp, "%16s events: %10d\n", name, 847 ret += fprintf(fp, "%16s events: %10d\n", name, stats->nr_events[i]);
851 stats->nr_events[i]);
852 } 848 }
853 849
854 return ret; 850 return ret;
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index ea0a452550b0..8052373bcd6a 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -106,6 +106,7 @@ libperf-y += units.o
106libperf-y += time-utils.o 106libperf-y += time-utils.o
107libperf-y += expr-bison.o 107libperf-y += expr-bison.o
108libperf-y += branch.o 108libperf-y += branch.o
109libperf-y += mem2node.o
109 110
110libperf-$(CONFIG_LIBBPF) += bpf-loader.o 111libperf-$(CONFIG_LIBBPF) += bpf-loader.o
111libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 112libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 28b233c3dcbe..3a428d7c59b9 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -14,6 +14,7 @@
14#include "sort.h" 14#include "sort.h"
15#include "build-id.h" 15#include "build-id.h"
16#include "color.h" 16#include "color.h"
17#include "config.h"
17#include "cache.h" 18#include "cache.h"
18#include "symbol.h" 19#include "symbol.h"
19#include "debug.h" 20#include "debug.h"
@@ -27,8 +28,25 @@
27#include <linux/bitops.h> 28#include <linux/bitops.h>
28#include <linux/kernel.h> 29#include <linux/kernel.h>
29 30
31/* FIXME: For the HE_COLORSET */
32#include "ui/browser.h"
33
34/*
35 * FIXME: Using the same values as slang.h,
36 * but that header may not be available everywhere
37 */
38#define LARROW_CHAR ((unsigned char)',')
39#define RARROW_CHAR ((unsigned char)'+')
40#define DARROW_CHAR ((unsigned char)'.')
41#define UARROW_CHAR ((unsigned char)'-')
42
30#include "sane_ctype.h" 43#include "sane_ctype.h"
31 44
45struct annotation_options annotation__default_options = {
46 .use_offset = true,
47 .jump_arrows = true,
48};
49
32const char *disassembler_style; 50const char *disassembler_style;
33const char *objdump_path; 51const char *objdump_path;
34static regex_t file_lineno; 52static regex_t file_lineno;
@@ -184,9 +202,13 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
184 return arch->ins_is_fused(arch, ins1, ins2); 202 return arch->ins_is_fused(arch, ins1, ins2);
185} 203}
186 204
187static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 205static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
188{ 206{
189 char *endptr, *tok, *name; 207 char *endptr, *tok, *name;
208 struct map *map = ms->map;
209 struct addr_map_symbol target = {
210 .map = map,
211 };
190 212
191 ops->target.addr = strtoull(ops->raw, &endptr, 16); 213 ops->target.addr = strtoull(ops->raw, &endptr, 16);
192 214
@@ -208,32 +230,36 @@ static int call__parse(struct arch *arch, struct ins_operands *ops, struct map *
208 ops->target.name = strdup(name); 230 ops->target.name = strdup(name);
209 *tok = '>'; 231 *tok = '>';
210 232
211 return ops->target.name == NULL ? -1 : 0; 233 if (ops->target.name == NULL)
234 return -1;
235find_target:
236 target.addr = map__objdump_2mem(map, ops->target.addr);
212 237
213indirect_call: 238 if (map_groups__find_ams(&target) == 0 &&
214 tok = strchr(endptr, '*'); 239 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
215 if (tok == NULL) { 240 ops->target.sym = target.sym;
216 struct symbol *sym = map__find_symbol(map, map->map_ip(map, ops->target.addr));
217 if (sym != NULL)
218 ops->target.name = strdup(sym->name);
219 else
220 ops->target.addr = 0;
221 return 0;
222 }
223 241
224 ops->target.addr = strtoull(tok + 1, NULL, 16);
225 return 0; 242 return 0;
243
244indirect_call:
245 tok = strchr(endptr, '*');
246 if (tok != NULL)
247 ops->target.addr = strtoull(tok + 1, NULL, 16);
248 goto find_target;
226} 249}
227 250
228static int call__scnprintf(struct ins *ins, char *bf, size_t size, 251static int call__scnprintf(struct ins *ins, char *bf, size_t size,
229 struct ins_operands *ops) 252 struct ins_operands *ops)
230{ 253{
231 if (ops->target.name) 254 if (ops->target.sym)
232 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name); 255 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
233 256
234 if (ops->target.addr == 0) 257 if (ops->target.addr == 0)
235 return ins__raw_scnprintf(ins, bf, size, ops); 258 return ins__raw_scnprintf(ins, bf, size, ops);
236 259
260 if (ops->target.name)
261 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name);
262
237 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr); 263 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr);
238} 264}
239 265
@@ -244,14 +270,29 @@ static struct ins_ops call_ops = {
244 270
245bool ins__is_call(const struct ins *ins) 271bool ins__is_call(const struct ins *ins)
246{ 272{
247 return ins->ops == &call_ops; 273 return ins->ops == &call_ops || ins->ops == &s390_call_ops;
248} 274}
249 275
250static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) 276static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms)
251{ 277{
252 const char *s = strchr(ops->raw, '+'); 278 struct map *map = ms->map;
279 struct symbol *sym = ms->sym;
280 struct addr_map_symbol target = {
281 .map = map,
282 };
253 const char *c = strchr(ops->raw, ','); 283 const char *c = strchr(ops->raw, ',');
254 284 u64 start, end;
285 /*
286 * Examples of lines to parse for the _cpp_lex_token@@Base
287 * function:
288 *
289 * 1159e6c: jne 115aa32 <_cpp_lex_token@@Base+0xf92>
290 * 1159e8b: jne c469be <cpp_named_operator2name@@Base+0xa72>
291 *
292 * The first is a jump to an offset inside the same function,
293 * the second is to another function, i.e. that 0xa72 is an
294 * offset in the cpp_named_operator2name@@base function.
295 */
255 /* 296 /*
256 * skip over possible up to 2 operands to get to address, e.g.: 297 * skip over possible up to 2 operands to get to address, e.g.:
257 * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0> 298 * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
@@ -267,8 +308,36 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
267 ops->target.addr = strtoull(ops->raw, NULL, 16); 308 ops->target.addr = strtoull(ops->raw, NULL, 16);
268 } 309 }
269 310
270 if (s++ != NULL) { 311 target.addr = map__objdump_2mem(map, ops->target.addr);
271 ops->target.offset = strtoull(s, NULL, 16); 312 start = map->unmap_ip(map, sym->start),
313 end = map->unmap_ip(map, sym->end);
314
315 ops->target.outside = target.addr < start || target.addr > end;
316
317 /*
318 * FIXME: things like this in _cpp_lex_token (gcc's cc1 program):
319
320 cpp_named_operator2name@@Base+0xa72
321
322 * Point to a place that is after the cpp_named_operator2name
323 * boundaries, i.e. in the ELF symbol table for cc1
324 * cpp_named_operator2name is marked as being 32-bytes long, but it in
325 * fact is much larger than that, so we seem to need a symbols__find()
326 * routine that looks for >= current->start and < next_symbol->start,
327 * possibly just for C++ objects?
328 *
329 * For now lets just make some progress by marking jumps to outside the
330 * current function as call like.
331 *
332 * Actual navigation will come next, with further understanding of how
333 * the symbol searching and disassembly should be done.
334 */
335 if (map_groups__find_ams(&target) == 0 &&
336 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
337 ops->target.sym = target.sym;
338
339 if (!ops->target.outside) {
340 ops->target.offset = target.addr - start;
272 ops->target.offset_avail = true; 341 ops->target.offset_avail = true;
273 } else { 342 } else {
274 ops->target.offset_avail = false; 343 ops->target.offset_avail = false;
@@ -280,11 +349,15 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
280static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 349static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
281 struct ins_operands *ops) 350 struct ins_operands *ops)
282{ 351{
283 const char *c = strchr(ops->raw, ','); 352 const char *c;
284 353
285 if (!ops->target.addr || ops->target.offset < 0) 354 if (!ops->target.addr || ops->target.offset < 0)
286 return ins__raw_scnprintf(ins, bf, size, ops); 355 return ins__raw_scnprintf(ins, bf, size, ops);
287 356
357 if (ops->target.outside && ops->target.sym != NULL)
358 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
359
360 c = strchr(ops->raw, ',');
288 if (c != NULL) { 361 if (c != NULL) {
289 const char *c2 = strchr(c + 1, ','); 362 const char *c2 = strchr(c + 1, ',');
290 363
@@ -340,7 +413,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
340 return 0; 413 return 0;
341} 414}
342 415
343static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *map) 416static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
344{ 417{
345 ops->locked.ops = zalloc(sizeof(*ops->locked.ops)); 418 ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
346 if (ops->locked.ops == NULL) 419 if (ops->locked.ops == NULL)
@@ -355,7 +428,7 @@ static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *
355 goto out_free_ops; 428 goto out_free_ops;
356 429
357 if (ops->locked.ins.ops->parse && 430 if (ops->locked.ins.ops->parse &&
358 ops->locked.ins.ops->parse(arch, ops->locked.ops, map) < 0) 431 ops->locked.ins.ops->parse(arch, ops->locked.ops, ms) < 0)
359 goto out_free_ops; 432 goto out_free_ops;
360 433
361 return 0; 434 return 0;
@@ -398,7 +471,7 @@ static struct ins_ops lock_ops = {
398 .scnprintf = lock__scnprintf, 471 .scnprintf = lock__scnprintf,
399}; 472};
400 473
401static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map *map __maybe_unused) 474static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
402{ 475{
403 char *s = strchr(ops->raw, ','), *target, *comment, prev; 476 char *s = strchr(ops->raw, ','), *target, *comment, prev;
404 477
@@ -459,7 +532,7 @@ static struct ins_ops mov_ops = {
459 .scnprintf = mov__scnprintf, 532 .scnprintf = mov__scnprintf,
460}; 533};
461 534
462static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map *map __maybe_unused) 535static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
463{ 536{
464 char *target, *comment, *s, prev; 537 char *target, *comment, *s, prev;
465 538
@@ -826,6 +899,66 @@ int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
826 return err; 899 return err;
827} 900}
828 901
902static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64 end)
903{
904 unsigned n_insn = 0;
905 u64 offset;
906
907 for (offset = start; offset <= end; offset++) {
908 if (notes->offsets[offset])
909 n_insn++;
910 }
911 return n_insn;
912}
913
914static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch)
915{
916 unsigned n_insn;
917 u64 offset;
918
919 n_insn = annotation__count_insn(notes, start, end);
920 if (n_insn && ch->num && ch->cycles) {
921 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
922
923 /* Hide data when there are too many overlaps. */
924 if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
925 return;
926
927 for (offset = start; offset <= end; offset++) {
928 struct annotation_line *al = notes->offsets[offset];
929
930 if (al)
931 al->ipc = ipc;
932 }
933 }
934}
935
936void annotation__compute_ipc(struct annotation *notes, size_t size)
937{
938 u64 offset;
939
940 if (!notes->src || !notes->src->cycles_hist)
941 return;
942
943 pthread_mutex_lock(&notes->lock);
944 for (offset = 0; offset < size; ++offset) {
945 struct cyc_hist *ch;
946
947 ch = &notes->src->cycles_hist[offset];
948 if (ch && ch->cycles) {
949 struct annotation_line *al;
950
951 if (ch->have_start)
952 annotation__count_and_fill(notes, ch->start, offset, ch);
953 al = notes->offsets[offset];
954 if (al && ch->num_aggr)
955 al->cycles = ch->cycles_aggr / ch->num_aggr;
956 notes->have_cycles = true;
957 }
958 }
959 pthread_mutex_unlock(&notes->lock);
960}
961
829int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample, 962int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
830 int evidx) 963 int evidx)
831{ 964{
@@ -838,14 +971,14 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *samp
838 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample); 971 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip, sample);
839} 972}
840 973
841static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 974static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
842{ 975{
843 dl->ins.ops = ins__find(arch, dl->ins.name); 976 dl->ins.ops = ins__find(arch, dl->ins.name);
844 977
845 if (!dl->ins.ops) 978 if (!dl->ins.ops)
846 return; 979 return;
847 980
848 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, map) < 0) 981 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, ms) < 0)
849 dl->ins.ops = NULL; 982 dl->ins.ops = NULL;
850} 983}
851 984
@@ -882,7 +1015,7 @@ out_free_name:
882struct annotate_args { 1015struct annotate_args {
883 size_t privsize; 1016 size_t privsize;
884 struct arch *arch; 1017 struct arch *arch;
885 struct map *map; 1018 struct map_symbol ms;
886 struct perf_evsel *evsel; 1019 struct perf_evsel *evsel;
887 s64 offset; 1020 s64 offset;
888 char *line; 1021 char *line;
@@ -964,7 +1097,7 @@ static struct disasm_line *disasm_line__new(struct annotate_args *args)
964 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0) 1097 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
965 goto out_free_line; 1098 goto out_free_line;
966 1099
967 disasm_line__init_ins(dl, args->arch, args->map); 1100 disasm_line__init_ins(dl, args->arch, &args->ms);
968 } 1101 }
969 } 1102 }
970 1103
@@ -1222,7 +1355,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1222 struct annotate_args *args, 1355 struct annotate_args *args,
1223 int *line_nr) 1356 int *line_nr)
1224{ 1357{
1225 struct map *map = args->map; 1358 struct map *map = args->ms.map;
1226 struct annotation *notes = symbol__annotation(sym); 1359 struct annotation *notes = symbol__annotation(sym);
1227 struct disasm_line *dl; 1360 struct disasm_line *dl;
1228 char *line = NULL, *parsed_line, *tmp, *tmp2; 1361 char *line = NULL, *parsed_line, *tmp, *tmp2;
@@ -1269,6 +1402,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1269 args->offset = offset; 1402 args->offset = offset;
1270 args->line = parsed_line; 1403 args->line = parsed_line;
1271 args->line_nr = *line_nr; 1404 args->line_nr = *line_nr;
1405 args->ms.sym = sym;
1272 1406
1273 dl = disasm_line__new(args); 1407 dl = disasm_line__new(args);
1274 free(line); 1408 free(line);
@@ -1277,14 +1411,14 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1277 if (dl == NULL) 1411 if (dl == NULL)
1278 return -1; 1412 return -1;
1279 1413
1280 if (!disasm_line__has_offset(dl)) { 1414 if (!disasm_line__has_local_offset(dl)) {
1281 dl->ops.target.offset = dl->ops.target.addr - 1415 dl->ops.target.offset = dl->ops.target.addr -
1282 map__rip_2objdump(map, sym->start); 1416 map__rip_2objdump(map, sym->start);
1283 dl->ops.target.offset_avail = true; 1417 dl->ops.target.offset_avail = true;
1284 } 1418 }
1285 1419
1286 /* kcore has no symbols, so add the call target name */ 1420 /* kcore has no symbols, so add the call target symbol */
1287 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.name) { 1421 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
1288 struct addr_map_symbol target = { 1422 struct addr_map_symbol target = {
1289 .map = map, 1423 .map = map,
1290 .addr = dl->ops.target.addr, 1424 .addr = dl->ops.target.addr,
@@ -1292,7 +1426,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1292 1426
1293 if (!map_groups__find_ams(&target) && 1427 if (!map_groups__find_ams(&target) &&
1294 target.sym->start == target.al_addr) 1428 target.sym->start == target.al_addr)
1295 dl->ops.target.name = strdup(target.sym->name); 1429 dl->ops.target.sym = target.sym;
1296 } 1430 }
1297 1431
1298 annotation_line__add(&dl->al, &notes->src->source); 1432 annotation_line__add(&dl->al, &notes->src->source);
@@ -1421,9 +1555,9 @@ fallback:
1421 1555
1422static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) 1556static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1423{ 1557{
1424 struct map *map = args->map; 1558 struct map *map = args->ms.map;
1425 struct dso *dso = map->dso; 1559 struct dso *dso = map->dso;
1426 char command[PATH_MAX * 2]; 1560 char *command;
1427 FILE *file; 1561 FILE *file;
1428 char symfs_filename[PATH_MAX]; 1562 char symfs_filename[PATH_MAX];
1429 struct kcore_extract kce; 1563 struct kcore_extract kce;
@@ -1464,7 +1598,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1464 strcpy(symfs_filename, tmp); 1598 strcpy(symfs_filename, tmp);
1465 } 1599 }
1466 1600
1467 snprintf(command, sizeof(command), 1601 err = asprintf(&command,
1468 "%s %s%s --start-address=0x%016" PRIx64 1602 "%s %s%s --start-address=0x%016" PRIx64
1469 " --stop-address=0x%016" PRIx64 1603 " --stop-address=0x%016" PRIx64
1470 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand", 1604 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
@@ -1477,12 +1611,17 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1477 symbol_conf.annotate_src ? "-S" : "", 1611 symbol_conf.annotate_src ? "-S" : "",
1478 symfs_filename, symfs_filename); 1612 symfs_filename, symfs_filename);
1479 1613
1614 if (err < 0) {
1615 pr_err("Failure allocating memory for the command to run\n");
1616 goto out_remove_tmp;
1617 }
1618
1480 pr_debug("Executing: %s\n", command); 1619 pr_debug("Executing: %s\n", command);
1481 1620
1482 err = -1; 1621 err = -1;
1483 if (pipe(stdout_fd) < 0) { 1622 if (pipe(stdout_fd) < 0) {
1484 pr_err("Failure creating the pipe to run %s\n", command); 1623 pr_err("Failure creating the pipe to run %s\n", command);
1485 goto out_remove_tmp; 1624 goto out_free_command;
1486 } 1625 }
1487 1626
1488 pid = fork(); 1627 pid = fork();
@@ -1509,7 +1648,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1509 * If we were using debug info should retry with 1648 * If we were using debug info should retry with
1510 * original binary. 1649 * original binary.
1511 */ 1650 */
1512 goto out_remove_tmp; 1651 goto out_free_command;
1513 } 1652 }
1514 1653
1515 nline = 0; 1654 nline = 0;
@@ -1537,6 +1676,8 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1537 1676
1538 fclose(file); 1677 fclose(file);
1539 err = 0; 1678 err = 0;
1679out_free_command:
1680 free(command);
1540out_remove_tmp: 1681out_remove_tmp:
1541 close(stdout_fd[0]); 1682 close(stdout_fd[0]);
1542 1683
@@ -1550,7 +1691,7 @@ out:
1550 1691
1551out_close_stdout: 1692out_close_stdout:
1552 close(stdout_fd[1]); 1693 close(stdout_fd[1]);
1553 goto out_remove_tmp; 1694 goto out_free_command;
1554} 1695}
1555 1696
1556static void calc_percent(struct sym_hist *hist, 1697static void calc_percent(struct sym_hist *hist,
@@ -1613,7 +1754,6 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1613{ 1754{
1614 struct annotate_args args = { 1755 struct annotate_args args = {
1615 .privsize = privsize, 1756 .privsize = privsize,
1616 .map = map,
1617 .evsel = evsel, 1757 .evsel = evsel,
1618 }; 1758 };
1619 struct perf_env *env = perf_evsel__env(evsel); 1759 struct perf_env *env = perf_evsel__env(evsel);
@@ -1639,6 +1779,9 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1639 } 1779 }
1640 } 1780 }
1641 1781
1782 args.ms.map = map;
1783 args.ms.sym = sym;
1784
1642 return symbol__disassemble(sym, &args); 1785 return symbol__disassemble(sym, &args);
1643} 1786}
1644 1787
@@ -1879,6 +2022,103 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1879 return more; 2022 return more;
1880} 2023}
1881 2024
2025static void FILE__set_percent_color(void *fp __maybe_unused,
2026 double percent __maybe_unused,
2027 bool current __maybe_unused)
2028{
2029}
2030
2031static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
2032 int nr __maybe_unused, bool current __maybe_unused)
2033{
2034 return 0;
2035}
2036
2037static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
2038{
2039 return 0;
2040}
2041
2042static void FILE__printf(void *fp, const char *fmt, ...)
2043{
2044 va_list args;
2045
2046 va_start(args, fmt);
2047 vfprintf(fp, fmt, args);
2048 va_end(args);
2049}
2050
2051static void FILE__write_graph(void *fp, int graph)
2052{
2053 const char *s;
2054 switch (graph) {
2055
2056 case DARROW_CHAR: s = "↓"; break;
2057 case UARROW_CHAR: s = "↑"; break;
2058 case LARROW_CHAR: s = "←"; break;
2059 case RARROW_CHAR: s = "→"; break;
2060 default: s = "?"; break;
2061 }
2062
2063 fputs(s, fp);
2064}
2065
2066int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
2067{
2068 struct annotation *notes = symbol__annotation(sym);
2069 struct annotation_write_ops ops = {
2070 .first_line = true,
2071 .obj = fp,
2072 .set_color = FILE__set_color,
2073 .set_percent_color = FILE__set_percent_color,
2074 .set_jumps_percent_color = FILE__set_jumps_percent_color,
2075 .printf = FILE__printf,
2076 .write_graph = FILE__write_graph,
2077 };
2078 struct annotation_line *al;
2079
2080 list_for_each_entry(al, &notes->src->source, node) {
2081 if (annotation_line__filter(al, notes))
2082 continue;
2083 annotation_line__write(al, notes, &ops);
2084 fputc('\n', fp);
2085 ops.first_line = false;
2086 }
2087
2088 return 0;
2089}
2090
2091int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
2092{
2093 const char *ev_name = perf_evsel__name(evsel);
2094 char buf[1024];
2095 char *filename;
2096 int err = -1;
2097 FILE *fp;
2098
2099 if (asprintf(&filename, "%s.annotation", ms->sym->name) < 0)
2100 return -1;
2101
2102 fp = fopen(filename, "w");
2103 if (fp == NULL)
2104 goto out_free_filename;
2105
2106 if (perf_evsel__is_group_event(evsel)) {
2107 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2108 ev_name = buf;
2109 }
2110
2111 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2112 ms->sym->name, ms->map->dso->long_name, ev_name);
2113 symbol__annotate_fprintf2(ms->sym, fp);
2114
2115 fclose(fp);
2116 err = 0;
2117out_free_filename:
2118 free(filename);
2119 return err;
2120}
2121
1882void symbol__annotate_zero_histogram(struct symbol *sym, int evidx) 2122void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
1883{ 2123{
1884 struct annotation *notes = symbol__annotation(sym); 2124 struct annotation *notes = symbol__annotation(sym);
@@ -1938,8 +2178,109 @@ size_t disasm__fprintf(struct list_head *head, FILE *fp)
1938 return printed; 2178 return printed;
1939} 2179}
1940 2180
2181bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym)
2182{
2183 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
2184 !disasm_line__has_local_offset(dl) || dl->ops.target.offset < 0 ||
2185 dl->ops.target.offset >= (s64)symbol__size(sym))
2186 return false;
2187
2188 return true;
2189}
2190
2191void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
2192{
2193 u64 offset, size = symbol__size(sym);
2194
2195 /* PLT symbols contain external offsets */
2196 if (strstr(sym->name, "@plt"))
2197 return;
2198
2199 for (offset = 0; offset < size; ++offset) {
2200 struct annotation_line *al = notes->offsets[offset];
2201 struct disasm_line *dl;
2202
2203 dl = disasm_line(al);
2204
2205 if (!disasm_line__is_valid_local_jump(dl, sym))
2206 continue;
2207
2208 al = notes->offsets[dl->ops.target.offset];
2209
2210 /*
2211 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
2212 * have to adjust to the previous offset?
2213 */
2214 if (al == NULL)
2215 continue;
2216
2217 if (++al->jump_sources > notes->max_jump_sources)
2218 notes->max_jump_sources = al->jump_sources;
2219
2220 ++notes->nr_jumps;
2221 }
2222}
2223
2224void annotation__set_offsets(struct annotation *notes, s64 size)
2225{
2226 struct annotation_line *al;
2227
2228 notes->max_line_len = 0;
2229
2230 list_for_each_entry(al, &notes->src->source, node) {
2231 size_t line_len = strlen(al->line);
2232
2233 if (notes->max_line_len < line_len)
2234 notes->max_line_len = line_len;
2235 al->idx = notes->nr_entries++;
2236 if (al->offset != -1) {
2237 al->idx_asm = notes->nr_asm_entries++;
2238 /*
2239 * FIXME: short term bandaid to cope with assembly
2240 * routines that comes with labels in the same column
2241 * as the address in objdump, sigh.
2242 *
2243 * E.g. copy_user_generic_unrolled
2244 */
2245 if (al->offset < size)
2246 notes->offsets[al->offset] = al;
2247 } else
2248 al->idx_asm = -1;
2249 }
2250}
2251
2252static inline int width_jumps(int n)
2253{
2254 if (n >= 100)
2255 return 5;
2256 if (n / 10)
2257 return 2;
2258 return 1;
2259}
2260
2261void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2262{
2263 notes->widths.addr = notes->widths.target =
2264 notes->widths.min_addr = hex_width(symbol__size(sym));
2265 notes->widths.max_addr = hex_width(sym->end);
2266 notes->widths.jumps = width_jumps(notes->max_jump_sources);
2267}
2268
2269void annotation__update_column_widths(struct annotation *notes)
2270{
2271 if (notes->options->use_offset)
2272 notes->widths.target = notes->widths.min_addr;
2273 else
2274 notes->widths.target = notes->widths.max_addr;
2275
2276 notes->widths.addr = notes->widths.target;
2277
2278 if (notes->options->show_nr_jumps)
2279 notes->widths.addr += notes->widths.jumps + 1;
2280}
2281
1941static void annotation__calc_lines(struct annotation *notes, struct map *map, 2282static void annotation__calc_lines(struct annotation *notes, struct map *map,
1942 struct rb_root *root, u64 start) 2283 struct rb_root *root)
1943{ 2284{
1944 struct annotation_line *al; 2285 struct annotation_line *al;
1945 struct rb_root tmp_root = RB_ROOT; 2286 struct rb_root tmp_root = RB_ROOT;
@@ -1960,8 +2301,8 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
1960 if (percent_max <= 0.5) 2301 if (percent_max <= 0.5)
1961 continue; 2302 continue;
1962 2303
1963 al->path = get_srcline(map->dso, start + al->offset, NULL, 2304 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
1964 false, true, start + al->offset); 2305 false, true, notes->start + al->offset);
1965 insert_source_line(&tmp_root, al); 2306 insert_source_line(&tmp_root, al);
1966 } 2307 }
1967 2308
@@ -1972,9 +2313,40 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map,
1972 struct rb_root *root) 2313 struct rb_root *root)
1973{ 2314{
1974 struct annotation *notes = symbol__annotation(sym); 2315 struct annotation *notes = symbol__annotation(sym);
1975 u64 start = map__rip_2objdump(map, sym->start);
1976 2316
1977 annotation__calc_lines(notes, map, root, start); 2317 annotation__calc_lines(notes, map, root);
2318}
2319
2320int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2321 struct perf_evsel *evsel, bool print_lines,
2322 bool full_paths)
2323{
2324 struct dso *dso = map->dso;
2325 struct rb_root source_line = RB_ROOT;
2326 struct annotation_options opts = annotation__default_options;
2327 const char *ev_name = perf_evsel__name(evsel);
2328 char buf[1024];
2329
2330 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0)
2331 return -1;
2332
2333 if (print_lines) {
2334 srcline_full_filename = full_paths;
2335 symbol__calc_lines(sym, map, &source_line);
2336 print_summary(&source_line, dso->long_name);
2337 }
2338
2339 if (perf_evsel__is_group_event(evsel)) {
2340 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2341 ev_name = buf;
2342 }
2343
2344 fprintf(stdout, "%s() %s\nEvent: %s\n\n", sym->name, dso->long_name, ev_name);
2345 symbol__annotate_fprintf2(sym, stdout);
2346
2347 annotated_source__purge(symbol__annotation(sym)->src);
2348
2349 return 0;
1978} 2350}
1979 2351
1980int symbol__tty_annotate(struct symbol *sym, struct map *map, 2352int symbol__tty_annotate(struct symbol *sym, struct map *map,
@@ -2007,3 +2379,276 @@ bool ui__has_annotation(void)
2007{ 2379{
2008 return use_browser == 1 && perf_hpp_list.sym; 2380 return use_browser == 1 && perf_hpp_list.sym;
2009} 2381}
2382
2383
2384double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes)
2385{
2386 double percent_max = 0.0;
2387 int i;
2388
2389 for (i = 0; i < notes->nr_events; i++) {
2390 if (al->samples[i].percent > percent_max)
2391 percent_max = al->samples[i].percent;
2392 }
2393
2394 return percent_max;
2395}
2396
2397static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
2398 void *obj, char *bf, size_t size,
2399 void (*obj__printf)(void *obj, const char *fmt, ...),
2400 void (*obj__write_graph)(void *obj, int graph))
2401{
2402 if (dl->ins.ops && dl->ins.ops->scnprintf) {
2403 if (ins__is_jump(&dl->ins)) {
2404 bool fwd;
2405
2406 if (dl->ops.target.outside)
2407 goto call_like;
2408 fwd = dl->ops.target.offset > dl->al.offset;
2409 obj__write_graph(obj, fwd ? DARROW_CHAR : UARROW_CHAR);
2410 obj__printf(obj, " ");
2411 } else if (ins__is_call(&dl->ins)) {
2412call_like:
2413 obj__write_graph(obj, RARROW_CHAR);
2414 obj__printf(obj, " ");
2415 } else if (ins__is_ret(&dl->ins)) {
2416 obj__write_graph(obj, LARROW_CHAR);
2417 obj__printf(obj, " ");
2418 } else {
2419 obj__printf(obj, " ");
2420 }
2421 } else {
2422 obj__printf(obj, " ");
2423 }
2424
2425 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
2426}
2427
2428static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2429 bool first_line, bool current_entry, bool change_color, int width,
2430 void *obj,
2431 int (*obj__set_color)(void *obj, int color),
2432 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2433 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
2434 void (*obj__printf)(void *obj, const char *fmt, ...),
2435 void (*obj__write_graph)(void *obj, int graph))
2436
2437{
2438 double percent_max = annotation_line__max_percent(al, notes);
2439 int pcnt_width = annotation__pcnt_width(notes),
2440 cycles_width = annotation__cycles_width(notes);
2441 bool show_title = false;
2442 char bf[256];
2443 int printed;
2444
2445 if (first_line && (al->offset == -1 || percent_max == 0.0)) {
2446 if (notes->have_cycles) {
2447 if (al->ipc == 0.0 && al->cycles == 0)
2448 show_title = true;
2449 } else
2450 show_title = true;
2451 }
2452
2453 if (al->offset != -1 && percent_max != 0.0) {
2454 int i;
2455
2456 for (i = 0; i < notes->nr_events; i++) {
2457 obj__set_percent_color(obj, al->samples[i].percent, current_entry);
2458 if (notes->options->show_total_period) {
2459 obj__printf(obj, "%11" PRIu64 " ", al->samples[i].he.period);
2460 } else if (notes->options->show_nr_samples) {
2461 obj__printf(obj, "%6" PRIu64 " ",
2462 al->samples[i].he.nr_samples);
2463 } else {
2464 obj__printf(obj, "%6.2f ",
2465 al->samples[i].percent);
2466 }
2467 }
2468 } else {
2469 obj__set_percent_color(obj, 0, current_entry);
2470
2471 if (!show_title)
2472 obj__printf(obj, "%-*s", pcnt_width, " ");
2473 else {
2474 obj__printf(obj, "%-*s", pcnt_width,
2475 notes->options->show_total_period ? "Period" :
2476 notes->options->show_nr_samples ? "Samples" : "Percent");
2477 }
2478 }
2479
2480 if (notes->have_cycles) {
2481 if (al->ipc)
2482 obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
2483 else if (!show_title)
2484 obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
2485 else
2486 obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
2487
2488 if (al->cycles)
2489 obj__printf(obj, "%*" PRIu64 " ",
2490 ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
2491 else if (!show_title)
2492 obj__printf(obj, "%*s", ANNOTATION__CYCLES_WIDTH, " ");
2493 else
2494 obj__printf(obj, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle");
2495 }
2496
2497 obj__printf(obj, " ");
2498
2499 if (!*al->line)
2500 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
2501 else if (al->offset == -1) {
2502 if (al->line_nr && notes->options->show_linenr)
2503 printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
2504 else
2505 printed = scnprintf(bf, sizeof(bf), "%-*s ", notes->widths.addr, " ");
2506 obj__printf(obj, bf);
2507 obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line);
2508 } else {
2509 u64 addr = al->offset;
2510 int color = -1;
2511
2512 if (!notes->options->use_offset)
2513 addr += notes->start;
2514
2515 if (!notes->options->use_offset) {
2516 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
2517 } else {
2518 if (al->jump_sources) {
2519 if (notes->options->show_nr_jumps) {
2520 int prev;
2521 printed = scnprintf(bf, sizeof(bf), "%*d ",
2522 notes->widths.jumps,
2523 al->jump_sources);
2524 prev = obj__set_jumps_percent_color(obj, al->jump_sources,
2525 current_entry);
2526 obj__printf(obj, bf);
2527 obj__set_color(obj, prev);
2528 }
2529
2530 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
2531 notes->widths.target, addr);
2532 } else {
2533 printed = scnprintf(bf, sizeof(bf), "%-*s ",
2534 notes->widths.addr, " ");
2535 }
2536 }
2537
2538 if (change_color)
2539 color = obj__set_color(obj, HE_COLORSET_ADDR);
2540 obj__printf(obj, bf);
2541 if (change_color)
2542 obj__set_color(obj, color);
2543
2544 disasm_line__write(disasm_line(al), notes, obj, bf, sizeof(bf), obj__printf, obj__write_graph);
2545
2546 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width - 3 - printed, bf);
2547 }
2548
2549}
2550
2551void annotation_line__write(struct annotation_line *al, struct annotation *notes,
2552 struct annotation_write_ops *ops)
2553{
2554 __annotation_line__write(al, notes, ops->first_line, ops->current_entry,
2555 ops->change_color, ops->width, ops->obj,
2556 ops->set_color, ops->set_percent_color,
2557 ops->set_jumps_percent_color, ops->printf,
2558 ops->write_graph);
2559}
2560
2561int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
2562 struct annotation_options *options, struct arch **parch)
2563{
2564 struct annotation *notes = symbol__annotation(sym);
2565 size_t size = symbol__size(sym);
2566 int nr_pcnt = 1, err;
2567
2568 notes->offsets = zalloc(size * sizeof(struct annotation_line *));
2569 if (notes->offsets == NULL)
2570 return -1;
2571
2572 if (perf_evsel__is_group_event(evsel))
2573 nr_pcnt = evsel->nr_members;
2574
2575 err = symbol__annotate(sym, map, evsel, 0, parch);
2576 if (err)
2577 goto out_free_offsets;
2578
2579 notes->options = options;
2580
2581 symbol__calc_percent(sym, evsel);
2582
2583 notes->start = map__rip_2objdump(map, sym->start);
2584
2585 annotation__set_offsets(notes, size);
2586 annotation__mark_jump_targets(notes, sym);
2587 annotation__compute_ipc(notes, size);
2588 annotation__init_column_widths(notes, sym);
2589 notes->nr_events = nr_pcnt;
2590
2591 annotation__update_column_widths(notes);
2592
2593 return 0;
2594
2595out_free_offsets:
2596 zfree(&notes->offsets);
2597 return -1;
2598}
2599
2600#define ANNOTATION__CFG(n) \
2601 { .name = #n, .value = &annotation__default_options.n, }
2602
2603/*
2604 * Keep the entries sorted, they are bsearch'ed
2605 */
2606static struct annotation_config {
2607 const char *name;
2608 bool *value;
2609} annotation__configs[] = {
2610 ANNOTATION__CFG(hide_src_code),
2611 ANNOTATION__CFG(jump_arrows),
2612 ANNOTATION__CFG(show_linenr),
2613 ANNOTATION__CFG(show_nr_jumps),
2614 ANNOTATION__CFG(show_nr_samples),
2615 ANNOTATION__CFG(show_total_period),
2616 ANNOTATION__CFG(use_offset),
2617};
2618
2619#undef ANNOTATION__CFG
2620
2621static int annotation_config__cmp(const void *name, const void *cfgp)
2622{
2623 const struct annotation_config *cfg = cfgp;
2624
2625 return strcmp(name, cfg->name);
2626}
2627
2628static int annotation__config(const char *var, const char *value,
2629 void *data __maybe_unused)
2630{
2631 struct annotation_config *cfg;
2632 const char *name;
2633
2634 if (!strstarts(var, "annotate."))
2635 return 0;
2636
2637 name = var + 9;
2638 cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs),
2639 sizeof(struct annotation_config), annotation_config__cmp);
2640
2641 if (cfg == NULL)
2642 pr_debug("%s variable unknown, ignoring...", var);
2643 else
2644 *cfg->value = perf_config_bool(name, value);
2645 return 0;
2646}
2647
2648void annotation_config__init(void)
2649{
2650 perf_config(annotation__config, NULL);
2651
2652 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2653 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2654}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index ce427445671f..ff7e3df31efa 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -24,9 +24,11 @@ struct ins_operands {
24 struct { 24 struct {
25 char *raw; 25 char *raw;
26 char *name; 26 char *name;
27 struct symbol *sym;
27 u64 addr; 28 u64 addr;
28 s64 offset; 29 s64 offset;
29 bool offset_avail; 30 bool offset_avail;
31 bool outside;
30 } target; 32 } target;
31 union { 33 union {
32 struct { 34 struct {
@@ -45,7 +47,7 @@ struct arch;
45 47
46struct ins_ops { 48struct ins_ops {
47 void (*free)(struct ins_operands *ops); 49 void (*free)(struct ins_operands *ops);
48 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map *map); 50 int (*parse)(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms);
49 int (*scnprintf)(struct ins *ins, char *bf, size_t size, 51 int (*scnprintf)(struct ins *ins, char *bf, size_t size,
50 struct ins_operands *ops); 52 struct ins_operands *ops);
51}; 53};
@@ -57,6 +59,21 @@ bool ins__is_lock(const struct ins *ins);
57int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 59int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
58bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2); 60bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
59 61
62#define ANNOTATION__IPC_WIDTH 6
63#define ANNOTATION__CYCLES_WIDTH 6
64
65struct annotation_options {
66 bool hide_src_code,
67 use_offset,
68 jump_arrows,
69 show_linenr,
70 show_nr_jumps,
71 show_nr_samples,
72 show_total_period;
73};
74
75extern struct annotation_options annotation__default_options;
76
60struct annotation; 77struct annotation;
61 78
62struct sym_hist_entry { 79struct sym_hist_entry {
@@ -76,10 +93,13 @@ struct annotation_line {
76 s64 offset; 93 s64 offset;
77 char *line; 94 char *line;
78 int line_nr; 95 int line_nr;
96 int jump_sources;
79 float ipc; 97 float ipc;
80 u64 cycles; 98 u64 cycles;
81 size_t privsize; 99 size_t privsize;
82 char *path; 100 char *path;
101 u32 idx;
102 int idx_asm;
83 int samples_nr; 103 int samples_nr;
84 struct annotation_data samples[0]; 104 struct annotation_data samples[0];
85}; 105};
@@ -97,14 +117,40 @@ static inline struct disasm_line *disasm_line(struct annotation_line *al)
97 return al ? container_of(al, struct disasm_line, al) : NULL; 117 return al ? container_of(al, struct disasm_line, al) : NULL;
98} 118}
99 119
100static inline bool disasm_line__has_offset(const struct disasm_line *dl) 120/*
121 * Is this offset in the same function as the line it is used?
122 * asm functions jump to other functions, for instance.
123 */
124static inline bool disasm_line__has_local_offset(const struct disasm_line *dl)
101{ 125{
102 return dl->ops.target.offset_avail; 126 return dl->ops.target.offset_avail && !dl->ops.target.outside;
103} 127}
104 128
129/*
130 * Can we draw an arrow from the jump to its target, for instance? I.e.
131 * is the jump and its target in the same function?
132 */
133bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym);
134
105void disasm_line__free(struct disasm_line *dl); 135void disasm_line__free(struct disasm_line *dl);
106struct annotation_line * 136struct annotation_line *
107annotation_line__next(struct annotation_line *pos, struct list_head *head); 137annotation_line__next(struct annotation_line *pos, struct list_head *head);
138
139struct annotation_write_ops {
140 bool first_line, current_entry, change_color;
141 int width;
142 void *obj;
143 int (*set_color)(void *obj, int color);
144 void (*set_percent_color)(void *obj, double percent, bool current);
145 int (*set_jumps_percent_color)(void *obj, int nr, bool current);
146 void (*printf)(void *obj, const char *fmt, ...);
147 void (*write_graph)(void *obj, int graph);
148};
149
150double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes);
151void annotation_line__write(struct annotation_line *al, struct annotation *notes,
152 struct annotation_write_ops *ops);
153
108int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 154int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
109size_t disasm__fprintf(struct list_head *head, FILE *fp); 155size_t disasm__fprintf(struct list_head *head, FILE *fp);
110void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); 156void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
@@ -150,9 +196,47 @@ struct annotated_source {
150struct annotation { 196struct annotation {
151 pthread_mutex_t lock; 197 pthread_mutex_t lock;
152 u64 max_coverage; 198 u64 max_coverage;
199 u64 start;
200 struct annotation_options *options;
201 struct annotation_line **offsets;
202 int nr_events;
203 int nr_jumps;
204 int max_jump_sources;
205 int nr_entries;
206 int nr_asm_entries;
207 u16 max_line_len;
208 struct {
209 u8 addr;
210 u8 jumps;
211 u8 target;
212 u8 min_addr;
213 u8 max_addr;
214 } widths;
215 bool have_cycles;
153 struct annotated_source *src; 216 struct annotated_source *src;
154}; 217};
155 218
219static inline int annotation__cycles_width(struct annotation *notes)
220{
221 return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
222}
223
224static inline int annotation__pcnt_width(struct annotation *notes)
225{
226 return (notes->options->show_total_period ? 12 : 7) * notes->nr_events;
227}
228
229static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes)
230{
231 return notes->options->hide_src_code && al->offset == -1;
232}
233
234void annotation__set_offsets(struct annotation *notes, s64 size);
235void annotation__compute_ipc(struct annotation *notes, size_t size);
236void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym);
237void annotation__update_column_widths(struct annotation *notes);
238void annotation__init_column_widths(struct annotation *notes, struct symbol *sym);
239
156static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) 240static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
157{ 241{
158 return (((void *)&notes->src->histograms) + 242 return (((void *)&notes->src->histograms) +
@@ -180,6 +264,10 @@ void symbol__annotate_zero_histograms(struct symbol *sym);
180int symbol__annotate(struct symbol *sym, struct map *map, 264int symbol__annotate(struct symbol *sym, struct map *map,
181 struct perf_evsel *evsel, size_t privsize, 265 struct perf_evsel *evsel, size_t privsize,
182 struct arch **parch); 266 struct arch **parch);
267int symbol__annotate2(struct symbol *sym, struct map *map,
268 struct perf_evsel *evsel,
269 struct annotation_options *options,
270 struct arch **parch);
183 271
184enum symbol_disassemble_errno { 272enum symbol_disassemble_errno {
185 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, 273 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
@@ -204,16 +292,23 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
204int symbol__annotate_printf(struct symbol *sym, struct map *map, 292int symbol__annotate_printf(struct symbol *sym, struct map *map,
205 struct perf_evsel *evsel, bool full_paths, 293 struct perf_evsel *evsel, bool full_paths,
206 int min_pcnt, int max_lines, int context); 294 int min_pcnt, int max_lines, int context);
295int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
207void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 296void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
208void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 297void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
209void annotated_source__purge(struct annotated_source *as); 298void annotated_source__purge(struct annotated_source *as);
210 299
300int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel);
301
211bool ui__has_annotation(void); 302bool ui__has_annotation(void);
212 303
213int symbol__tty_annotate(struct symbol *sym, struct map *map, 304int symbol__tty_annotate(struct symbol *sym, struct map *map,
214 struct perf_evsel *evsel, bool print_lines, 305 struct perf_evsel *evsel, bool print_lines,
215 bool full_paths, int min_pcnt, int max_lines); 306 bool full_paths, int min_pcnt, int max_lines);
216 307
308int symbol__tty_annotate2(struct symbol *sym, struct map *map,
309 struct perf_evsel *evsel, bool print_lines,
310 bool full_paths);
311
217#ifdef HAVE_SLANG_SUPPORT 312#ifdef HAVE_SLANG_SUPPORT
218int symbol__tui_annotate(struct symbol *sym, struct map *map, 313int symbol__tui_annotate(struct symbol *sym, struct map *map,
219 struct perf_evsel *evsel, 314 struct perf_evsel *evsel,
@@ -231,4 +326,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
231 326
232extern const char *disassembler_style; 327extern const char *disassembler_style;
233 328
329void annotation_config__init(void);
330
234#endif /* __PERF_ANNOTATE_H */ 331#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 9faf3b5367db..fb357a00dd86 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -60,6 +60,12 @@
60#include "sane_ctype.h" 60#include "sane_ctype.h"
61#include "symbol/kallsyms.h" 61#include "symbol/kallsyms.h"
62 62
63static bool auxtrace__dont_decode(struct perf_session *session)
64{
65 return !session->itrace_synth_opts ||
66 session->itrace_synth_opts->dont_decode;
67}
68
63int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, 69int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
64 struct auxtrace_mmap_params *mp, 70 struct auxtrace_mmap_params *mp,
65 void *userpg, int fd) 71 void *userpg, int fd)
@@ -227,9 +233,9 @@ static void *auxtrace_copy_data(u64 size, struct perf_session *session)
227 return p; 233 return p;
228} 234}
229 235
230static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, 236static int auxtrace_queues__queue_buffer(struct auxtrace_queues *queues,
231 unsigned int idx, 237 unsigned int idx,
232 struct auxtrace_buffer *buffer) 238 struct auxtrace_buffer *buffer)
233{ 239{
234 struct auxtrace_queue *queue; 240 struct auxtrace_queue *queue;
235 int err; 241 int err;
@@ -280,7 +286,7 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
280 return -ENOMEM; 286 return -ENOMEM;
281 b->size = BUFFER_LIMIT_FOR_32_BIT; 287 b->size = BUFFER_LIMIT_FOR_32_BIT;
282 b->consecutive = consecutive; 288 b->consecutive = consecutive;
283 err = auxtrace_queues__add_buffer(queues, idx, b); 289 err = auxtrace_queues__queue_buffer(queues, idx, b);
284 if (err) { 290 if (err) {
285 auxtrace_buffer__free(b); 291 auxtrace_buffer__free(b);
286 return err; 292 return err;
@@ -296,11 +302,14 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues,
296 return 0; 302 return 0;
297} 303}
298 304
299static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues, 305static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues,
300 struct perf_session *session, 306 struct perf_session *session,
301 unsigned int idx, 307 unsigned int idx,
302 struct auxtrace_buffer *buffer) 308 struct auxtrace_buffer *buffer,
309 struct auxtrace_buffer **buffer_ptr)
303{ 310{
311 int err;
312
304 if (session->one_mmap) { 313 if (session->one_mmap) {
305 buffer->data = buffer->data_offset - session->one_mmap_offset + 314 buffer->data = buffer->data_offset - session->one_mmap_offset +
306 session->one_mmap_addr; 315 session->one_mmap_addr;
@@ -311,14 +320,20 @@ static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues,
311 buffer->data_needs_freeing = true; 320 buffer->data_needs_freeing = true;
312 } else if (BITS_PER_LONG == 32 && 321 } else if (BITS_PER_LONG == 32 &&
313 buffer->size > BUFFER_LIMIT_FOR_32_BIT) { 322 buffer->size > BUFFER_LIMIT_FOR_32_BIT) {
314 int err;
315
316 err = auxtrace_queues__split_buffer(queues, idx, buffer); 323 err = auxtrace_queues__split_buffer(queues, idx, buffer);
317 if (err) 324 if (err)
318 return err; 325 return err;
319 } 326 }
320 327
321 return auxtrace_queues__add_buffer(queues, idx, buffer); 328 err = auxtrace_queues__queue_buffer(queues, idx, buffer);
329 if (err)
330 return err;
331
332 /* FIXME: Doesn't work for split buffer */
333 if (buffer_ptr)
334 *buffer_ptr = buffer;
335
336 return 0;
322} 337}
323 338
324static bool filter_cpu(struct perf_session *session, int cpu) 339static bool filter_cpu(struct perf_session *session, int cpu)
@@ -353,13 +368,11 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues,
353 buffer->size = event->auxtrace.size; 368 buffer->size = event->auxtrace.size;
354 idx = event->auxtrace.idx; 369 idx = event->auxtrace.idx;
355 370
356 err = auxtrace_queues__add_event_buffer(queues, session, idx, buffer); 371 err = auxtrace_queues__add_buffer(queues, session, idx, buffer,
372 buffer_ptr);
357 if (err) 373 if (err)
358 goto out_err; 374 goto out_err;
359 375
360 if (buffer_ptr)
361 *buffer_ptr = buffer;
362
363 return 0; 376 return 0;
364 377
365out_err: 378out_err:
@@ -762,6 +775,9 @@ int auxtrace_queues__process_index(struct auxtrace_queues *queues,
762 size_t i; 775 size_t i;
763 int err; 776 int err;
764 777
778 if (auxtrace__dont_decode(session))
779 return 0;
780
765 list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) { 781 list_for_each_entry(auxtrace_index, &session->auxtrace_index, list) {
766 for (i = 0; i < auxtrace_index->nr; i++) { 782 for (i = 0; i < auxtrace_index->nr; i++) {
767 ent = &auxtrace_index->entries[i]; 783 ent = &auxtrace_index->entries[i];
@@ -892,12 +908,6 @@ out_free:
892 return err; 908 return err;
893} 909}
894 910
895static bool auxtrace__dont_decode(struct perf_session *session)
896{
897 return !session->itrace_synth_opts ||
898 session->itrace_synth_opts->dont_decode;
899}
900
901int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused, 911int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
902 union perf_event *event, 912 union perf_event *event,
903 struct perf_session *session) 913 struct perf_session *session)
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 453c148d2158..e731f55da072 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -130,6 +130,7 @@ struct auxtrace_index {
130/** 130/**
131 * struct auxtrace - session callbacks to allow AUX area data decoding. 131 * struct auxtrace - session callbacks to allow AUX area data decoding.
132 * @process_event: lets the decoder see all session events 132 * @process_event: lets the decoder see all session events
133 * @process_auxtrace_event: process a PERF_RECORD_AUXTRACE event
133 * @flush_events: process any remaining data 134 * @flush_events: process any remaining data
134 * @free_events: free resources associated with event processing 135 * @free_events: free resources associated with event processing
135 * @free: free resources associated with the session 136 * @free: free resources associated with the session
@@ -301,6 +302,7 @@ struct auxtrace_mmap_params {
301 * @parse_snapshot_options: parse snapshot options 302 * @parse_snapshot_options: parse snapshot options
302 * @reference: provide a 64-bit reference number for auxtrace_event 303 * @reference: provide a 64-bit reference number for auxtrace_event
303 * @read_finish: called after reading from an auxtrace mmap 304 * @read_finish: called after reading from an auxtrace mmap
305 * @alignment: alignment (if any) for AUX area data
304 */ 306 */
305struct auxtrace_record { 307struct auxtrace_record {
306 int (*recording_options)(struct auxtrace_record *itr, 308 int (*recording_options)(struct auxtrace_record *itr,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 7f8553630c4d..537eadd81914 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -316,7 +316,6 @@ static int machine__write_buildid_table(struct machine *machine,
316 struct feat_fd *fd) 316 struct feat_fd *fd)
317{ 317{
318 int err = 0; 318 int err = 0;
319 char nm[PATH_MAX];
320 struct dso *pos; 319 struct dso *pos;
321 u16 kmisc = PERF_RECORD_MISC_KERNEL, 320 u16 kmisc = PERF_RECORD_MISC_KERNEL,
322 umisc = PERF_RECORD_MISC_USER; 321 umisc = PERF_RECORD_MISC_USER;
@@ -338,9 +337,8 @@ static int machine__write_buildid_table(struct machine *machine,
338 name = pos->short_name; 337 name = pos->short_name;
339 name_len = pos->short_name_len; 338 name_len = pos->short_name_len;
340 } else if (dso__is_kcore(pos)) { 339 } else if (dso__is_kcore(pos)) {
341 machine__mmap_name(machine, nm, sizeof(nm)); 340 name = machine->mmap_name;
342 name = nm; 341 name_len = strlen(name);
343 name_len = strlen(nm);
344 } else { 342 } else {
345 name = pos->long_name; 343 name = pos->long_name;
346 name_len = pos->long_name_len; 344 name_len = pos->long_name_len;
@@ -813,12 +811,10 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine)
813 bool is_kallsyms = dso__is_kallsyms(dso); 811 bool is_kallsyms = dso__is_kallsyms(dso);
814 bool is_vdso = dso__is_vdso(dso); 812 bool is_vdso = dso__is_vdso(dso);
815 const char *name = dso->long_name; 813 const char *name = dso->long_name;
816 char nm[PATH_MAX];
817 814
818 if (dso__is_kcore(dso)) { 815 if (dso__is_kcore(dso)) {
819 is_kallsyms = true; 816 is_kallsyms = true;
820 machine__mmap_name(machine, nm, sizeof(nm)); 817 name = machine->mmap_name;
821 name = nm;
822 } 818 }
823 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 819 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
824 dso->nsinfo, is_kallsyms, is_vdso); 820 dso->nsinfo, is_kallsyms, is_vdso);
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 984f69144f87..decb91f9da82 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -71,7 +71,7 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
71 return -1; 71 return -1;
72} 72}
73 73
74static int open_cgroup(char *name) 74static int open_cgroup(const char *name)
75{ 75{
76 char path[PATH_MAX + 1]; 76 char path[PATH_MAX + 1];
77 char mnt[PATH_MAX + 1]; 77 char mnt[PATH_MAX + 1];
@@ -81,7 +81,7 @@ static int open_cgroup(char *name)
81 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1)) 81 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
82 return -1; 82 return -1;
83 83
84 snprintf(path, PATH_MAX, "%s/%s", mnt, name); 84 scnprintf(path, PATH_MAX, "%s/%s", mnt, name);
85 85
86 fd = open(path, O_RDONLY); 86 fd = open(path, O_RDONLY);
87 if (fd == -1) 87 if (fd == -1)
@@ -90,41 +90,64 @@ static int open_cgroup(char *name)
90 return fd; 90 return fd;
91} 91}
92 92
93static int add_cgroup(struct perf_evlist *evlist, char *str) 93static struct cgroup *evlist__find_cgroup(struct perf_evlist *evlist, const char *str)
94{ 94{
95 struct perf_evsel *counter; 95 struct perf_evsel *counter;
96 struct cgroup_sel *cgrp = NULL; 96 struct cgroup *cgrp = NULL;
97 int n;
98 /* 97 /*
99 * check if cgrp is already defined, if so we reuse it 98 * check if cgrp is already defined, if so we reuse it
100 */ 99 */
101 evlist__for_each_entry(evlist, counter) { 100 evlist__for_each_entry(evlist, counter) {
102 cgrp = counter->cgrp; 101 if (!counter->cgrp)
103 if (!cgrp)
104 continue; 102 continue;
105 if (!strcmp(cgrp->name, str)) { 103 if (!strcmp(counter->cgrp->name, str)) {
106 refcount_inc(&cgrp->refcnt); 104 cgrp = cgroup__get(counter->cgrp);
107 break; 105 break;
108 } 106 }
109
110 cgrp = NULL;
111 } 107 }
112 108
113 if (!cgrp) { 109 return cgrp;
114 cgrp = zalloc(sizeof(*cgrp)); 110}
115 if (!cgrp)
116 return -1;
117 111
118 cgrp->name = str; 112static struct cgroup *cgroup__new(const char *name)
119 refcount_set(&cgrp->refcnt, 1); 113{
114 struct cgroup *cgroup = zalloc(sizeof(*cgroup));
120 115
121 cgrp->fd = open_cgroup(str); 116 if (cgroup != NULL) {
122 if (cgrp->fd == -1) { 117 refcount_set(&cgroup->refcnt, 1);
123 free(cgrp); 118
124 return -1; 119 cgroup->name = strdup(name);
125 } 120 if (!cgroup->name)
121 goto out_err;
122 cgroup->fd = open_cgroup(name);
123 if (cgroup->fd == -1)
124 goto out_free_name;
126 } 125 }
127 126
127 return cgroup;
128
129out_free_name:
130 free(cgroup->name);
131out_err:
132 free(cgroup);
133 return NULL;
134}
135
136struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name)
137{
138 struct cgroup *cgroup = evlist__find_cgroup(evlist, name);
139
140 return cgroup ?: cgroup__new(name);
141}
142
143static int add_cgroup(struct perf_evlist *evlist, const char *str)
144{
145 struct perf_evsel *counter;
146 struct cgroup *cgrp = evlist__findnew_cgroup(evlist, str);
147 int n;
148
149 if (!cgrp)
150 return -1;
128 /* 151 /*
129 * find corresponding event 152 * find corresponding event
130 * if add cgroup N, then need to find event N 153 * if add cgroup N, then need to find event N
@@ -135,31 +158,58 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
135 goto found; 158 goto found;
136 n++; 159 n++;
137 } 160 }
138 if (refcount_dec_and_test(&cgrp->refcnt))
139 free(cgrp);
140 161
162 cgroup__put(cgrp);
141 return -1; 163 return -1;
142found: 164found:
143 counter->cgrp = cgrp; 165 counter->cgrp = cgrp;
144 return 0; 166 return 0;
145} 167}
146 168
147void close_cgroup(struct cgroup_sel *cgrp) 169static void cgroup__delete(struct cgroup *cgroup)
170{
171 close(cgroup->fd);
172 zfree(&cgroup->name);
173 free(cgroup);
174}
175
176void cgroup__put(struct cgroup *cgrp)
148{ 177{
149 if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) { 178 if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) {
150 close(cgrp->fd); 179 cgroup__delete(cgrp);
151 zfree(&cgrp->name);
152 free(cgrp);
153 } 180 }
154} 181}
155 182
156int parse_cgroups(const struct option *opt __maybe_unused, const char *str, 183struct cgroup *cgroup__get(struct cgroup *cgroup)
184{
185 if (cgroup)
186 refcount_inc(&cgroup->refcnt);
187 return cgroup;
188}
189
190static void evsel__set_default_cgroup(struct perf_evsel *evsel, struct cgroup *cgroup)
191{
192 if (evsel->cgrp == NULL)
193 evsel->cgrp = cgroup__get(cgroup);
194}
195
196void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup)
197{
198 struct perf_evsel *evsel;
199
200 evlist__for_each_entry(evlist, evsel)
201 evsel__set_default_cgroup(evsel, cgroup);
202}
203
204int parse_cgroups(const struct option *opt, const char *str,
157 int unset __maybe_unused) 205 int unset __maybe_unused)
158{ 206{
159 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 207 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
208 struct perf_evsel *counter;
209 struct cgroup *cgrp = NULL;
160 const char *p, *e, *eos = str + strlen(str); 210 const char *p, *e, *eos = str + strlen(str);
161 char *s; 211 char *s;
162 int ret; 212 int ret, i;
163 213
164 if (list_empty(&evlist->entries)) { 214 if (list_empty(&evlist->entries)) {
165 fprintf(stderr, "must define events before cgroups\n"); 215 fprintf(stderr, "must define events before cgroups\n");
@@ -177,10 +227,9 @@ int parse_cgroups(const struct option *opt __maybe_unused, const char *str,
177 if (!s) 227 if (!s)
178 return -1; 228 return -1;
179 ret = add_cgroup(evlist, s); 229 ret = add_cgroup(evlist, s);
180 if (ret) { 230 free(s);
181 free(s); 231 if (ret)
182 return -1; 232 return -1;
183 }
184 } 233 }
185 /* nr_cgroups is increased een for empty cgroups */ 234 /* nr_cgroups is increased een for empty cgroups */
186 nr_cgroups++; 235 nr_cgroups++;
@@ -188,5 +237,18 @@ int parse_cgroups(const struct option *opt __maybe_unused, const char *str,
188 break; 237 break;
189 str = p+1; 238 str = p+1;
190 } 239 }
240 /* for the case one cgroup combine to multiple events */
241 i = 0;
242 if (nr_cgroups == 1) {
243 evlist__for_each_entry(evlist, counter) {
244 if (i == 0)
245 cgrp = counter->cgrp;
246 else {
247 counter->cgrp = cgrp;
248 refcount_inc(&cgrp->refcnt);
249 }
250 i++;
251 }
252 }
191 return 0; 253 return 0;
192} 254}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
index afafc87e9201..f033a80c1b14 100644
--- a/tools/perf/util/cgroup.h
+++ b/tools/perf/util/cgroup.h
@@ -6,7 +6,7 @@
6 6
7struct option; 7struct option;
8 8
9struct cgroup_sel { 9struct cgroup {
10 char *name; 10 char *name;
11 int fd; 11 int fd;
12 refcount_t refcnt; 12 refcount_t refcnt;
@@ -14,7 +14,16 @@ struct cgroup_sel {
14 14
15 15
16extern int nr_cgroups; /* number of explicit cgroups defined */ 16extern int nr_cgroups; /* number of explicit cgroups defined */
17void close_cgroup(struct cgroup_sel *cgrp); 17
18struct cgroup *cgroup__get(struct cgroup *cgroup);
19void cgroup__put(struct cgroup *cgroup);
20
21struct perf_evlist;
22
23struct cgroup *evlist__findnew_cgroup(struct perf_evlist *evlist, const char *name);
24
25void evlist__set_default_cgroup(struct perf_evlist *evlist, struct cgroup *cgroup);
26
18int parse_cgroups(const struct option *opt, const char *str, int unset); 27int parse_cgroups(const struct option *opt, const char *str, int unset);
19 28
20#endif /* __CGROUP_H__ */ 29#endif /* __CGROUP_H__ */
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index 1fb01849f1c7..640af88331b4 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -78,6 +78,8 @@ int cs_etm_decoder__reset(struct cs_etm_decoder *decoder)
78{ 78{
79 ocsd_datapath_resp_t dp_ret; 79 ocsd_datapath_resp_t dp_ret;
80 80
81 decoder->prev_return = OCSD_RESP_CONT;
82
81 dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET, 83 dp_ret = ocsd_dt_process_data(decoder->dcd_tree, OCSD_OP_RESET,
82 0, 0, NULL, NULL); 84 0, 0, NULL, NULL);
83 if (OCSD_DATA_RESP_IS_FATAL(dp_ret)) 85 if (OCSD_DATA_RESP_IS_FATAL(dp_ret))
@@ -253,16 +255,16 @@ static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
253 decoder->packet_count = 0; 255 decoder->packet_count = 0;
254 for (i = 0; i < MAX_BUFFER; i++) { 256 for (i = 0; i < MAX_BUFFER; i++) {
255 decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL; 257 decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL;
256 decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL; 258 decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL;
257 decoder->packet_buffer[i].exc = false; 259 decoder->packet_buffer[i].last_instr_taken_branch = false;
258 decoder->packet_buffer[i].exc_ret = false; 260 decoder->packet_buffer[i].exc = false;
259 decoder->packet_buffer[i].cpu = INT_MIN; 261 decoder->packet_buffer[i].exc_ret = false;
262 decoder->packet_buffer[i].cpu = INT_MIN;
260 } 263 }
261} 264}
262 265
263static ocsd_datapath_resp_t 266static ocsd_datapath_resp_t
264cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, 267cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
265 const ocsd_generic_trace_elem *elem,
266 const u8 trace_chan_id, 268 const u8 trace_chan_id,
267 enum cs_etm_sample_type sample_type) 269 enum cs_etm_sample_type sample_type)
268{ 270{
@@ -278,18 +280,16 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
278 return OCSD_RESP_FATAL_SYS_ERR; 280 return OCSD_RESP_FATAL_SYS_ERR;
279 281
280 et = decoder->tail; 282 et = decoder->tail;
283 et = (et + 1) & (MAX_BUFFER - 1);
284 decoder->tail = et;
285 decoder->packet_count++;
286
281 decoder->packet_buffer[et].sample_type = sample_type; 287 decoder->packet_buffer[et].sample_type = sample_type;
282 decoder->packet_buffer[et].start_addr = elem->st_addr;
283 decoder->packet_buffer[et].end_addr = elem->en_addr;
284 decoder->packet_buffer[et].exc = false; 288 decoder->packet_buffer[et].exc = false;
285 decoder->packet_buffer[et].exc_ret = false; 289 decoder->packet_buffer[et].exc_ret = false;
286 decoder->packet_buffer[et].cpu = *((int *)inode->priv); 290 decoder->packet_buffer[et].cpu = *((int *)inode->priv);
287 291 decoder->packet_buffer[et].start_addr = 0xdeadbeefdeadbeefUL;
288 /* Wrap around if need be */ 292 decoder->packet_buffer[et].end_addr = 0xdeadbeefdeadbeefUL;
289 et = (et + 1) & (MAX_BUFFER - 1);
290
291 decoder->tail = et;
292 decoder->packet_count++;
293 293
294 if (decoder->packet_count == MAX_BUFFER - 1) 294 if (decoder->packet_count == MAX_BUFFER - 1)
295 return OCSD_RESP_WAIT; 295 return OCSD_RESP_WAIT;
@@ -297,6 +297,47 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
297 return OCSD_RESP_CONT; 297 return OCSD_RESP_CONT;
298} 298}
299 299
300static ocsd_datapath_resp_t
301cs_etm_decoder__buffer_range(struct cs_etm_decoder *decoder,
302 const ocsd_generic_trace_elem *elem,
303 const uint8_t trace_chan_id)
304{
305 int ret = 0;
306 struct cs_etm_packet *packet;
307
308 ret = cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
309 CS_ETM_RANGE);
310 if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT)
311 return ret;
312
313 packet = &decoder->packet_buffer[decoder->tail];
314
315 packet->start_addr = elem->st_addr;
316 packet->end_addr = elem->en_addr;
317 switch (elem->last_i_type) {
318 case OCSD_INSTR_BR:
319 case OCSD_INSTR_BR_INDIRECT:
320 packet->last_instr_taken_branch = elem->last_instr_exec;
321 break;
322 case OCSD_INSTR_ISB:
323 case OCSD_INSTR_DSB_DMB:
324 case OCSD_INSTR_OTHER:
325 default:
326 packet->last_instr_taken_branch = false;
327 break;
328 }
329
330 return ret;
331}
332
333static ocsd_datapath_resp_t
334cs_etm_decoder__buffer_trace_on(struct cs_etm_decoder *decoder,
335 const uint8_t trace_chan_id)
336{
337 return cs_etm_decoder__buffer_packet(decoder, trace_chan_id,
338 CS_ETM_TRACE_ON);
339}
340
300static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( 341static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
301 const void *context, 342 const void *context,
302 const ocsd_trc_index_t indx __maybe_unused, 343 const ocsd_trc_index_t indx __maybe_unused,
@@ -313,12 +354,13 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
313 decoder->trace_on = false; 354 decoder->trace_on = false;
314 break; 355 break;
315 case OCSD_GEN_TRC_ELEM_TRACE_ON: 356 case OCSD_GEN_TRC_ELEM_TRACE_ON:
357 resp = cs_etm_decoder__buffer_trace_on(decoder,
358 trace_chan_id);
316 decoder->trace_on = true; 359 decoder->trace_on = true;
317 break; 360 break;
318 case OCSD_GEN_TRC_ELEM_INSTR_RANGE: 361 case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
319 resp = cs_etm_decoder__buffer_packet(decoder, elem, 362 resp = cs_etm_decoder__buffer_range(decoder, elem,
320 trace_chan_id, 363 trace_chan_id);
321 CS_ETM_RANGE);
322 break; 364 break;
323 case OCSD_GEN_TRC_ELEM_EXCEPTION: 365 case OCSD_GEN_TRC_ELEM_EXCEPTION:
324 decoder->packet_buffer[decoder->tail].exc = true; 366 decoder->packet_buffer[decoder->tail].exc = true;
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
index 3d2e6205d186..743f5f444304 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
@@ -24,12 +24,14 @@ struct cs_etm_buffer {
24 24
25enum cs_etm_sample_type { 25enum cs_etm_sample_type {
26 CS_ETM_RANGE = 1 << 0, 26 CS_ETM_RANGE = 1 << 0,
27 CS_ETM_TRACE_ON = 1 << 1,
27}; 28};
28 29
29struct cs_etm_packet { 30struct cs_etm_packet {
30 enum cs_etm_sample_type sample_type; 31 enum cs_etm_sample_type sample_type;
31 u64 start_addr; 32 u64 start_addr;
32 u64 end_addr; 33 u64 end_addr;
34 u8 last_instr_taken_branch;
33 u8 exc; 35 u8 exc;
34 u8 exc_ret; 36 u8 exc_ret;
35 int cpu; 37 int cpu;
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index b9f0a53dfa65..1b0d422373be 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -32,6 +32,14 @@
32 32
33#define MAX_TIMESTAMP (~0ULL) 33#define MAX_TIMESTAMP (~0ULL)
34 34
35/*
36 * A64 instructions are always 4 bytes
37 *
38 * Only A64 is supported, so can use this constant for converting between
39 * addresses and instruction counts, calculting offsets etc
40 */
41#define A64_INSTR_SIZE 4
42
35struct cs_etm_auxtrace { 43struct cs_etm_auxtrace {
36 struct auxtrace auxtrace; 44 struct auxtrace auxtrace;
37 struct auxtrace_queues queues; 45 struct auxtrace_queues queues;
@@ -45,11 +53,15 @@ struct cs_etm_auxtrace {
45 u8 snapshot_mode; 53 u8 snapshot_mode;
46 u8 data_queued; 54 u8 data_queued;
47 u8 sample_branches; 55 u8 sample_branches;
56 u8 sample_instructions;
48 57
49 int num_cpu; 58 int num_cpu;
50 u32 auxtrace_type; 59 u32 auxtrace_type;
51 u64 branches_sample_type; 60 u64 branches_sample_type;
52 u64 branches_id; 61 u64 branches_id;
62 u64 instructions_sample_type;
63 u64 instructions_sample_period;
64 u64 instructions_id;
53 u64 **metadata; 65 u64 **metadata;
54 u64 kernel_start; 66 u64 kernel_start;
55 unsigned int pmu_type; 67 unsigned int pmu_type;
@@ -68,6 +80,12 @@ struct cs_etm_queue {
68 u64 time; 80 u64 time;
69 u64 timestamp; 81 u64 timestamp;
70 u64 offset; 82 u64 offset;
83 u64 period_instructions;
84 struct branch_stack *last_branch;
85 struct branch_stack *last_branch_rb;
86 size_t last_branch_pos;
87 struct cs_etm_packet *prev_packet;
88 struct cs_etm_packet *packet;
71}; 89};
72 90
73static int cs_etm__update_queues(struct cs_etm_auxtrace *etm); 91static int cs_etm__update_queues(struct cs_etm_auxtrace *etm);
@@ -174,6 +192,16 @@ static void cs_etm__free_queue(void *priv)
174{ 192{
175 struct cs_etm_queue *etmq = priv; 193 struct cs_etm_queue *etmq = priv;
176 194
195 if (!etmq)
196 return;
197
198 thread__zput(etmq->thread);
199 cs_etm_decoder__free(etmq->decoder);
200 zfree(&etmq->event_buf);
201 zfree(&etmq->last_branch);
202 zfree(&etmq->last_branch_rb);
203 zfree(&etmq->prev_packet);
204 zfree(&etmq->packet);
177 free(etmq); 205 free(etmq);
178} 206}
179 207
@@ -270,11 +298,35 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
270 struct cs_etm_decoder_params d_params; 298 struct cs_etm_decoder_params d_params;
271 struct cs_etm_trace_params *t_params; 299 struct cs_etm_trace_params *t_params;
272 struct cs_etm_queue *etmq; 300 struct cs_etm_queue *etmq;
301 size_t szp = sizeof(struct cs_etm_packet);
273 302
274 etmq = zalloc(sizeof(*etmq)); 303 etmq = zalloc(sizeof(*etmq));
275 if (!etmq) 304 if (!etmq)
276 return NULL; 305 return NULL;
277 306
307 etmq->packet = zalloc(szp);
308 if (!etmq->packet)
309 goto out_free;
310
311 if (etm->synth_opts.last_branch || etm->sample_branches) {
312 etmq->prev_packet = zalloc(szp);
313 if (!etmq->prev_packet)
314 goto out_free;
315 }
316
317 if (etm->synth_opts.last_branch) {
318 size_t sz = sizeof(struct branch_stack);
319
320 sz += etm->synth_opts.last_branch_sz *
321 sizeof(struct branch_entry);
322 etmq->last_branch = zalloc(sz);
323 if (!etmq->last_branch)
324 goto out_free;
325 etmq->last_branch_rb = zalloc(sz);
326 if (!etmq->last_branch_rb)
327 goto out_free;
328 }
329
278 etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE); 330 etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
279 if (!etmq->event_buf) 331 if (!etmq->event_buf)
280 goto out_free; 332 goto out_free;
@@ -329,6 +381,7 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
329 goto out_free_decoder; 381 goto out_free_decoder;
330 382
331 etmq->offset = 0; 383 etmq->offset = 0;
384 etmq->period_instructions = 0;
332 385
333 return etmq; 386 return etmq;
334 387
@@ -336,6 +389,10 @@ out_free_decoder:
336 cs_etm_decoder__free(etmq->decoder); 389 cs_etm_decoder__free(etmq->decoder);
337out_free: 390out_free:
338 zfree(&etmq->event_buf); 391 zfree(&etmq->event_buf);
392 zfree(&etmq->last_branch);
393 zfree(&etmq->last_branch_rb);
394 zfree(&etmq->prev_packet);
395 zfree(&etmq->packet);
339 free(etmq); 396 free(etmq);
340 397
341 return NULL; 398 return NULL;
@@ -389,6 +446,129 @@ static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
389 return 0; 446 return 0;
390} 447}
391 448
449static inline void cs_etm__copy_last_branch_rb(struct cs_etm_queue *etmq)
450{
451 struct branch_stack *bs_src = etmq->last_branch_rb;
452 struct branch_stack *bs_dst = etmq->last_branch;
453 size_t nr = 0;
454
455 /*
456 * Set the number of records before early exit: ->nr is used to
457 * determine how many branches to copy from ->entries.
458 */
459 bs_dst->nr = bs_src->nr;
460
461 /*
462 * Early exit when there is nothing to copy.
463 */
464 if (!bs_src->nr)
465 return;
466
467 /*
468 * As bs_src->entries is a circular buffer, we need to copy from it in
469 * two steps. First, copy the branches from the most recently inserted
470 * branch ->last_branch_pos until the end of bs_src->entries buffer.
471 */
472 nr = etmq->etm->synth_opts.last_branch_sz - etmq->last_branch_pos;
473 memcpy(&bs_dst->entries[0],
474 &bs_src->entries[etmq->last_branch_pos],
475 sizeof(struct branch_entry) * nr);
476
477 /*
478 * If we wrapped around at least once, the branches from the beginning
479 * of the bs_src->entries buffer and until the ->last_branch_pos element
480 * are older valid branches: copy them over. The total number of
481 * branches copied over will be equal to the number of branches asked by
482 * the user in last_branch_sz.
483 */
484 if (bs_src->nr >= etmq->etm->synth_opts.last_branch_sz) {
485 memcpy(&bs_dst->entries[nr],
486 &bs_src->entries[0],
487 sizeof(struct branch_entry) * etmq->last_branch_pos);
488 }
489}
490
491static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq)
492{
493 etmq->last_branch_pos = 0;
494 etmq->last_branch_rb->nr = 0;
495}
496
497static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet)
498{
499 /*
500 * The packet records the execution range with an exclusive end address
501 *
502 * A64 instructions are constant size, so the last executed
503 * instruction is A64_INSTR_SIZE before the end address
504 * Will need to do instruction level decode for T32 instructions as
505 * they can be variable size (not yet supported).
506 */
507 return packet->end_addr - A64_INSTR_SIZE;
508}
509
510static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet)
511{
512 /*
513 * Only A64 instructions are currently supported, so can get
514 * instruction count by dividing.
515 * Will need to do instruction level decode for T32 instructions as
516 * they can be variable size (not yet supported).
517 */
518 return (packet->end_addr - packet->start_addr) / A64_INSTR_SIZE;
519}
520
521static inline u64 cs_etm__instr_addr(const struct cs_etm_packet *packet,
522 u64 offset)
523{
524 /*
525 * Only A64 instructions are currently supported, so can get
526 * instruction address by muliplying.
527 * Will need to do instruction level decode for T32 instructions as
528 * they can be variable size (not yet supported).
529 */
530 return packet->start_addr + offset * A64_INSTR_SIZE;
531}
532
533static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq)
534{
535 struct branch_stack *bs = etmq->last_branch_rb;
536 struct branch_entry *be;
537
538 /*
539 * The branches are recorded in a circular buffer in reverse
540 * chronological order: we start recording from the last element of the
541 * buffer down. After writing the first element of the stack, move the
542 * insert position back to the end of the buffer.
543 */
544 if (!etmq->last_branch_pos)
545 etmq->last_branch_pos = etmq->etm->synth_opts.last_branch_sz;
546
547 etmq->last_branch_pos -= 1;
548
549 be = &bs->entries[etmq->last_branch_pos];
550 be->from = cs_etm__last_executed_instr(etmq->prev_packet);
551 be->to = etmq->packet->start_addr;
552 /* No support for mispredict */
553 be->flags.mispred = 0;
554 be->flags.predicted = 1;
555
556 /*
557 * Increment bs->nr until reaching the number of last branches asked by
558 * the user on the command line.
559 */
560 if (bs->nr < etmq->etm->synth_opts.last_branch_sz)
561 bs->nr += 1;
562}
563
564static int cs_etm__inject_event(union perf_event *event,
565 struct perf_sample *sample, u64 type)
566{
567 event->header.size = perf_event__sample_event_size(sample, type, 0);
568 return perf_event__synthesize_sample(event, type, 0, sample);
569}
570
571
392static int 572static int
393cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq) 573cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
394{ 574{
@@ -453,35 +633,105 @@ static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
453 } 633 }
454} 634}
455 635
636static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
637 u64 addr, u64 period)
638{
639 int ret = 0;
640 struct cs_etm_auxtrace *etm = etmq->etm;
641 union perf_event *event = etmq->event_buf;
642 struct perf_sample sample = {.ip = 0,};
643
644 event->sample.header.type = PERF_RECORD_SAMPLE;
645 event->sample.header.misc = PERF_RECORD_MISC_USER;
646 event->sample.header.size = sizeof(struct perf_event_header);
647
648 sample.ip = addr;
649 sample.pid = etmq->pid;
650 sample.tid = etmq->tid;
651 sample.id = etmq->etm->instructions_id;
652 sample.stream_id = etmq->etm->instructions_id;
653 sample.period = period;
654 sample.cpu = etmq->packet->cpu;
655 sample.flags = 0;
656 sample.insn_len = 1;
657 sample.cpumode = event->header.misc;
658
659 if (etm->synth_opts.last_branch) {
660 cs_etm__copy_last_branch_rb(etmq);
661 sample.branch_stack = etmq->last_branch;
662 }
663
664 if (etm->synth_opts.inject) {
665 ret = cs_etm__inject_event(event, &sample,
666 etm->instructions_sample_type);
667 if (ret)
668 return ret;
669 }
670
671 ret = perf_session__deliver_synth_event(etm->session, event, &sample);
672
673 if (ret)
674 pr_err(
675 "CS ETM Trace: failed to deliver instruction event, error %d\n",
676 ret);
677
678 if (etm->synth_opts.last_branch)
679 cs_etm__reset_last_branch_rb(etmq);
680
681 return ret;
682}
683
456/* 684/*
457 * The cs etm packet encodes an instruction range between a branch target 685 * The cs etm packet encodes an instruction range between a branch target
458 * and the next taken branch. Generate sample accordingly. 686 * and the next taken branch. Generate sample accordingly.
459 */ 687 */
460static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, 688static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
461 struct cs_etm_packet *packet)
462{ 689{
463 int ret = 0; 690 int ret = 0;
464 struct cs_etm_auxtrace *etm = etmq->etm; 691 struct cs_etm_auxtrace *etm = etmq->etm;
465 struct perf_sample sample = {.ip = 0,}; 692 struct perf_sample sample = {.ip = 0,};
466 union perf_event *event = etmq->event_buf; 693 union perf_event *event = etmq->event_buf;
467 u64 start_addr = packet->start_addr; 694 struct dummy_branch_stack {
468 u64 end_addr = packet->end_addr; 695 u64 nr;
696 struct branch_entry entries;
697 } dummy_bs;
469 698
470 event->sample.header.type = PERF_RECORD_SAMPLE; 699 event->sample.header.type = PERF_RECORD_SAMPLE;
471 event->sample.header.misc = PERF_RECORD_MISC_USER; 700 event->sample.header.misc = PERF_RECORD_MISC_USER;
472 event->sample.header.size = sizeof(struct perf_event_header); 701 event->sample.header.size = sizeof(struct perf_event_header);
473 702
474 sample.ip = start_addr; 703 sample.ip = cs_etm__last_executed_instr(etmq->prev_packet);
475 sample.pid = etmq->pid; 704 sample.pid = etmq->pid;
476 sample.tid = etmq->tid; 705 sample.tid = etmq->tid;
477 sample.addr = end_addr; 706 sample.addr = etmq->packet->start_addr;
478 sample.id = etmq->etm->branches_id; 707 sample.id = etmq->etm->branches_id;
479 sample.stream_id = etmq->etm->branches_id; 708 sample.stream_id = etmq->etm->branches_id;
480 sample.period = 1; 709 sample.period = 1;
481 sample.cpu = packet->cpu; 710 sample.cpu = etmq->packet->cpu;
482 sample.flags = 0; 711 sample.flags = 0;
483 sample.cpumode = PERF_RECORD_MISC_USER; 712 sample.cpumode = PERF_RECORD_MISC_USER;
484 713
714 /*
715 * perf report cannot handle events without a branch stack
716 */
717 if (etm->synth_opts.last_branch) {
718 dummy_bs = (struct dummy_branch_stack){
719 .nr = 1,
720 .entries = {
721 .from = sample.ip,
722 .to = sample.addr,
723 },
724 };
725 sample.branch_stack = (struct branch_stack *)&dummy_bs;
726 }
727
728 if (etm->synth_opts.inject) {
729 ret = cs_etm__inject_event(event, &sample,
730 etm->branches_sample_type);
731 if (ret)
732 return ret;
733 }
734
485 ret = perf_session__deliver_synth_event(etm->session, event, &sample); 735 ret = perf_session__deliver_synth_event(etm->session, event, &sample);
486 736
487 if (ret) 737 if (ret)
@@ -578,6 +828,24 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
578 etm->sample_branches = true; 828 etm->sample_branches = true;
579 etm->branches_sample_type = attr.sample_type; 829 etm->branches_sample_type = attr.sample_type;
580 etm->branches_id = id; 830 etm->branches_id = id;
831 id += 1;
832 attr.sample_type &= ~(u64)PERF_SAMPLE_ADDR;
833 }
834
835 if (etm->synth_opts.last_branch)
836 attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
837
838 if (etm->synth_opts.instructions) {
839 attr.config = PERF_COUNT_HW_INSTRUCTIONS;
840 attr.sample_period = etm->synth_opts.period;
841 etm->instructions_sample_period = attr.sample_period;
842 err = cs_etm__synth_event(session, &attr, id);
843 if (err)
844 return err;
845 etm->sample_instructions = true;
846 etm->instructions_sample_type = attr.sample_type;
847 etm->instructions_id = id;
848 id += 1;
581 } 849 }
582 850
583 return 0; 851 return 0;
@@ -585,25 +853,108 @@ static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
585 853
586static int cs_etm__sample(struct cs_etm_queue *etmq) 854static int cs_etm__sample(struct cs_etm_queue *etmq)
587{ 855{
856 struct cs_etm_auxtrace *etm = etmq->etm;
857 struct cs_etm_packet *tmp;
588 int ret; 858 int ret;
589 struct cs_etm_packet packet; 859 u64 instrs_executed;
590 860
591 while (1) { 861 instrs_executed = cs_etm__instr_count(etmq->packet);
592 ret = cs_etm_decoder__get_packet(etmq->decoder, &packet); 862 etmq->period_instructions += instrs_executed;
593 if (ret <= 0) 863
864 /*
865 * Record a branch when the last instruction in
866 * PREV_PACKET is a branch.
867 */
868 if (etm->synth_opts.last_branch &&
869 etmq->prev_packet &&
870 etmq->prev_packet->sample_type == CS_ETM_RANGE &&
871 etmq->prev_packet->last_instr_taken_branch)
872 cs_etm__update_last_branch_rb(etmq);
873
874 if (etm->sample_instructions &&
875 etmq->period_instructions >= etm->instructions_sample_period) {
876 /*
877 * Emit instruction sample periodically
878 * TODO: allow period to be defined in cycles and clock time
879 */
880
881 /* Get number of instructions executed after the sample point */
882 u64 instrs_over = etmq->period_instructions -
883 etm->instructions_sample_period;
884
885 /*
886 * Calculate the address of the sampled instruction (-1 as
887 * sample is reported as though instruction has just been
888 * executed, but PC has not advanced to next instruction)
889 */
890 u64 offset = (instrs_executed - instrs_over - 1);
891 u64 addr = cs_etm__instr_addr(etmq->packet, offset);
892
893 ret = cs_etm__synth_instruction_sample(
894 etmq, addr, etm->instructions_sample_period);
895 if (ret)
896 return ret;
897
898 /* Carry remaining instructions into next sample period */
899 etmq->period_instructions = instrs_over;
900 }
901
902 if (etm->sample_branches &&
903 etmq->prev_packet &&
904 etmq->prev_packet->sample_type == CS_ETM_RANGE &&
905 etmq->prev_packet->last_instr_taken_branch) {
906 ret = cs_etm__synth_branch_sample(etmq);
907 if (ret)
594 return ret; 908 return ret;
909 }
595 910
911 if (etm->sample_branches || etm->synth_opts.last_branch) {
596 /* 912 /*
597 * If the packet contains an instruction range, generate an 913 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
598 * instruction sequence event. 914 * the next incoming packet.
599 */ 915 */
600 if (packet.sample_type & CS_ETM_RANGE) 916 tmp = etmq->packet;
601 cs_etm__synth_branch_sample(etmq, &packet); 917 etmq->packet = etmq->prev_packet;
918 etmq->prev_packet = tmp;
602 } 919 }
603 920
604 return 0; 921 return 0;
605} 922}
606 923
924static int cs_etm__flush(struct cs_etm_queue *etmq)
925{
926 int err = 0;
927 struct cs_etm_packet *tmp;
928
929 if (etmq->etm->synth_opts.last_branch &&
930 etmq->prev_packet &&
931 etmq->prev_packet->sample_type == CS_ETM_RANGE) {
932 /*
933 * Generate a last branch event for the branches left in the
934 * circular buffer at the end of the trace.
935 *
936 * Use the address of the end of the last reported execution
937 * range
938 */
939 u64 addr = cs_etm__last_executed_instr(etmq->prev_packet);
940
941 err = cs_etm__synth_instruction_sample(
942 etmq, addr,
943 etmq->period_instructions);
944 etmq->period_instructions = 0;
945
946 /*
947 * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
948 * the next incoming packet.
949 */
950 tmp = etmq->packet;
951 etmq->packet = etmq->prev_packet;
952 etmq->prev_packet = tmp;
953 }
954
955 return err;
956}
957
607static int cs_etm__run_decoder(struct cs_etm_queue *etmq) 958static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
608{ 959{
609 struct cs_etm_auxtrace *etm = etmq->etm; 960 struct cs_etm_auxtrace *etm = etmq->etm;
@@ -615,45 +966,72 @@ static int cs_etm__run_decoder(struct cs_etm_queue *etmq)
615 etm->kernel_start = machine__kernel_start(etm->machine); 966 etm->kernel_start = machine__kernel_start(etm->machine);
616 967
617 /* Go through each buffer in the queue and decode them one by one */ 968 /* Go through each buffer in the queue and decode them one by one */
618more: 969 while (1) {
619 buffer_used = 0; 970 buffer_used = 0;
620 memset(&buffer, 0, sizeof(buffer)); 971 memset(&buffer, 0, sizeof(buffer));
621 err = cs_etm__get_trace(&buffer, etmq); 972 err = cs_etm__get_trace(&buffer, etmq);
622 if (err <= 0) 973 if (err <= 0)
623 return err;
624 /*
625 * We cannot assume consecutive blocks in the data file are contiguous,
626 * reset the decoder to force re-sync.
627 */
628 err = cs_etm_decoder__reset(etmq->decoder);
629 if (err != 0)
630 return err;
631
632 /* Run trace decoder until buffer consumed or end of trace */
633 do {
634 processed = 0;
635
636 err = cs_etm_decoder__process_data_block(
637 etmq->decoder,
638 etmq->offset,
639 &buffer.buf[buffer_used],
640 buffer.len - buffer_used,
641 &processed);
642
643 if (err)
644 return err; 974 return err;
645
646 etmq->offset += processed;
647 buffer_used += processed;
648
649 /* 975 /*
650 * Nothing to do with an error condition, let's hope the next 976 * We cannot assume consecutive blocks in the data file are
651 * chunk will be better. 977 * contiguous, reset the decoder to force re-sync.
652 */ 978 */
653 err = cs_etm__sample(etmq); 979 err = cs_etm_decoder__reset(etmq->decoder);
654 } while (buffer.len > buffer_used); 980 if (err != 0)
981 return err;
982
983 /* Run trace decoder until buffer consumed or end of trace */
984 do {
985 processed = 0;
986 err = cs_etm_decoder__process_data_block(
987 etmq->decoder,
988 etmq->offset,
989 &buffer.buf[buffer_used],
990 buffer.len - buffer_used,
991 &processed);
992 if (err)
993 return err;
994
995 etmq->offset += processed;
996 buffer_used += processed;
997
998 /* Process each packet in this chunk */
999 while (1) {
1000 err = cs_etm_decoder__get_packet(etmq->decoder,
1001 etmq->packet);
1002 if (err <= 0)
1003 /*
1004 * Stop processing this chunk on
1005 * end of data or error
1006 */
1007 break;
1008
1009 switch (etmq->packet->sample_type) {
1010 case CS_ETM_RANGE:
1011 /*
1012 * If the packet contains an instruction
1013 * range, generate instruction sequence
1014 * events.
1015 */
1016 cs_etm__sample(etmq);
1017 break;
1018 case CS_ETM_TRACE_ON:
1019 /*
1020 * Discontinuity in trace, flush
1021 * previous branch stack
1022 */
1023 cs_etm__flush(etmq);
1024 break;
1025 default:
1026 break;
1027 }
1028 }
1029 } while (buffer.len > buffer_used);
655 1030
656goto more; 1031 if (err == 0)
1032 /* Flush any remaining branch stack entries */
1033 err = cs_etm__flush(etmq);
1034 }
657 1035
658 return err; 1036 return err;
659} 1037}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index f3a71db83947..3d6459626c2a 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -232,7 +232,6 @@ int perf_quiet_option(void)
232 var++; 232 var++;
233 } 233 }
234 234
235 quiet = true;
236 return 0; 235 return 0;
237} 236}
238 237
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 6d311868d850..4c842762e3f2 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -32,6 +32,10 @@ void perf_env__exit(struct perf_env *env)
32 for (i = 0; i < env->caches_cnt; i++) 32 for (i = 0; i < env->caches_cnt; i++)
33 cpu_cache_level__free(&env->caches[i]); 33 cpu_cache_level__free(&env->caches[i]);
34 zfree(&env->caches); 34 zfree(&env->caches);
35
36 for (i = 0; i < env->nr_memory_nodes; i++)
37 free(env->memory_nodes[i].set);
38 zfree(&env->memory_nodes);
35} 39}
36 40
37int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) 41int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index bf970f57dce0..c4ef2e523367 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -27,6 +27,12 @@ struct numa_node {
27 struct cpu_map *map; 27 struct cpu_map *map;
28}; 28};
29 29
30struct memory_node {
31 u64 node;
32 u64 size;
33 unsigned long *set;
34};
35
30struct perf_env { 36struct perf_env {
31 char *hostname; 37 char *hostname;
32 char *os_release; 38 char *os_release;
@@ -43,6 +49,7 @@ struct perf_env {
43 int nr_sibling_cores; 49 int nr_sibling_cores;
44 int nr_sibling_threads; 50 int nr_sibling_threads;
45 int nr_numa_nodes; 51 int nr_numa_nodes;
52 int nr_memory_nodes;
46 int nr_pmu_mappings; 53 int nr_pmu_mappings;
47 int nr_groups; 54 int nr_groups;
48 char *cmdline; 55 char *cmdline;
@@ -54,6 +61,8 @@ struct perf_env {
54 struct cpu_cache_level *caches; 61 struct cpu_cache_level *caches;
55 int caches_cnt; 62 int caches_cnt;
56 struct numa_node *numa_nodes; 63 struct numa_node *numa_nodes;
64 struct memory_node *memory_nodes;
65 unsigned long long memory_bsize;
57}; 66};
58 67
59extern struct perf_env perf_env; 68extern struct perf_env perf_env;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 44e603c27944..f0a6cbd033cc 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -894,8 +894,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
894 struct machine *machine) 894 struct machine *machine)
895{ 895{
896 size_t size; 896 size_t size;
897 const char *mmap_name;
898 char name_buff[PATH_MAX];
899 struct map *map = machine__kernel_map(machine); 897 struct map *map = machine__kernel_map(machine);
900 struct kmap *kmap; 898 struct kmap *kmap;
901 int err; 899 int err;
@@ -918,7 +916,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
918 return -1; 916 return -1;
919 } 917 }
920 918
921 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
922 if (machine__is_host(machine)) { 919 if (machine__is_host(machine)) {
923 /* 920 /*
924 * kernel uses PERF_RECORD_MISC_USER for user space maps, 921 * kernel uses PERF_RECORD_MISC_USER for user space maps,
@@ -931,7 +928,7 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
931 928
932 kmap = map__kmap(map); 929 kmap = map__kmap(map);
933 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 930 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
934 "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; 931 "%s%s", machine->mmap_name, kmap->ref_reloc_sym->name) + 1;
935 size = PERF_ALIGN(size, sizeof(u64)); 932 size = PERF_ALIGN(size, sizeof(u64));
936 event->mmap.header.type = PERF_RECORD_MMAP; 933 event->mmap.header.type = PERF_RECORD_MMAP;
937 event->mmap.header.size = (sizeof(event->mmap) - 934 event->mmap.header.size = (sizeof(event->mmap) -
@@ -1591,17 +1588,6 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
1591 return -1; 1588 return -1;
1592 1589
1593 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); 1590 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
1594 /*
1595 * Have we already created the kernel maps for this machine?
1596 *
1597 * This should have happened earlier, when we processed the kernel MMAP
1598 * events, but for older perf.data files there was no such thing, so do
1599 * it now.
1600 */
1601 if (sample->cpumode == PERF_RECORD_MISC_KERNEL &&
1602 machine__kernel_map(machine) == NULL)
1603 machine__create_kernel_maps(machine);
1604
1605 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al); 1591 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al);
1606 dump_printf(" ...... dso: %s\n", 1592 dump_printf(" ...... dso: %s\n",
1607 al->map ? al->map->dso->long_name : 1593 al->map ? al->map->dso->long_name :
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e5fc14e53c05..a59281d64368 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -702,29 +702,6 @@ static int perf_evlist__resume(struct perf_evlist *evlist)
702 return perf_evlist__set_paused(evlist, false); 702 return perf_evlist__set_paused(evlist, false);
703} 703}
704 704
705union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx)
706{
707 struct perf_mmap *md = &evlist->mmap[idx];
708
709 /*
710 * Check messup is required for forward overwritable ring buffer:
711 * memory pointed by md->prev can be overwritten in this case.
712 * No need for read-write ring buffer: kernel stop outputting when
713 * it hit md->prev (perf_mmap__consume()).
714 */
715 return perf_mmap__read_forward(md);
716}
717
718union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
719{
720 return perf_evlist__mmap_read_forward(evlist, idx);
721}
722
723void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
724{
725 perf_mmap__consume(&evlist->mmap[idx], false);
726}
727
728static void perf_evlist__munmap_nofree(struct perf_evlist *evlist) 705static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
729{ 706{
730 int i; 707 int i;
@@ -745,7 +722,8 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
745 zfree(&evlist->overwrite_mmap); 722 zfree(&evlist->overwrite_mmap);
746} 723}
747 724
748static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist) 725static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist,
726 bool overwrite)
749{ 727{
750 int i; 728 int i;
751 struct perf_mmap *map; 729 struct perf_mmap *map;
@@ -759,9 +737,10 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
759 737
760 for (i = 0; i < evlist->nr_mmaps; i++) { 738 for (i = 0; i < evlist->nr_mmaps; i++) {
761 map[i].fd = -1; 739 map[i].fd = -1;
740 map[i].overwrite = overwrite;
762 /* 741 /*
763 * When the perf_mmap() call is made we grab one refcount, plus 742 * When the perf_mmap() call is made we grab one refcount, plus
764 * one extra to let perf_evlist__mmap_consume() get the last 743 * one extra to let perf_mmap__consume() get the last
765 * events after all real references (perf_mmap__get()) are 744 * events after all real references (perf_mmap__get()) are
766 * dropped. 745 * dropped.
767 * 746 *
@@ -802,7 +781,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
802 maps = evlist->overwrite_mmap; 781 maps = evlist->overwrite_mmap;
803 782
804 if (!maps) { 783 if (!maps) {
805 maps = perf_evlist__alloc_mmap(evlist); 784 maps = perf_evlist__alloc_mmap(evlist, true);
806 if (!maps) 785 if (!maps)
807 return -1; 786 return -1;
808 evlist->overwrite_mmap = maps; 787 evlist->overwrite_mmap = maps;
@@ -1052,7 +1031,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1052 struct mmap_params mp; 1031 struct mmap_params mp;
1053 1032
1054 if (!evlist->mmap) 1033 if (!evlist->mmap)
1055 evlist->mmap = perf_evlist__alloc_mmap(evlist); 1034 evlist->mmap = perf_evlist__alloc_mmap(evlist, false);
1056 if (!evlist->mmap) 1035 if (!evlist->mmap)
1057 return -ENOMEM; 1036 return -ENOMEM;
1058 1037
@@ -1086,11 +1065,30 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
1086 1065
1087int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) 1066int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
1088{ 1067{
1068 bool all_threads = (target->per_thread && target->system_wide);
1089 struct cpu_map *cpus; 1069 struct cpu_map *cpus;
1090 struct thread_map *threads; 1070 struct thread_map *threads;
1091 1071
1072 /*
1073 * If specify '-a' and '--per-thread' to perf record, perf record
1074 * will override '--per-thread'. target->per_thread = false and
1075 * target->system_wide = true.
1076 *
1077 * If specify '--per-thread' only to perf record,
1078 * target->per_thread = true and target->system_wide = false.
1079 *
1080 * So target->per_thread && target->system_wide is false.
1081 * For perf record, thread_map__new_str doesn't call
1082 * thread_map__new_all_cpus. That will keep perf record's
1083 * current behavior.
1084 *
1085 * For perf stat, it allows the case that target->per_thread and
1086 * target->system_wide are all true. It means to collect system-wide
1087 * per-thread data. thread_map__new_str will call
1088 * thread_map__new_all_cpus to enumerate all threads.
1089 */
1092 threads = thread_map__new_str(target->pid, target->tid, target->uid, 1090 threads = thread_map__new_str(target->pid, target->tid, target->uid,
1093 target->per_thread); 1091 all_threads);
1094 1092
1095 if (!threads) 1093 if (!threads)
1096 return -1; 1094 return -1;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 336b838e6957..6c41b2f78713 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -129,10 +129,6 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
129 129
130void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state); 130void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state);
131 131
132union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
133
134union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist,
135 int idx);
136void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 132void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
137 133
138int perf_evlist__open(struct perf_evlist *evlist); 134int perf_evlist__open(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ef351688b797..1ac8d9236efd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -244,6 +244,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
244 evsel->metric_name = NULL; 244 evsel->metric_name = NULL;
245 evsel->metric_events = NULL; 245 evsel->metric_events = NULL;
246 evsel->collect_stat = false; 246 evsel->collect_stat = false;
247 evsel->pmu_name = NULL;
247} 248}
248 249
249struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) 250struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
@@ -621,22 +622,34 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel)
621 return evsel->group_name ?: "anon group"; 622 return evsel->group_name ?: "anon group";
622} 623}
623 624
625/*
626 * Returns the group details for the specified leader,
627 * with following rules.
628 *
629 * For record -e '{cycles,instructions}'
630 * 'anon group { cycles:u, instructions:u }'
631 *
632 * For record -e 'cycles,instructions' and report --group
633 * 'cycles:u, instructions:u'
634 */
624int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) 635int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
625{ 636{
626 int ret; 637 int ret = 0;
627 struct perf_evsel *pos; 638 struct perf_evsel *pos;
628 const char *group_name = perf_evsel__group_name(evsel); 639 const char *group_name = perf_evsel__group_name(evsel);
629 640
630 ret = scnprintf(buf, size, "%s", group_name); 641 if (!evsel->forced_leader)
642 ret = scnprintf(buf, size, "%s { ", group_name);
631 643
632 ret += scnprintf(buf + ret, size - ret, " { %s", 644 ret += scnprintf(buf + ret, size - ret, "%s",
633 perf_evsel__name(evsel)); 645 perf_evsel__name(evsel));
634 646
635 for_each_group_member(pos, evsel) 647 for_each_group_member(pos, evsel)
636 ret += scnprintf(buf + ret, size - ret, ", %s", 648 ret += scnprintf(buf + ret, size - ret, ", %s",
637 perf_evsel__name(pos)); 649 perf_evsel__name(pos));
638 650
639 ret += scnprintf(buf + ret, size - ret, " }"); 651 if (!evsel->forced_leader)
652 ret += scnprintf(buf + ret, size - ret, " }");
640 653
641 return ret; 654 return ret;
642} 655}
@@ -1233,7 +1246,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
1233 perf_evsel__free_fd(evsel); 1246 perf_evsel__free_fd(evsel);
1234 perf_evsel__free_id(evsel); 1247 perf_evsel__free_id(evsel);
1235 perf_evsel__free_config_terms(evsel); 1248 perf_evsel__free_config_terms(evsel);
1236 close_cgroup(evsel->cgrp); 1249 cgroup__put(evsel->cgrp);
1237 cpu_map__put(evsel->cpus); 1250 cpu_map__put(evsel->cpus);
1238 cpu_map__put(evsel->own_cpus); 1251 cpu_map__put(evsel->own_cpus);
1239 thread_map__put(evsel->threads); 1252 thread_map__put(evsel->threads);
@@ -1915,6 +1928,9 @@ try_fallback:
1915 goto fallback_missing_features; 1928 goto fallback_missing_features;
1916 } 1929 }
1917out_close: 1930out_close:
1931 if (err)
1932 threads->err_thread = thread;
1933
1918 do { 1934 do {
1919 while (--thread >= 0) { 1935 while (--thread >= 0) {
1920 close(FD(evsel, cpu, thread)); 1936 close(FD(evsel, cpu, thread));
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index a7487c6d1866..d3ee3af618ef 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -30,7 +30,7 @@ struct perf_sample_id {
30 u64 period; 30 u64 period;
31}; 31};
32 32
33struct cgroup_sel; 33struct cgroup;
34 34
35/* 35/*
36 * The 'struct perf_evsel_config_term' is used to pass event 36 * The 'struct perf_evsel_config_term' is used to pass event
@@ -107,7 +107,7 @@ struct perf_evsel {
107 struct perf_stat_evsel *stats; 107 struct perf_stat_evsel *stats;
108 void *priv; 108 void *priv;
109 u64 db_id; 109 u64 db_id;
110 struct cgroup_sel *cgrp; 110 struct cgroup *cgrp;
111 void *handler; 111 void *handler;
112 struct cpu_map *cpus; 112 struct cpu_map *cpus;
113 struct cpu_map *own_cpus; 113 struct cpu_map *own_cpus;
@@ -125,6 +125,7 @@ struct perf_evsel {
125 bool per_pkg; 125 bool per_pkg;
126 bool precise_max; 126 bool precise_max;
127 bool ignore_missing_thread; 127 bool ignore_missing_thread;
128 bool forced_leader;
128 /* parse modifier helper */ 129 /* parse modifier helper */
129 int exclude_GH; 130 int exclude_GH;
130 int nr_members; 131 int nr_members;
@@ -142,6 +143,7 @@ struct perf_evsel {
142 struct perf_evsel **metric_events; 143 struct perf_evsel **metric_events;
143 bool collect_stat; 144 bool collect_stat;
144 bool weak_group; 145 bool weak_group;
146 const char *pmu_name;
145}; 147};
146 148
147union u64_swap { 149union u64_swap {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a326e0d8b5b6..121df1683c36 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -17,6 +17,7 @@
17#include <sys/stat.h> 17#include <sys/stat.h>
18#include <sys/utsname.h> 18#include <sys/utsname.h>
19#include <linux/time64.h> 19#include <linux/time64.h>
20#include <dirent.h>
20 21
21#include "evlist.h" 22#include "evlist.h"
22#include "evsel.h" 23#include "evsel.h"
@@ -37,6 +38,7 @@
37#include "asm/bug.h" 38#include "asm/bug.h"
38#include "tool.h" 39#include "tool.h"
39#include "time-utils.h" 40#include "time-utils.h"
41#include "units.h"
40 42
41#include "sane_ctype.h" 43#include "sane_ctype.h"
42 44
@@ -132,6 +134,25 @@ int do_write(struct feat_fd *ff, const void *buf, size_t size)
132} 134}
133 135
134/* Return: 0 if succeded, -ERR if failed. */ 136/* Return: 0 if succeded, -ERR if failed. */
137static int do_write_bitmap(struct feat_fd *ff, unsigned long *set, u64 size)
138{
139 u64 *p = (u64 *) set;
140 int i, ret;
141
142 ret = do_write(ff, &size, sizeof(size));
143 if (ret < 0)
144 return ret;
145
146 for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
147 ret = do_write(ff, p + i, sizeof(*p));
148 if (ret < 0)
149 return ret;
150 }
151
152 return 0;
153}
154
155/* Return: 0 if succeded, -ERR if failed. */
135int write_padded(struct feat_fd *ff, const void *bf, 156int write_padded(struct feat_fd *ff, const void *bf,
136 size_t count, size_t count_aligned) 157 size_t count, size_t count_aligned)
137{ 158{
@@ -243,6 +264,38 @@ static char *do_read_string(struct feat_fd *ff)
243 return NULL; 264 return NULL;
244} 265}
245 266
267/* Return: 0 if succeded, -ERR if failed. */
268static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize)
269{
270 unsigned long *set;
271 u64 size, *p;
272 int i, ret;
273
274 ret = do_read_u64(ff, &size);
275 if (ret)
276 return ret;
277
278 set = bitmap_alloc(size);
279 if (!set)
280 return -ENOMEM;
281
282 bitmap_zero(set, size);
283
284 p = (u64 *) set;
285
286 for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
287 ret = do_read_u64(ff, p + i);
288 if (ret < 0) {
289 free(set);
290 return ret;
291 }
292 }
293
294 *pset = set;
295 *psize = size;
296 return 0;
297}
298
246static int write_tracing_data(struct feat_fd *ff, 299static int write_tracing_data(struct feat_fd *ff,
247 struct perf_evlist *evlist) 300 struct perf_evlist *evlist)
248{ 301{
@@ -1196,6 +1249,176 @@ static int write_sample_time(struct feat_fd *ff,
1196 sizeof(evlist->last_sample_time)); 1249 sizeof(evlist->last_sample_time));
1197} 1250}
1198 1251
1252
1253static int memory_node__read(struct memory_node *n, unsigned long idx)
1254{
1255 unsigned int phys, size = 0;
1256 char path[PATH_MAX];
1257 struct dirent *ent;
1258 DIR *dir;
1259
1260#define for_each_memory(mem, dir) \
1261 while ((ent = readdir(dir))) \
1262 if (strcmp(ent->d_name, ".") && \
1263 strcmp(ent->d_name, "..") && \
1264 sscanf(ent->d_name, "memory%u", &mem) == 1)
1265
1266 scnprintf(path, PATH_MAX,
1267 "%s/devices/system/node/node%lu",
1268 sysfs__mountpoint(), idx);
1269
1270 dir = opendir(path);
1271 if (!dir) {
1272 pr_warning("failed: cant' open memory sysfs data\n");
1273 return -1;
1274 }
1275
1276 for_each_memory(phys, dir) {
1277 size = max(phys, size);
1278 }
1279
1280 size++;
1281
1282 n->set = bitmap_alloc(size);
1283 if (!n->set) {
1284 closedir(dir);
1285 return -ENOMEM;
1286 }
1287
1288 bitmap_zero(n->set, size);
1289 n->node = idx;
1290 n->size = size;
1291
1292 rewinddir(dir);
1293
1294 for_each_memory(phys, dir) {
1295 set_bit(phys, n->set);
1296 }
1297
1298 closedir(dir);
1299 return 0;
1300}
1301
1302static int memory_node__sort(const void *a, const void *b)
1303{
1304 const struct memory_node *na = a;
1305 const struct memory_node *nb = b;
1306
1307 return na->node - nb->node;
1308}
1309
1310static int build_mem_topology(struct memory_node *nodes, u64 size, u64 *cntp)
1311{
1312 char path[PATH_MAX];
1313 struct dirent *ent;
1314 DIR *dir;
1315 u64 cnt = 0;
1316 int ret = 0;
1317
1318 scnprintf(path, PATH_MAX, "%s/devices/system/node/",
1319 sysfs__mountpoint());
1320
1321 dir = opendir(path);
1322 if (!dir) {
1323 pr_warning("failed: can't open node sysfs data\n");
1324 return -1;
1325 }
1326
1327 while (!ret && (ent = readdir(dir))) {
1328 unsigned int idx;
1329 int r;
1330
1331 if (!strcmp(ent->d_name, ".") ||
1332 !strcmp(ent->d_name, ".."))
1333 continue;
1334
1335 r = sscanf(ent->d_name, "node%u", &idx);
1336 if (r != 1)
1337 continue;
1338
1339 if (WARN_ONCE(cnt >= size,
1340 "failed to write MEM_TOPOLOGY, way too many nodes\n"))
1341 return -1;
1342
1343 ret = memory_node__read(&nodes[cnt++], idx);
1344 }
1345
1346 *cntp = cnt;
1347 closedir(dir);
1348
1349 if (!ret)
1350 qsort(nodes, cnt, sizeof(nodes[0]), memory_node__sort);
1351
1352 return ret;
1353}
1354
1355#define MAX_MEMORY_NODES 2000
1356
1357/*
1358 * The MEM_TOPOLOGY holds physical memory map for every
1359 * node in system. The format of data is as follows:
1360 *
1361 * 0 - version | for future changes
1362 * 8 - block_size_bytes | /sys/devices/system/memory/block_size_bytes
1363 * 16 - count | number of nodes
1364 *
1365 * For each node we store map of physical indexes for
1366 * each node:
1367 *
1368 * 32 - node id | node index
1369 * 40 - size | size of bitmap
1370 * 48 - bitmap | bitmap of memory indexes that belongs to node
1371 */
1372static int write_mem_topology(struct feat_fd *ff __maybe_unused,
1373 struct perf_evlist *evlist __maybe_unused)
1374{
1375 static struct memory_node nodes[MAX_MEMORY_NODES];
1376 u64 bsize, version = 1, i, nr;
1377 int ret;
1378
1379 ret = sysfs__read_xll("devices/system/memory/block_size_bytes",
1380 (unsigned long long *) &bsize);
1381 if (ret)
1382 return ret;
1383
1384 ret = build_mem_topology(&nodes[0], MAX_MEMORY_NODES, &nr);
1385 if (ret)
1386 return ret;
1387
1388 ret = do_write(ff, &version, sizeof(version));
1389 if (ret < 0)
1390 goto out;
1391
1392 ret = do_write(ff, &bsize, sizeof(bsize));
1393 if (ret < 0)
1394 goto out;
1395
1396 ret = do_write(ff, &nr, sizeof(nr));
1397 if (ret < 0)
1398 goto out;
1399
1400 for (i = 0; i < nr; i++) {
1401 struct memory_node *n = &nodes[i];
1402
1403 #define _W(v) \
1404 ret = do_write(ff, &n->v, sizeof(n->v)); \
1405 if (ret < 0) \
1406 goto out;
1407
1408 _W(node)
1409 _W(size)
1410
1411 #undef _W
1412
1413 ret = do_write_bitmap(ff, n->set, n->size);
1414 if (ret < 0)
1415 goto out;
1416 }
1417
1418out:
1419 return ret;
1420}
1421
1199static void print_hostname(struct feat_fd *ff, FILE *fp) 1422static void print_hostname(struct feat_fd *ff, FILE *fp)
1200{ 1423{
1201 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); 1424 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
@@ -1543,6 +1766,35 @@ static void print_sample_time(struct feat_fd *ff, FILE *fp)
1543 fprintf(fp, "# sample duration : %10.3f ms\n", d); 1766 fprintf(fp, "# sample duration : %10.3f ms\n", d);
1544} 1767}
1545 1768
1769static void memory_node__fprintf(struct memory_node *n,
1770 unsigned long long bsize, FILE *fp)
1771{
1772 char buf_map[100], buf_size[50];
1773 unsigned long long size;
1774
1775 size = bsize * bitmap_weight(n->set, n->size);
1776 unit_number__scnprintf(buf_size, 50, size);
1777
1778 bitmap_scnprintf(n->set, n->size, buf_map, 100);
1779 fprintf(fp, "# %3" PRIu64 " [%s]: %s\n", n->node, buf_size, buf_map);
1780}
1781
1782static void print_mem_topology(struct feat_fd *ff, FILE *fp)
1783{
1784 struct memory_node *nodes;
1785 int i, nr;
1786
1787 nodes = ff->ph->env.memory_nodes;
1788 nr = ff->ph->env.nr_memory_nodes;
1789
1790 fprintf(fp, "# memory nodes (nr %d, block size 0x%llx):\n",
1791 nr, ff->ph->env.memory_bsize);
1792
1793 for (i = 0; i < nr; i++) {
1794 memory_node__fprintf(&nodes[i], ff->ph->env.memory_bsize, fp);
1795 }
1796}
1797
1546static int __event_process_build_id(struct build_id_event *bev, 1798static int __event_process_build_id(struct build_id_event *bev,
1547 char *filename, 1799 char *filename,
1548 struct perf_session *session) 1800 struct perf_session *session)
@@ -2205,6 +2457,58 @@ static int process_sample_time(struct feat_fd *ff, void *data __maybe_unused)
2205 return 0; 2457 return 0;
2206} 2458}
2207 2459
2460static int process_mem_topology(struct feat_fd *ff,
2461 void *data __maybe_unused)
2462{
2463 struct memory_node *nodes;
2464 u64 version, i, nr, bsize;
2465 int ret = -1;
2466
2467 if (do_read_u64(ff, &version))
2468 return -1;
2469
2470 if (version != 1)
2471 return -1;
2472
2473 if (do_read_u64(ff, &bsize))
2474 return -1;
2475
2476 if (do_read_u64(ff, &nr))
2477 return -1;
2478
2479 nodes = zalloc(sizeof(*nodes) * nr);
2480 if (!nodes)
2481 return -1;
2482
2483 for (i = 0; i < nr; i++) {
2484 struct memory_node n;
2485
2486 #define _R(v) \
2487 if (do_read_u64(ff, &n.v)) \
2488 goto out; \
2489
2490 _R(node)
2491 _R(size)
2492
2493 #undef _R
2494
2495 if (do_read_bitmap(ff, &n.set, &n.size))
2496 goto out;
2497
2498 nodes[i] = n;
2499 }
2500
2501 ff->ph->env.memory_bsize = bsize;
2502 ff->ph->env.memory_nodes = nodes;
2503 ff->ph->env.nr_memory_nodes = nr;
2504 ret = 0;
2505
2506out:
2507 if (ret)
2508 free(nodes);
2509 return ret;
2510}
2511
2208struct feature_ops { 2512struct feature_ops {
2209 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2513 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2210 void (*print)(struct feat_fd *ff, FILE *fp); 2514 void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2263,6 +2567,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2263 FEAT_OPN(STAT, stat, false), 2567 FEAT_OPN(STAT, stat, false),
2264 FEAT_OPN(CACHE, cache, true), 2568 FEAT_OPN(CACHE, cache, true),
2265 FEAT_OPR(SAMPLE_TIME, sample_time, false), 2569 FEAT_OPR(SAMPLE_TIME, sample_time, false),
2570 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
2266}; 2571};
2267 2572
2268struct header_print_data { 2573struct header_print_data {
@@ -2318,7 +2623,12 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2318 if (ret == -1) 2623 if (ret == -1)
2319 return -1; 2624 return -1;
2320 2625
2321 fprintf(fp, "# captured on: %s", ctime(&st.st_ctime)); 2626 fprintf(fp, "# captured on : %s", ctime(&st.st_ctime));
2627
2628 fprintf(fp, "# header version : %u\n", header->version);
2629 fprintf(fp, "# data offset : %" PRIu64 "\n", header->data_offset);
2630 fprintf(fp, "# data size : %" PRIu64 "\n", header->data_size);
2631 fprintf(fp, "# feat offset : %" PRIu64 "\n", header->feat_offset);
2322 2632
2323 perf_header__process_sections(header, fd, &hd, 2633 perf_header__process_sections(header, fd, &hd,
2324 perf_file_section__fprintf_info); 2634 perf_file_section__fprintf_info);
@@ -3105,8 +3415,17 @@ int perf_event__synthesize_features(struct perf_tool *tool,
3105 return ret; 3415 return ret;
3106 } 3416 }
3107 } 3417 }
3418
3419 /* Send HEADER_LAST_FEATURE mark. */
3420 fe = ff.buf;
3421 fe->feat_id = HEADER_LAST_FEATURE;
3422 fe->header.type = PERF_RECORD_HEADER_FEATURE;
3423 fe->header.size = sizeof(*fe);
3424
3425 ret = process(tool, ff.buf, NULL, NULL);
3426
3108 free(ff.buf); 3427 free(ff.buf);
3109 return 0; 3428 return ret;
3110} 3429}
3111 3430
3112int perf_event__process_feature(struct perf_tool *tool, 3431int perf_event__process_feature(struct perf_tool *tool,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index f28aaaa3a440..90d4577a92dc 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -36,6 +36,7 @@ enum {
36 HEADER_STAT, 36 HEADER_STAT,
37 HEADER_CACHE, 37 HEADER_CACHE,
38 HEADER_SAMPLE_TIME, 38 HEADER_SAMPLE_TIME,
39 HEADER_MEM_TOPOLOGY,
39 HEADER_LAST_FEATURE, 40 HEADER_LAST_FEATURE,
40 HEADER_FEAT_BITS = 256, 41 HEADER_FEAT_BITS = 256,
41}; 42};
@@ -174,4 +175,5 @@ int write_padded(struct feat_fd *fd, const void *bf,
174int get_cpuid(char *buffer, size_t sz); 175int get_cpuid(char *buffer, size_t sz);
175 176
176char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused); 177char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused);
178int strcmp_cpuid_str(const char *s1, const char *s2);
177#endif /* __PERF_HEADER_H */ 179#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index b6140950301e..7d968892ee39 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -536,7 +536,7 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
536 * This mem info was allocated from sample__resolve_mem 536 * This mem info was allocated from sample__resolve_mem
537 * and will not be used anymore. 537 * and will not be used anymore.
538 */ 538 */
539 zfree(&entry->mem_info); 539 mem_info__zput(entry->mem_info);
540 540
541 /* If the map of an existing hist_entry has 541 /* If the map of an existing hist_entry has
542 * become out-of-date due to an exec() or 542 * become out-of-date due to an exec() or
@@ -879,7 +879,7 @@ iter_prepare_cumulative_entry(struct hist_entry_iter *iter,
879 * cumulated only one time to prevent entries more than 100% 879 * cumulated only one time to prevent entries more than 100%
880 * overhead. 880 * overhead.
881 */ 881 */
882 he_cache = malloc(sizeof(*he_cache) * (iter->max_stack + 1)); 882 he_cache = malloc(sizeof(*he_cache) * (callchain_cursor.nr + 1));
883 if (he_cache == NULL) 883 if (he_cache == NULL)
884 return -ENOMEM; 884 return -ENOMEM;
885 885
@@ -1045,8 +1045,6 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
1045 if (err) 1045 if (err)
1046 return err; 1046 return err;
1047 1047
1048 iter->max_stack = max_stack_depth;
1049
1050 err = iter->ops->prepare_entry(iter, al); 1048 err = iter->ops->prepare_entry(iter, al);
1051 if (err) 1049 if (err)
1052 goto out; 1050 goto out;
@@ -1141,7 +1139,7 @@ void hist_entry__delete(struct hist_entry *he)
1141 if (he->mem_info) { 1139 if (he->mem_info) {
1142 map__zput(he->mem_info->iaddr.map); 1140 map__zput(he->mem_info->iaddr.map);
1143 map__zput(he->mem_info->daddr.map); 1141 map__zput(he->mem_info->daddr.map);
1144 zfree(&he->mem_info); 1142 mem_info__zput(he->mem_info);
1145 } 1143 }
1146 1144
1147 zfree(&he->stat_acc); 1145 zfree(&he->stat_acc);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 02721b579746..e869cad4d89f 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -107,7 +107,6 @@ struct hist_entry_iter {
107 int curr; 107 int curr;
108 108
109 bool hide_unresolved; 109 bool hide_unresolved;
110 int max_stack;
111 110
112 struct perf_evsel *evsel; 111 struct perf_evsel *evsel;
113 struct perf_sample *sample; 112 struct perf_sample *sample;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index aa1593ce551d..f9157aed1289 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -1378,6 +1378,7 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
1378 intel_pt_clear_tx_flags(decoder); 1378 intel_pt_clear_tx_flags(decoder);
1379 decoder->have_tma = false; 1379 decoder->have_tma = false;
1380 decoder->cbr = 0; 1380 decoder->cbr = 0;
1381 decoder->timestamp_insn_cnt = 0;
1381 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; 1382 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
1382 decoder->overflow = true; 1383 decoder->overflow = true;
1383 return -EOVERFLOW; 1384 return -EOVERFLOW;
@@ -1616,6 +1617,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1616 case INTEL_PT_PWRX: 1617 case INTEL_PT_PWRX:
1617 intel_pt_log("ERROR: Missing TIP after FUP\n"); 1618 intel_pt_log("ERROR: Missing TIP after FUP\n");
1618 decoder->pkt_state = INTEL_PT_STATE_ERR3; 1619 decoder->pkt_state = INTEL_PT_STATE_ERR3;
1620 decoder->pkt_step = 0;
1619 return -ENOENT; 1621 return -ENOENT;
1620 1622
1621 case INTEL_PT_OVF: 1623 case INTEL_PT_OVF:
@@ -2390,14 +2392,6 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
2390 return &decoder->state; 2392 return &decoder->state;
2391} 2393}
2392 2394
2393static bool intel_pt_at_psb(unsigned char *buf, size_t len)
2394{
2395 if (len < INTEL_PT_PSB_LEN)
2396 return false;
2397 return memmem(buf, INTEL_PT_PSB_LEN, INTEL_PT_PSB_STR,
2398 INTEL_PT_PSB_LEN);
2399}
2400
2401/** 2395/**
2402 * intel_pt_next_psb - move buffer pointer to the start of the next PSB packet. 2396 * intel_pt_next_psb - move buffer pointer to the start of the next PSB packet.
2403 * @buf: pointer to buffer pointer 2397 * @buf: pointer to buffer pointer
@@ -2486,6 +2480,7 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
2486 * @buf: buffer 2480 * @buf: buffer
2487 * @len: size of buffer 2481 * @len: size of buffer
2488 * @tsc: TSC value returned 2482 * @tsc: TSC value returned
2483 * @rem: returns remaining size when TSC is found
2489 * 2484 *
2490 * Find a TSC packet in @buf and return the TSC value. This function assumes 2485 * Find a TSC packet in @buf and return the TSC value. This function assumes
2491 * that @buf starts at a PSB and that PSB+ will contain TSC and so stops if a 2486 * that @buf starts at a PSB and that PSB+ will contain TSC and so stops if a
@@ -2493,7 +2488,8 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
2493 * 2488 *
2494 * Return: %true if TSC is found, false otherwise. 2489 * Return: %true if TSC is found, false otherwise.
2495 */ 2490 */
2496static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc) 2491static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
2492 size_t *rem)
2497{ 2493{
2498 struct intel_pt_pkt packet; 2494 struct intel_pt_pkt packet;
2499 int ret; 2495 int ret;
@@ -2504,6 +2500,7 @@ static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc)
2504 return false; 2500 return false;
2505 if (packet.type == INTEL_PT_TSC) { 2501 if (packet.type == INTEL_PT_TSC) {
2506 *tsc = packet.payload; 2502 *tsc = packet.payload;
2503 *rem = len;
2507 return true; 2504 return true;
2508 } 2505 }
2509 if (packet.type == INTEL_PT_PSBEND) 2506 if (packet.type == INTEL_PT_PSBEND)
@@ -2554,6 +2551,8 @@ static int intel_pt_tsc_cmp(uint64_t tsc1, uint64_t tsc2)
2554 * @len_a: size of first buffer 2551 * @len_a: size of first buffer
2555 * @buf_b: second buffer 2552 * @buf_b: second buffer
2556 * @len_b: size of second buffer 2553 * @len_b: size of second buffer
2554 * @consecutive: returns true if there is data in buf_b that is consecutive
2555 * to buf_a
2557 * 2556 *
2558 * If the trace contains TSC we can look at the last TSC of @buf_a and the 2557 * If the trace contains TSC we can look at the last TSC of @buf_a and the
2559 * first TSC of @buf_b in order to determine if the buffers overlap, and then 2558 * first TSC of @buf_b in order to determine if the buffers overlap, and then
@@ -2566,33 +2565,41 @@ static int intel_pt_tsc_cmp(uint64_t tsc1, uint64_t tsc2)
2566static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a, 2565static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2567 size_t len_a, 2566 size_t len_a,
2568 unsigned char *buf_b, 2567 unsigned char *buf_b,
2569 size_t len_b) 2568 size_t len_b, bool *consecutive)
2570{ 2569{
2571 uint64_t tsc_a, tsc_b; 2570 uint64_t tsc_a, tsc_b;
2572 unsigned char *p; 2571 unsigned char *p;
2573 size_t len; 2572 size_t len, rem_a, rem_b;
2574 2573
2575 p = intel_pt_last_psb(buf_a, len_a); 2574 p = intel_pt_last_psb(buf_a, len_a);
2576 if (!p) 2575 if (!p)
2577 return buf_b; /* No PSB in buf_a => no overlap */ 2576 return buf_b; /* No PSB in buf_a => no overlap */
2578 2577
2579 len = len_a - (p - buf_a); 2578 len = len_a - (p - buf_a);
2580 if (!intel_pt_next_tsc(p, len, &tsc_a)) { 2579 if (!intel_pt_next_tsc(p, len, &tsc_a, &rem_a)) {
2581 /* The last PSB+ in buf_a is incomplete, so go back one more */ 2580 /* The last PSB+ in buf_a is incomplete, so go back one more */
2582 len_a -= len; 2581 len_a -= len;
2583 p = intel_pt_last_psb(buf_a, len_a); 2582 p = intel_pt_last_psb(buf_a, len_a);
2584 if (!p) 2583 if (!p)
2585 return buf_b; /* No full PSB+ => assume no overlap */ 2584 return buf_b; /* No full PSB+ => assume no overlap */
2586 len = len_a - (p - buf_a); 2585 len = len_a - (p - buf_a);
2587 if (!intel_pt_next_tsc(p, len, &tsc_a)) 2586 if (!intel_pt_next_tsc(p, len, &tsc_a, &rem_a))
2588 return buf_b; /* No TSC in buf_a => assume no overlap */ 2587 return buf_b; /* No TSC in buf_a => assume no overlap */
2589 } 2588 }
2590 2589
2591 while (1) { 2590 while (1) {
2592 /* Ignore PSB+ with no TSC */ 2591 /* Ignore PSB+ with no TSC */
2593 if (intel_pt_next_tsc(buf_b, len_b, &tsc_b) && 2592 if (intel_pt_next_tsc(buf_b, len_b, &tsc_b, &rem_b)) {
2594 intel_pt_tsc_cmp(tsc_a, tsc_b) < 0) 2593 int cmp = intel_pt_tsc_cmp(tsc_a, tsc_b);
2595 return buf_b; /* tsc_a < tsc_b => no overlap */ 2594
2595 /* Same TSC, so buffers are consecutive */
2596 if (!cmp && rem_b >= rem_a) {
2597 *consecutive = true;
2598 return buf_b + len_b - (rem_b - rem_a);
2599 }
2600 if (cmp < 0)
2601 return buf_b; /* tsc_a < tsc_b => no overlap */
2602 }
2596 2603
2597 if (!intel_pt_step_psb(&buf_b, &len_b)) 2604 if (!intel_pt_step_psb(&buf_b, &len_b))
2598 return buf_b + len_b; /* No PSB in buf_b => no data */ 2605 return buf_b + len_b; /* No PSB in buf_b => no data */
@@ -2606,6 +2613,8 @@ static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2606 * @buf_b: second buffer 2613 * @buf_b: second buffer
2607 * @len_b: size of second buffer 2614 * @len_b: size of second buffer
2608 * @have_tsc: can use TSC packets to detect overlap 2615 * @have_tsc: can use TSC packets to detect overlap
2616 * @consecutive: returns true if there is data in buf_b that is consecutive
2617 * to buf_a
2609 * 2618 *
2610 * When trace samples or snapshots are recorded there is the possibility that 2619 * When trace samples or snapshots are recorded there is the possibility that
2611 * the data overlaps. Note that, for the purposes of decoding, data is only 2620 * the data overlaps. Note that, for the purposes of decoding, data is only
@@ -2616,7 +2625,7 @@ static unsigned char *intel_pt_find_overlap_tsc(unsigned char *buf_a,
2616 */ 2625 */
2617unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a, 2626unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2618 unsigned char *buf_b, size_t len_b, 2627 unsigned char *buf_b, size_t len_b,
2619 bool have_tsc) 2628 bool have_tsc, bool *consecutive)
2620{ 2629{
2621 unsigned char *found; 2630 unsigned char *found;
2622 2631
@@ -2628,7 +2637,8 @@ unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2628 return buf_b; /* No overlap */ 2637 return buf_b; /* No overlap */
2629 2638
2630 if (have_tsc) { 2639 if (have_tsc) {
2631 found = intel_pt_find_overlap_tsc(buf_a, len_a, buf_b, len_b); 2640 found = intel_pt_find_overlap_tsc(buf_a, len_a, buf_b, len_b,
2641 consecutive);
2632 if (found) 2642 if (found)
2633 return found; 2643 return found;
2634 } 2644 }
@@ -2643,28 +2653,16 @@ unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
2643 } 2653 }
2644 2654
2645 /* Now len_b >= len_a */ 2655 /* Now len_b >= len_a */
2646 if (len_b > len_a) {
2647 /* The leftover buffer 'b' must start at a PSB */
2648 while (!intel_pt_at_psb(buf_b + len_a, len_b - len_a)) {
2649 if (!intel_pt_step_psb(&buf_a, &len_a))
2650 return buf_b; /* No overlap */
2651 }
2652 }
2653
2654 while (1) { 2656 while (1) {
2655 /* Potential overlap so check the bytes */ 2657 /* Potential overlap so check the bytes */
2656 found = memmem(buf_a, len_a, buf_b, len_a); 2658 found = memmem(buf_a, len_a, buf_b, len_a);
2657 if (found) 2659 if (found) {
2660 *consecutive = true;
2658 return buf_b + len_a; 2661 return buf_b + len_a;
2662 }
2659 2663
2660 /* Try again at next PSB in buffer 'a' */ 2664 /* Try again at next PSB in buffer 'a' */
2661 if (!intel_pt_step_psb(&buf_a, &len_a)) 2665 if (!intel_pt_step_psb(&buf_a, &len_a))
2662 return buf_b; /* No overlap */ 2666 return buf_b; /* No overlap */
2663
2664 /* The leftover buffer 'b' must start at a PSB */
2665 while (!intel_pt_at_psb(buf_b + len_a, len_b - len_a)) {
2666 if (!intel_pt_step_psb(&buf_a, &len_a))
2667 return buf_b; /* No overlap */
2668 }
2669 } 2667 }
2670} 2668}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 921b22e8ca0e..fc1752d50019 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -117,7 +117,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder);
117 117
118unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a, 118unsigned char *intel_pt_find_overlap(unsigned char *buf_a, size_t len_a,
119 unsigned char *buf_b, size_t len_b, 119 unsigned char *buf_b, size_t len_b,
120 bool have_tsc); 120 bool have_tsc, bool *consecutive);
121 121
122int intel_pt__strerror(int code, char *buf, size_t buflen); 122int intel_pt__strerror(int code, char *buf, size_t buflen);
123 123
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 3773d9c54f45..0effaff57020 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -132,6 +132,7 @@ struct intel_pt_queue {
132 struct intel_pt *pt; 132 struct intel_pt *pt;
133 unsigned int queue_nr; 133 unsigned int queue_nr;
134 struct auxtrace_buffer *buffer; 134 struct auxtrace_buffer *buffer;
135 struct auxtrace_buffer *old_buffer;
135 void *decoder; 136 void *decoder;
136 const struct intel_pt_state *state; 137 const struct intel_pt_state *state;
137 struct ip_callchain *chain; 138 struct ip_callchain *chain;
@@ -143,6 +144,7 @@ struct intel_pt_queue {
143 bool stop; 144 bool stop;
144 bool step_through_buffers; 145 bool step_through_buffers;
145 bool use_buffer_pid_tid; 146 bool use_buffer_pid_tid;
147 bool sync_switch;
146 pid_t pid, tid; 148 pid_t pid, tid;
147 int cpu; 149 int cpu;
148 int switch_state; 150 int switch_state;
@@ -207,49 +209,28 @@ static void intel_pt_dump_event(struct intel_pt *pt, unsigned char *buf,
207static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a, 209static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a,
208 struct auxtrace_buffer *b) 210 struct auxtrace_buffer *b)
209{ 211{
212 bool consecutive = false;
210 void *start; 213 void *start;
211 214
212 start = intel_pt_find_overlap(a->data, a->size, b->data, b->size, 215 start = intel_pt_find_overlap(a->data, a->size, b->data, b->size,
213 pt->have_tsc); 216 pt->have_tsc, &consecutive);
214 if (!start) 217 if (!start)
215 return -EINVAL; 218 return -EINVAL;
216 b->use_size = b->data + b->size - start; 219 b->use_size = b->data + b->size - start;
217 b->use_data = start; 220 b->use_data = start;
221 if (b->use_size && consecutive)
222 b->consecutive = true;
218 return 0; 223 return 0;
219} 224}
220 225
221static void intel_pt_use_buffer_pid_tid(struct intel_pt_queue *ptq,
222 struct auxtrace_queue *queue,
223 struct auxtrace_buffer *buffer)
224{
225 if (queue->cpu == -1 && buffer->cpu != -1)
226 ptq->cpu = buffer->cpu;
227
228 ptq->pid = buffer->pid;
229 ptq->tid = buffer->tid;
230
231 intel_pt_log("queue %u cpu %d pid %d tid %d\n",
232 ptq->queue_nr, ptq->cpu, ptq->pid, ptq->tid);
233
234 thread__zput(ptq->thread);
235
236 if (ptq->tid != -1) {
237 if (ptq->pid != -1)
238 ptq->thread = machine__findnew_thread(ptq->pt->machine,
239 ptq->pid,
240 ptq->tid);
241 else
242 ptq->thread = machine__find_thread(ptq->pt->machine, -1,
243 ptq->tid);
244 }
245}
246
247/* This function assumes data is processed sequentially only */ 226/* This function assumes data is processed sequentially only */
248static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data) 227static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
249{ 228{
250 struct intel_pt_queue *ptq = data; 229 struct intel_pt_queue *ptq = data;
251 struct auxtrace_buffer *buffer = ptq->buffer, *old_buffer = buffer; 230 struct auxtrace_buffer *buffer = ptq->buffer;
231 struct auxtrace_buffer *old_buffer = ptq->old_buffer;
252 struct auxtrace_queue *queue; 232 struct auxtrace_queue *queue;
233 bool might_overlap;
253 234
254 if (ptq->stop) { 235 if (ptq->stop) {
255 b->len = 0; 236 b->len = 0;
@@ -257,7 +238,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
257 } 238 }
258 239
259 queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; 240 queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
260next: 241
261 buffer = auxtrace_buffer__next(queue, buffer); 242 buffer = auxtrace_buffer__next(queue, buffer);
262 if (!buffer) { 243 if (!buffer) {
263 if (old_buffer) 244 if (old_buffer)
@@ -276,7 +257,8 @@ next:
276 return -ENOMEM; 257 return -ENOMEM;
277 } 258 }
278 259
279 if (ptq->pt->snapshot_mode && !buffer->consecutive && old_buffer && 260 might_overlap = ptq->pt->snapshot_mode || ptq->pt->sampling_mode;
261 if (might_overlap && !buffer->consecutive && old_buffer &&
280 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer)) 262 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
281 return -ENOMEM; 263 return -ENOMEM;
282 264
@@ -289,33 +271,24 @@ next:
289 } 271 }
290 b->ref_timestamp = buffer->reference; 272 b->ref_timestamp = buffer->reference;
291 273
292 /* 274 if (!old_buffer || (might_overlap && !buffer->consecutive)) {
293 * If in snapshot mode and the buffer has no usable data, get next
294 * buffer and again check overlap against old_buffer.
295 */
296 if (ptq->pt->snapshot_mode && !b->len)
297 goto next;
298
299 if (old_buffer)
300 auxtrace_buffer__drop_data(old_buffer);
301
302 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
303 !buffer->consecutive)) {
304 b->consecutive = false; 275 b->consecutive = false;
305 b->trace_nr = buffer->buffer_nr + 1; 276 b->trace_nr = buffer->buffer_nr + 1;
306 } else { 277 } else {
307 b->consecutive = true; 278 b->consecutive = true;
308 } 279 }
309 280
310 if (ptq->use_buffer_pid_tid && (ptq->pid != buffer->pid ||
311 ptq->tid != buffer->tid))
312 intel_pt_use_buffer_pid_tid(ptq, queue, buffer);
313
314 if (ptq->step_through_buffers) 281 if (ptq->step_through_buffers)
315 ptq->stop = true; 282 ptq->stop = true;
316 283
317 if (!b->len) 284 if (b->len) {
285 if (old_buffer)
286 auxtrace_buffer__drop_data(old_buffer);
287 ptq->old_buffer = buffer;
288 } else {
289 auxtrace_buffer__drop_data(buffer);
318 return intel_pt_get_trace(b, data); 290 return intel_pt_get_trace(b, data);
291 }
319 292
320 return 0; 293 return 0;
321} 294}
@@ -954,16 +927,15 @@ static int intel_pt_setup_queue(struct intel_pt *pt,
954 ptq->cpu = queue->cpu; 927 ptq->cpu = queue->cpu;
955 ptq->tid = queue->tid; 928 ptq->tid = queue->tid;
956 929
957 if (pt->sampling_mode) { 930 if (pt->sampling_mode && !pt->snapshot_mode &&
958 if (pt->timeless_decoding) 931 pt->timeless_decoding)
959 ptq->step_through_buffers = true; 932 ptq->step_through_buffers = true;
960 if (pt->timeless_decoding || !pt->have_sched_switch) 933
961 ptq->use_buffer_pid_tid = true; 934 ptq->sync_switch = pt->sync_switch;
962 }
963 } 935 }
964 936
965 if (!ptq->on_heap && 937 if (!ptq->on_heap &&
966 (!pt->sync_switch || 938 (!ptq->sync_switch ||
967 ptq->switch_state != INTEL_PT_SS_EXPECTING_SWITCH_EVENT)) { 939 ptq->switch_state != INTEL_PT_SS_EXPECTING_SWITCH_EVENT)) {
968 const struct intel_pt_state *state; 940 const struct intel_pt_state *state;
969 int ret; 941 int ret;
@@ -1546,7 +1518,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1546 if (pt->synth_opts.last_branch) 1518 if (pt->synth_opts.last_branch)
1547 intel_pt_update_last_branch_rb(ptq); 1519 intel_pt_update_last_branch_rb(ptq);
1548 1520
1549 if (!pt->sync_switch) 1521 if (!ptq->sync_switch)
1550 return 0; 1522 return 0;
1551 1523
1552 if (intel_pt_is_switch_ip(ptq, state->to_ip)) { 1524 if (intel_pt_is_switch_ip(ptq, state->to_ip)) {
@@ -1627,6 +1599,21 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
1627 return switch_ip; 1599 return switch_ip;
1628} 1600}
1629 1601
1602static void intel_pt_enable_sync_switch(struct intel_pt *pt)
1603{
1604 unsigned int i;
1605
1606 pt->sync_switch = true;
1607
1608 for (i = 0; i < pt->queues.nr_queues; i++) {
1609 struct auxtrace_queue *queue = &pt->queues.queue_array[i];
1610 struct intel_pt_queue *ptq = queue->priv;
1611
1612 if (ptq)
1613 ptq->sync_switch = true;
1614 }
1615}
1616
1630static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) 1617static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1631{ 1618{
1632 const struct intel_pt_state *state = ptq->state; 1619 const struct intel_pt_state *state = ptq->state;
@@ -1643,7 +1630,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1643 if (pt->switch_ip) { 1630 if (pt->switch_ip) {
1644 intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n", 1631 intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n",
1645 pt->switch_ip, pt->ptss_ip); 1632 pt->switch_ip, pt->ptss_ip);
1646 pt->sync_switch = true; 1633 intel_pt_enable_sync_switch(pt);
1647 } 1634 }
1648 } 1635 }
1649 } 1636 }
@@ -1659,9 +1646,9 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1659 if (state->err) { 1646 if (state->err) {
1660 if (state->err == INTEL_PT_ERR_NODATA) 1647 if (state->err == INTEL_PT_ERR_NODATA)
1661 return 1; 1648 return 1;
1662 if (pt->sync_switch && 1649 if (ptq->sync_switch &&
1663 state->from_ip >= pt->kernel_start) { 1650 state->from_ip >= pt->kernel_start) {
1664 pt->sync_switch = false; 1651 ptq->sync_switch = false;
1665 intel_pt_next_tid(pt, ptq); 1652 intel_pt_next_tid(pt, ptq);
1666 } 1653 }
1667 if (pt->synth_opts.errors) { 1654 if (pt->synth_opts.errors) {
@@ -1687,7 +1674,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
1687 state->timestamp, state->est_timestamp); 1674 state->timestamp, state->est_timestamp);
1688 ptq->timestamp = state->est_timestamp; 1675 ptq->timestamp = state->est_timestamp;
1689 /* Use estimated TSC in unknown switch state */ 1676 /* Use estimated TSC in unknown switch state */
1690 } else if (pt->sync_switch && 1677 } else if (ptq->sync_switch &&
1691 ptq->switch_state == INTEL_PT_SS_UNKNOWN && 1678 ptq->switch_state == INTEL_PT_SS_UNKNOWN &&
1692 intel_pt_is_switch_ip(ptq, state->to_ip) && 1679 intel_pt_is_switch_ip(ptq, state->to_ip) &&
1693 ptq->next_tid == -1) { 1680 ptq->next_tid == -1) {
@@ -1834,7 +1821,7 @@ static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,
1834 return 1; 1821 return 1;
1835 1822
1836 ptq = intel_pt_cpu_to_ptq(pt, cpu); 1823 ptq = intel_pt_cpu_to_ptq(pt, cpu);
1837 if (!ptq) 1824 if (!ptq || !ptq->sync_switch)
1838 return 1; 1825 return 1;
1839 1826
1840 switch (ptq->switch_state) { 1827 switch (ptq->switch_state) {
@@ -2075,9 +2062,6 @@ static int intel_pt_process_auxtrace_event(struct perf_session *session,
2075 struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt, 2062 struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
2076 auxtrace); 2063 auxtrace);
2077 2064
2078 if (pt->sampling_mode)
2079 return 0;
2080
2081 if (!pt->data_queued) { 2065 if (!pt->data_queued) {
2082 struct auxtrace_buffer *buffer; 2066 struct auxtrace_buffer *buffer;
2083 off_t data_offset; 2067 off_t data_offset;
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 4952b429caa7..1cca0a2fa641 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -433,6 +433,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
433 char serr[STRERR_BUFSIZE]; 433 char serr[STRERR_BUFSIZE];
434 char *kbuild_dir = NULL, *kbuild_include_opts = NULL; 434 char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
435 const char *template = llvm_param.clang_bpf_cmd_template; 435 const char *template = llvm_param.clang_bpf_cmd_template;
436 char *command_echo, *command_out;
436 437
437 if (path[0] != '-' && realpath(path, abspath) == NULL) { 438 if (path[0] != '-' && realpath(path, abspath) == NULL) {
438 err = errno; 439 err = errno;
@@ -487,6 +488,16 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
487 (path[0] == '-') ? path : abspath); 488 (path[0] == '-') ? path : abspath);
488 489
489 pr_debug("llvm compiling command template: %s\n", template); 490 pr_debug("llvm compiling command template: %s\n", template);
491
492 if (asprintf(&command_echo, "echo -n \"%s\"", template) < 0)
493 goto errout;
494
495 err = read_from_pipe(command_echo, (void **) &command_out, NULL);
496 if (err)
497 goto errout;
498
499 pr_debug("llvm compiling command : %s\n", command_out);
500
490 err = read_from_pipe(template, &obj_buf, &obj_buf_sz); 501 err = read_from_pipe(template, &obj_buf, &obj_buf_sz);
491 if (err) { 502 if (err) {
492 pr_err("ERROR:\tunable to compile %s\n", path); 503 pr_err("ERROR:\tunable to compile %s\n", path);
@@ -497,6 +508,8 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
497 goto errout; 508 goto errout;
498 } 509 }
499 510
511 free(command_echo);
512 free(command_out);
500 free(kbuild_dir); 513 free(kbuild_dir);
501 free(kbuild_include_opts); 514 free(kbuild_include_opts);
502 515
@@ -509,6 +522,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
509 *p_obj_buf_sz = obj_buf_sz; 522 *p_obj_buf_sz = obj_buf_sz;
510 return 0; 523 return 0;
511errout: 524errout:
525 free(command_echo);
512 free(kbuild_dir); 526 free(kbuild_dir);
513 free(kbuild_include_opts); 527 free(kbuild_include_opts);
514 free(obj_buf); 528 free(obj_buf);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b05a67464c03..2eca8478e24f 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -48,8 +48,23 @@ static void machine__threads_init(struct machine *machine)
48 } 48 }
49} 49}
50 50
51static int machine__set_mmap_name(struct machine *machine)
52{
53 if (machine__is_host(machine))
54 machine->mmap_name = strdup("[kernel.kallsyms]");
55 else if (machine__is_default_guest(machine))
56 machine->mmap_name = strdup("[guest.kernel.kallsyms]");
57 else if (asprintf(&machine->mmap_name, "[guest.kernel.kallsyms.%d]",
58 machine->pid) < 0)
59 machine->mmap_name = NULL;
60
61 return machine->mmap_name ? 0 : -ENOMEM;
62}
63
51int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 64int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
52{ 65{
66 int err = -ENOMEM;
67
53 memset(machine, 0, sizeof(*machine)); 68 memset(machine, 0, sizeof(*machine));
54 map_groups__init(&machine->kmaps, machine); 69 map_groups__init(&machine->kmaps, machine);
55 RB_CLEAR_NODE(&machine->rb_node); 70 RB_CLEAR_NODE(&machine->rb_node);
@@ -73,13 +88,16 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
73 if (machine->root_dir == NULL) 88 if (machine->root_dir == NULL)
74 return -ENOMEM; 89 return -ENOMEM;
75 90
91 if (machine__set_mmap_name(machine))
92 goto out;
93
76 if (pid != HOST_KERNEL_ID) { 94 if (pid != HOST_KERNEL_ID) {
77 struct thread *thread = machine__findnew_thread(machine, -1, 95 struct thread *thread = machine__findnew_thread(machine, -1,
78 pid); 96 pid);
79 char comm[64]; 97 char comm[64];
80 98
81 if (thread == NULL) 99 if (thread == NULL)
82 return -ENOMEM; 100 goto out;
83 101
84 snprintf(comm, sizeof(comm), "[guest/%d]", pid); 102 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
85 thread__set_comm(thread, comm, 0); 103 thread__set_comm(thread, comm, 0);
@@ -87,7 +105,13 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
87 } 105 }
88 106
89 machine->current_tid = NULL; 107 machine->current_tid = NULL;
108 err = 0;
90 109
110out:
111 if (err) {
112 zfree(&machine->root_dir);
113 zfree(&machine->mmap_name);
114 }
91 return 0; 115 return 0;
92} 116}
93 117
@@ -119,7 +143,7 @@ struct machine *machine__new_kallsyms(void)
119 * ask for not using the kcore parsing code, once this one is fixed 143 * ask for not using the kcore parsing code, once this one is fixed
120 * to create a map per module. 144 * to create a map per module.
121 */ 145 */
122 if (machine && __machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION, true) <= 0) { 146 if (machine && machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION) <= 0) {
123 machine__delete(machine); 147 machine__delete(machine);
124 machine = NULL; 148 machine = NULL;
125 } 149 }
@@ -180,6 +204,7 @@ void machine__exit(struct machine *machine)
180 dsos__exit(&machine->dsos); 204 dsos__exit(&machine->dsos);
181 machine__exit_vdso(machine); 205 machine__exit_vdso(machine);
182 zfree(&machine->root_dir); 206 zfree(&machine->root_dir);
207 zfree(&machine->mmap_name);
183 zfree(&machine->current_tid); 208 zfree(&machine->current_tid);
184 209
185 for (i = 0; i < THREADS__TABLE_SIZE; i++) { 210 for (i = 0; i < THREADS__TABLE_SIZE; i++) {
@@ -322,20 +347,6 @@ void machines__process_guests(struct machines *machines,
322 } 347 }
323} 348}
324 349
325char *machine__mmap_name(struct machine *machine, char *bf, size_t size)
326{
327 if (machine__is_host(machine))
328 snprintf(bf, size, "[%s]", "kernel.kallsyms");
329 else if (machine__is_default_guest(machine))
330 snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
331 else {
332 snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms",
333 machine->pid);
334 }
335
336 return bf;
337}
338
339void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size) 350void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
340{ 351{
341 struct rb_node *node; 352 struct rb_node *node;
@@ -771,24 +782,18 @@ size_t machine__fprintf(struct machine *machine, FILE *fp)
771 782
772static struct dso *machine__get_kernel(struct machine *machine) 783static struct dso *machine__get_kernel(struct machine *machine)
773{ 784{
774 const char *vmlinux_name = NULL; 785 const char *vmlinux_name = machine->mmap_name;
775 struct dso *kernel; 786 struct dso *kernel;
776 787
777 if (machine__is_host(machine)) { 788 if (machine__is_host(machine)) {
778 vmlinux_name = symbol_conf.vmlinux_name; 789 if (symbol_conf.vmlinux_name)
779 if (!vmlinux_name) 790 vmlinux_name = symbol_conf.vmlinux_name;
780 vmlinux_name = DSO__NAME_KALLSYMS;
781 791
782 kernel = machine__findnew_kernel(machine, vmlinux_name, 792 kernel = machine__findnew_kernel(machine, vmlinux_name,
783 "[kernel]", DSO_TYPE_KERNEL); 793 "[kernel]", DSO_TYPE_KERNEL);
784 } else { 794 } else {
785 char bf[PATH_MAX]; 795 if (symbol_conf.default_guest_vmlinux_name)
786
787 if (machine__is_default_guest(machine))
788 vmlinux_name = symbol_conf.default_guest_vmlinux_name; 796 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
789 if (!vmlinux_name)
790 vmlinux_name = machine__mmap_name(machine, bf,
791 sizeof(bf));
792 797
793 kernel = machine__findnew_kernel(machine, vmlinux_name, 798 kernel = machine__findnew_kernel(machine, vmlinux_name,
794 "[guest.kernel]", 799 "[guest.kernel]",
@@ -849,13 +854,10 @@ static int machine__get_running_kernel_start(struct machine *machine,
849 return 0; 854 return 0;
850} 855}
851 856
852int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 857static int
858__machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
853{ 859{
854 int type; 860 int type;
855 u64 start = 0;
856
857 if (machine__get_running_kernel_start(machine, NULL, &start))
858 return -1;
859 861
860 /* In case of renewal the kernel map, destroy previous one */ 862 /* In case of renewal the kernel map, destroy previous one */
861 machine__destroy_kernel_maps(machine); 863 machine__destroy_kernel_maps(machine);
@@ -864,7 +866,7 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
864 struct kmap *kmap; 866 struct kmap *kmap;
865 struct map *map; 867 struct map *map;
866 868
867 machine->vmlinux_maps[type] = map__new2(start, kernel, type); 869 machine->vmlinux_maps[type] = map__new2(0, kernel, type);
868 if (machine->vmlinux_maps[type] == NULL) 870 if (machine->vmlinux_maps[type] == NULL)
869 return -1; 871 return -1;
870 872
@@ -987,11 +989,11 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
987 return machine__create_kernel_maps(machine); 989 return machine__create_kernel_maps(machine);
988} 990}
989 991
990int __machine__load_kallsyms(struct machine *machine, const char *filename, 992int machine__load_kallsyms(struct machine *machine, const char *filename,
991 enum map_type type, bool no_kcore) 993 enum map_type type)
992{ 994{
993 struct map *map = machine__kernel_map(machine); 995 struct map *map = machine__kernel_map(machine);
994 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore); 996 int ret = __dso__load_kallsyms(map->dso, filename, map, true);
995 997
996 if (ret > 0) { 998 if (ret > 0) {
997 dso__set_loaded(map->dso, type); 999 dso__set_loaded(map->dso, type);
@@ -1006,12 +1008,6 @@ int __machine__load_kallsyms(struct machine *machine, const char *filename,
1006 return ret; 1008 return ret;
1007} 1009}
1008 1010
1009int machine__load_kallsyms(struct machine *machine, const char *filename,
1010 enum map_type type)
1011{
1012 return __machine__load_kallsyms(machine, filename, type, false);
1013}
1014
1015int machine__load_vmlinux_path(struct machine *machine, enum map_type type) 1011int machine__load_vmlinux_path(struct machine *machine, enum map_type type)
1016{ 1012{
1017 struct map *map = machine__kernel_map(machine); 1013 struct map *map = machine__kernel_map(machine);
@@ -1215,6 +1211,24 @@ static int machine__create_modules(struct machine *machine)
1215 return 0; 1211 return 0;
1216} 1212}
1217 1213
1214static void machine__set_kernel_mmap(struct machine *machine,
1215 u64 start, u64 end)
1216{
1217 int i;
1218
1219 for (i = 0; i < MAP__NR_TYPES; i++) {
1220 machine->vmlinux_maps[i]->start = start;
1221 machine->vmlinux_maps[i]->end = end;
1222
1223 /*
1224 * Be a bit paranoid here, some perf.data file came with
1225 * a zero sized synthesized MMAP event for the kernel.
1226 */
1227 if (start == 0 && end == 0)
1228 machine->vmlinux_maps[i]->end = ~0ULL;
1229 }
1230}
1231
1218int machine__create_kernel_maps(struct machine *machine) 1232int machine__create_kernel_maps(struct machine *machine)
1219{ 1233{
1220 struct dso *kernel = machine__get_kernel(machine); 1234 struct dso *kernel = machine__get_kernel(machine);
@@ -1239,40 +1253,22 @@ int machine__create_kernel_maps(struct machine *machine)
1239 "continuing anyway...\n", machine->pid); 1253 "continuing anyway...\n", machine->pid);
1240 } 1254 }
1241 1255
1242 /*
1243 * Now that we have all the maps created, just set the ->end of them:
1244 */
1245 map_groups__fixup_end(&machine->kmaps);
1246
1247 if (!machine__get_running_kernel_start(machine, &name, &addr)) { 1256 if (!machine__get_running_kernel_start(machine, &name, &addr)) {
1248 if (name && 1257 if (name &&
1249 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { 1258 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
1250 machine__destroy_kernel_maps(machine); 1259 machine__destroy_kernel_maps(machine);
1251 return -1; 1260 return -1;
1252 } 1261 }
1262 machine__set_kernel_mmap(machine, addr, 0);
1253 } 1263 }
1254 1264
1265 /*
1266 * Now that we have all the maps created, just set the ->end of them:
1267 */
1268 map_groups__fixup_end(&machine->kmaps);
1255 return 0; 1269 return 0;
1256} 1270}
1257 1271
1258static void machine__set_kernel_mmap_len(struct machine *machine,
1259 union perf_event *event)
1260{
1261 int i;
1262
1263 for (i = 0; i < MAP__NR_TYPES; i++) {
1264 machine->vmlinux_maps[i]->start = event->mmap.start;
1265 machine->vmlinux_maps[i]->end = (event->mmap.start +
1266 event->mmap.len);
1267 /*
1268 * Be a bit paranoid here, some perf.data file came with
1269 * a zero sized synthesized MMAP event for the kernel.
1270 */
1271 if (machine->vmlinux_maps[i]->end == 0)
1272 machine->vmlinux_maps[i]->end = ~0ULL;
1273 }
1274}
1275
1276static bool machine__uses_kcore(struct machine *machine) 1272static bool machine__uses_kcore(struct machine *machine)
1277{ 1273{
1278 struct dso *dso; 1274 struct dso *dso;
@@ -1289,7 +1285,6 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1289 union perf_event *event) 1285 union perf_event *event)
1290{ 1286{
1291 struct map *map; 1287 struct map *map;
1292 char kmmap_prefix[PATH_MAX];
1293 enum dso_kernel_type kernel_type; 1288 enum dso_kernel_type kernel_type;
1294 bool is_kernel_mmap; 1289 bool is_kernel_mmap;
1295 1290
@@ -1297,15 +1292,14 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1297 if (machine__uses_kcore(machine)) 1292 if (machine__uses_kcore(machine))
1298 return 0; 1293 return 0;
1299 1294
1300 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
1301 if (machine__is_host(machine)) 1295 if (machine__is_host(machine))
1302 kernel_type = DSO_TYPE_KERNEL; 1296 kernel_type = DSO_TYPE_KERNEL;
1303 else 1297 else
1304 kernel_type = DSO_TYPE_GUEST_KERNEL; 1298 kernel_type = DSO_TYPE_GUEST_KERNEL;
1305 1299
1306 is_kernel_mmap = memcmp(event->mmap.filename, 1300 is_kernel_mmap = memcmp(event->mmap.filename,
1307 kmmap_prefix, 1301 machine->mmap_name,
1308 strlen(kmmap_prefix) - 1) == 0; 1302 strlen(machine->mmap_name) - 1) == 0;
1309 if (event->mmap.filename[0] == '/' || 1303 if (event->mmap.filename[0] == '/' ||
1310 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 1304 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
1311 map = machine__findnew_module_map(machine, event->mmap.start, 1305 map = machine__findnew_module_map(machine, event->mmap.start,
@@ -1316,7 +1310,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1316 map->end = map->start + event->mmap.len; 1310 map->end = map->start + event->mmap.len;
1317 } else if (is_kernel_mmap) { 1311 } else if (is_kernel_mmap) {
1318 const char *symbol_name = (event->mmap.filename + 1312 const char *symbol_name = (event->mmap.filename +
1319 strlen(kmmap_prefix)); 1313 strlen(machine->mmap_name));
1320 /* 1314 /*
1321 * Should be there already, from the build-id table in 1315 * Should be there already, from the build-id table in
1322 * the header. 1316 * the header.
@@ -1357,7 +1351,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1357 up_read(&machine->dsos.lock); 1351 up_read(&machine->dsos.lock);
1358 1352
1359 if (kernel == NULL) 1353 if (kernel == NULL)
1360 kernel = machine__findnew_dso(machine, kmmap_prefix); 1354 kernel = machine__findnew_dso(machine, machine->mmap_name);
1361 if (kernel == NULL) 1355 if (kernel == NULL)
1362 goto out_problem; 1356 goto out_problem;
1363 1357
@@ -1370,7 +1364,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1370 if (strstr(kernel->long_name, "vmlinux")) 1364 if (strstr(kernel->long_name, "vmlinux"))
1371 dso__set_short_name(kernel, "[kernel.vmlinux]", false); 1365 dso__set_short_name(kernel, "[kernel.vmlinux]", false);
1372 1366
1373 machine__set_kernel_mmap_len(machine, event); 1367 machine__set_kernel_mmap(machine, event->mmap.start,
1368 event->mmap.start + event->mmap.len);
1374 1369
1375 /* 1370 /*
1376 * Avoid using a zero address (kptr_restrict) for the ref reloc 1371 * Avoid using a zero address (kptr_restrict) for the ref reloc
@@ -1700,7 +1695,7 @@ static void ip__resolve_data(struct thread *thread,
1700struct mem_info *sample__resolve_mem(struct perf_sample *sample, 1695struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1701 struct addr_location *al) 1696 struct addr_location *al)
1702{ 1697{
1703 struct mem_info *mi = zalloc(sizeof(*mi)); 1698 struct mem_info *mi = mem_info__new();
1704 1699
1705 if (!mi) 1700 if (!mi)
1706 return NULL; 1701 return NULL;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 5ce860b64c74..66cc200ef86f 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -43,6 +43,7 @@ struct machine {
43 bool comm_exec; 43 bool comm_exec;
44 bool kptr_restrict_warned; 44 bool kptr_restrict_warned;
45 char *root_dir; 45 char *root_dir;
46 char *mmap_name;
46 struct threads threads[THREADS__TABLE_SIZE]; 47 struct threads threads[THREADS__TABLE_SIZE];
47 struct vdso_info *vdso_info; 48 struct vdso_info *vdso_info;
48 struct perf_env *env; 49 struct perf_env *env;
@@ -142,8 +143,6 @@ struct machine *machines__find(struct machines *machines, pid_t pid);
142struct machine *machines__findnew(struct machines *machines, pid_t pid); 143struct machine *machines__findnew(struct machines *machines, pid_t pid);
143 144
144void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); 145void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
145char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
146
147void machines__set_comm_exec(struct machines *machines, bool comm_exec); 146void machines__set_comm_exec(struct machines *machines, bool comm_exec);
148 147
149struct machine *machine__new_host(void); 148struct machine *machine__new_host(void);
@@ -226,8 +225,6 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
226 const char *filename); 225 const char *filename);
227int arch__fix_module_text_start(u64 *start, const char *name); 226int arch__fix_module_text_start(u64 *start, const char *name);
228 227
229int __machine__load_kallsyms(struct machine *machine, const char *filename,
230 enum map_type type, bool no_kcore);
231int machine__load_kallsyms(struct machine *machine, const char *filename, 228int machine__load_kallsyms(struct machine *machine, const char *filename,
232 enum map_type type); 229 enum map_type type);
233int machine__load_vmlinux_path(struct machine *machine, enum map_type type); 230int machine__load_vmlinux_path(struct machine *machine, enum map_type type);
@@ -239,7 +236,6 @@ size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
239 bool (skip)(struct dso *dso, int parm), int parm); 236 bool (skip)(struct dso *dso, int parm), int parm);
240 237
241void machine__destroy_kernel_maps(struct machine *machine); 238void machine__destroy_kernel_maps(struct machine *machine);
242int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
243int machine__create_kernel_maps(struct machine *machine); 239int machine__create_kernel_maps(struct machine *machine);
244 240
245int machines__create_kernel_maps(struct machines *machines, pid_t pid); 241int machines__create_kernel_maps(struct machines *machines, pid_t pid);
diff --git a/tools/perf/util/mem2node.c b/tools/perf/util/mem2node.c
new file mode 100644
index 000000000000..c6fd81c02586
--- /dev/null
+++ b/tools/perf/util/mem2node.c
@@ -0,0 +1,134 @@
1#include <errno.h>
2#include <inttypes.h>
3#include <linux/bitmap.h>
4#include "mem2node.h"
5#include "util.h"
6
7struct phys_entry {
8 struct rb_node rb_node;
9 u64 start;
10 u64 end;
11 u64 node;
12};
13
14static void phys_entry__insert(struct phys_entry *entry, struct rb_root *root)
15{
16 struct rb_node **p = &root->rb_node;
17 struct rb_node *parent = NULL;
18 struct phys_entry *e;
19
20 while (*p != NULL) {
21 parent = *p;
22 e = rb_entry(parent, struct phys_entry, rb_node);
23
24 if (entry->start < e->start)
25 p = &(*p)->rb_left;
26 else
27 p = &(*p)->rb_right;
28 }
29
30 rb_link_node(&entry->rb_node, parent, p);
31 rb_insert_color(&entry->rb_node, root);
32}
33
34static void
35phys_entry__init(struct phys_entry *entry, u64 start, u64 bsize, u64 node)
36{
37 entry->start = start;
38 entry->end = start + bsize;
39 entry->node = node;
40 RB_CLEAR_NODE(&entry->rb_node);
41}
42
43int mem2node__init(struct mem2node *map, struct perf_env *env)
44{
45 struct memory_node *n, *nodes = &env->memory_nodes[0];
46 struct phys_entry *entries, *tmp_entries;
47 u64 bsize = env->memory_bsize;
48 int i, j = 0, max = 0;
49
50 memset(map, 0x0, sizeof(*map));
51 map->root = RB_ROOT;
52
53 for (i = 0; i < env->nr_memory_nodes; i++) {
54 n = &nodes[i];
55 max += bitmap_weight(n->set, n->size);
56 }
57
58 entries = zalloc(sizeof(*entries) * max);
59 if (!entries)
60 return -ENOMEM;
61
62 for (i = 0; i < env->nr_memory_nodes; i++) {
63 u64 bit;
64
65 n = &nodes[i];
66
67 for (bit = 0; bit < n->size; bit++) {
68 u64 start;
69
70 if (!test_bit(bit, n->set))
71 continue;
72
73 start = bit * bsize;
74
75 /*
76 * Merge nearby areas, we walk in order
77 * through the bitmap, so no need to sort.
78 */
79 if (j > 0) {
80 struct phys_entry *prev = &entries[j - 1];
81
82 if ((prev->end == start) &&
83 (prev->node == n->node)) {
84 prev->end += bsize;
85 continue;
86 }
87 }
88
89 phys_entry__init(&entries[j++], start, bsize, n->node);
90 }
91 }
92
93 /* Cut unused entries, due to merging. */
94 tmp_entries = realloc(entries, sizeof(*entries) * j);
95 if (tmp_entries)
96 entries = tmp_entries;
97
98 for (i = 0; i < j; i++) {
99 pr_debug("mem2node %03" PRIu64 " [0x%016" PRIx64 "-0x%016" PRIx64 "]\n",
100 entries[i].node, entries[i].start, entries[i].end);
101
102 phys_entry__insert(&entries[i], &map->root);
103 }
104
105 map->entries = entries;
106 return 0;
107}
108
109void mem2node__exit(struct mem2node *map)
110{
111 zfree(&map->entries);
112}
113
114int mem2node__node(struct mem2node *map, u64 addr)
115{
116 struct rb_node **p, *parent = NULL;
117 struct phys_entry *entry;
118
119 p = &map->root.rb_node;
120 while (*p != NULL) {
121 parent = *p;
122 entry = rb_entry(parent, struct phys_entry, rb_node);
123 if (addr < entry->start)
124 p = &(*p)->rb_left;
125 else if (addr >= entry->end)
126 p = &(*p)->rb_right;
127 else
128 goto out;
129 }
130
131 entry = NULL;
132out:
133 return entry ? (int) entry->node : -1;
134}
diff --git a/tools/perf/util/mem2node.h b/tools/perf/util/mem2node.h
new file mode 100644
index 000000000000..59c4752a2181
--- /dev/null
+++ b/tools/perf/util/mem2node.h
@@ -0,0 +1,19 @@
1#ifndef __MEM2NODE_H
2#define __MEM2NODE_H
3
4#include <linux/rbtree.h>
5#include "env.h"
6
7struct phys_entry;
8
9struct mem2node {
10 struct rb_root root;
11 struct phys_entry *entries;
12 int cnt;
13};
14
15int mem2node__init(struct mem2node *map, struct perf_env *env);
16void mem2node__exit(struct mem2node *map);
17int mem2node__node(struct mem2node *map, u64 addr);
18
19#endif /* __MEM2NODE_H */
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 91531a7c8fbf..fc832676a798 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -64,25 +64,6 @@ static union perf_event *perf_mmap__read(struct perf_mmap *map,
64} 64}
65 65
66/* 66/*
67 * legacy interface for mmap read.
68 * Don't use it. Use perf_mmap__read_event().
69 */
70union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
71{
72 u64 head;
73
74 /*
75 * Check if event was unmapped due to a POLLHUP/POLLERR.
76 */
77 if (!refcount_read(&map->refcnt))
78 return NULL;
79
80 head = perf_mmap__read_head(map);
81
82 return perf_mmap__read(map, &map->prev, head);
83}
84
85/*
86 * Read event from ring buffer one by one. 67 * Read event from ring buffer one by one.
87 * Return one event for each call. 68 * Return one event for each call.
88 * 69 *
@@ -94,9 +75,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map)
94 * } 75 * }
95 * perf_mmap__read_done() 76 * perf_mmap__read_done()
96 */ 77 */
97union perf_event *perf_mmap__read_event(struct perf_mmap *map, 78union perf_event *perf_mmap__read_event(struct perf_mmap *map)
98 bool overwrite,
99 u64 *startp, u64 end)
100{ 79{
101 union perf_event *event; 80 union perf_event *event;
102 81
@@ -106,17 +85,14 @@ union perf_event *perf_mmap__read_event(struct perf_mmap *map,
106 if (!refcount_read(&map->refcnt)) 85 if (!refcount_read(&map->refcnt))
107 return NULL; 86 return NULL;
108 87
109 if (startp == NULL)
110 return NULL;
111
112 /* non-overwirte doesn't pause the ringbuffer */ 88 /* non-overwirte doesn't pause the ringbuffer */
113 if (!overwrite) 89 if (!map->overwrite)
114 end = perf_mmap__read_head(map); 90 map->end = perf_mmap__read_head(map);
115 91
116 event = perf_mmap__read(map, startp, end); 92 event = perf_mmap__read(map, &map->start, map->end);
117 93
118 if (!overwrite) 94 if (!map->overwrite)
119 map->prev = *startp; 95 map->prev = map->start;
120 96
121 return event; 97 return event;
122} 98}
@@ -139,9 +115,9 @@ void perf_mmap__put(struct perf_mmap *map)
139 perf_mmap__munmap(map); 115 perf_mmap__munmap(map);
140} 116}
141 117
142void perf_mmap__consume(struct perf_mmap *map, bool overwrite) 118void perf_mmap__consume(struct perf_mmap *map)
143{ 119{
144 if (!overwrite) { 120 if (!map->overwrite) {
145 u64 old = map->prev; 121 u64 old = map->prev;
146 122
147 perf_mmap__write_tail(map, old); 123 perf_mmap__write_tail(map, old);
@@ -191,7 +167,7 @@ void perf_mmap__munmap(struct perf_mmap *map)
191int 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)
192{ 168{
193 /* 169 /*
194 * The last one will be done at perf_evlist__mmap_consume(), so that we 170 * The last one will be done at perf_mmap__consume(), so that we
195 * make sure we don't prevent tools from consuming every last event in 171 * make sure we don't prevent tools from consuming every last event in
196 * the ring buffer. 172 * the ring buffer.
197 * 173 *
@@ -223,19 +199,18 @@ int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
223 return 0; 199 return 0;
224} 200}
225 201
226static int overwrite_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) 202static int overwrite_rb_find_range(void *buf, int mask, u64 *start, u64 *end)
227{ 203{
228 struct perf_event_header *pheader; 204 struct perf_event_header *pheader;
229 u64 evt_head = head; 205 u64 evt_head = *start;
230 int size = mask + 1; 206 int size = mask + 1;
231 207
232 pr_debug2("overwrite_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head); 208 pr_debug2("%s: buf=%p, start=%"PRIx64"\n", __func__, buf, *start);
233 pheader = (struct perf_event_header *)(buf + (head & mask)); 209 pheader = (struct perf_event_header *)(buf + (*start & mask));
234 *start = head;
235 while (true) { 210 while (true) {
236 if (evt_head - head >= (unsigned int)size) { 211 if (evt_head - *start >= (unsigned int)size) {
237 pr_debug("Finished reading overwrite ring buffer: rewind\n"); 212 pr_debug("Finished reading overwrite ring buffer: rewind\n");
238 if (evt_head - head > (unsigned int)size) 213 if (evt_head - *start > (unsigned int)size)
239 evt_head -= pheader->size; 214 evt_head -= pheader->size;
240 *end = evt_head; 215 *end = evt_head;
241 return 0; 216 return 0;
@@ -259,27 +234,26 @@ static int overwrite_rb_find_range(void *buf, int mask, u64 head, u64 *start, u6
259/* 234/*
260 * Report the start and end of the available data in ringbuffer 235 * Report the start and end of the available data in ringbuffer
261 */ 236 */
262int perf_mmap__read_init(struct perf_mmap *md, bool overwrite, 237static int __perf_mmap__read_init(struct perf_mmap *md)
263 u64 *startp, u64 *endp)
264{ 238{
265 u64 head = perf_mmap__read_head(md); 239 u64 head = perf_mmap__read_head(md);
266 u64 old = md->prev; 240 u64 old = md->prev;
267 unsigned char *data = md->base + page_size; 241 unsigned char *data = md->base + page_size;
268 unsigned long size; 242 unsigned long size;
269 243
270 *startp = overwrite ? head : old; 244 md->start = md->overwrite ? head : old;
271 *endp = overwrite ? old : head; 245 md->end = md->overwrite ? old : head;
272 246
273 if (*startp == *endp) 247 if (md->start == md->end)
274 return -EAGAIN; 248 return -EAGAIN;
275 249
276 size = *endp - *startp; 250 size = md->end - md->start;
277 if (size > (unsigned long)(md->mask) + 1) { 251 if (size > (unsigned long)(md->mask) + 1) {
278 if (!overwrite) { 252 if (!md->overwrite) {
279 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 253 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
280 254
281 md->prev = head; 255 md->prev = head;
282 perf_mmap__consume(md, overwrite); 256 perf_mmap__consume(md);
283 return -EAGAIN; 257 return -EAGAIN;
284 } 258 }
285 259
@@ -287,33 +261,43 @@ int perf_mmap__read_init(struct perf_mmap *md, bool overwrite,
287 * Backward ring buffer is full. We still have a chance to read 261 * Backward ring buffer is full. We still have a chance to read
288 * most of data from it. 262 * most of data from it.
289 */ 263 */
290 if (overwrite_rb_find_range(data, md->mask, head, startp, endp)) 264 if (overwrite_rb_find_range(data, md->mask, &md->start, &md->end))
291 return -EINVAL; 265 return -EINVAL;
292 } 266 }
293 267
294 return 0; 268 return 0;
295} 269}
296 270
297int perf_mmap__push(struct perf_mmap *md, bool overwrite, 271int perf_mmap__read_init(struct perf_mmap *map)
298 void *to, int push(void *to, void *buf, size_t size)) 272{
273 /*
274 * Check if event was unmapped due to a POLLHUP/POLLERR.
275 */
276 if (!refcount_read(&map->refcnt))
277 return -ENOENT;
278
279 return __perf_mmap__read_init(map);
280}
281
282int perf_mmap__push(struct perf_mmap *md, void *to,
283 int push(void *to, void *buf, size_t size))
299{ 284{
300 u64 head = perf_mmap__read_head(md); 285 u64 head = perf_mmap__read_head(md);
301 u64 end, start;
302 unsigned char *data = md->base + page_size; 286 unsigned char *data = md->base + page_size;
303 unsigned long size; 287 unsigned long size;
304 void *buf; 288 void *buf;
305 int rc = 0; 289 int rc = 0;
306 290
307 rc = perf_mmap__read_init(md, overwrite, &start, &end); 291 rc = perf_mmap__read_init(md);
308 if (rc < 0) 292 if (rc < 0)
309 return (rc == -EAGAIN) ? 0 : -1; 293 return (rc == -EAGAIN) ? 0 : -1;
310 294
311 size = end - start; 295 size = md->end - md->start;
312 296
313 if ((start & md->mask) + size != (end & md->mask)) { 297 if ((md->start & md->mask) + size != (md->end & md->mask)) {
314 buf = &data[start & md->mask]; 298 buf = &data[md->start & md->mask];
315 size = md->mask + 1 - (start & md->mask); 299 size = md->mask + 1 - (md->start & md->mask);
316 start += size; 300 md->start += size;
317 301
318 if (push(to, buf, size) < 0) { 302 if (push(to, buf, size) < 0) {
319 rc = -1; 303 rc = -1;
@@ -321,9 +305,9 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite,
321 } 305 }
322 } 306 }
323 307
324 buf = &data[start & md->mask]; 308 buf = &data[md->start & md->mask];
325 size = end - start; 309 size = md->end - md->start;
326 start += size; 310 md->start += size;
327 311
328 if (push(to, buf, size) < 0) { 312 if (push(to, buf, size) < 0) {
329 rc = -1; 313 rc = -1;
@@ -331,7 +315,7 @@ int perf_mmap__push(struct perf_mmap *md, bool overwrite,
331 } 315 }
332 316
333 md->prev = head; 317 md->prev = head;
334 perf_mmap__consume(md, overwrite); 318 perf_mmap__consume(md);
335out: 319out:
336 return rc; 320 return rc;
337} 321}
@@ -344,5 +328,11 @@ out:
344 */ 328 */
345void perf_mmap__read_done(struct perf_mmap *map) 329void perf_mmap__read_done(struct perf_mmap *map)
346{ 330{
331 /*
332 * Check if event was unmapped due to a POLLHUP/POLLERR.
333 */
334 if (!refcount_read(&map->refcnt))
335 return;
336
347 map->prev = perf_mmap__read_head(map); 337 map->prev = perf_mmap__read_head(map);
348} 338}
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index ec7d3a24e276..d82294db1295 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -20,6 +20,9 @@ struct perf_mmap {
20 int fd; 20 int fd;
21 refcount_t refcnt; 21 refcount_t refcnt;
22 u64 prev; 22 u64 prev;
23 u64 start;
24 u64 end;
25 bool overwrite;
23 struct auxtrace_mmap auxtrace_mmap; 26 struct auxtrace_mmap auxtrace_mmap;
24 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8); 27 char event_copy[PERF_SAMPLE_MAX_SIZE] __aligned(8);
25}; 28};
@@ -63,7 +66,7 @@ void perf_mmap__munmap(struct perf_mmap *map);
63void perf_mmap__get(struct perf_mmap *map); 66void perf_mmap__get(struct perf_mmap *map);
64void perf_mmap__put(struct perf_mmap *map); 67void perf_mmap__put(struct perf_mmap *map);
65 68
66void perf_mmap__consume(struct perf_mmap *map, bool overwrite); 69void perf_mmap__consume(struct perf_mmap *map);
67 70
68static inline u64 perf_mmap__read_head(struct perf_mmap *mm) 71static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
69{ 72{
@@ -86,16 +89,13 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
86 89
87union perf_event *perf_mmap__read_forward(struct perf_mmap *map); 90union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
88 91
89union perf_event *perf_mmap__read_event(struct perf_mmap *map, 92union perf_event *perf_mmap__read_event(struct perf_mmap *map);
90 bool overwrite,
91 u64 *startp, u64 end);
92 93
93int perf_mmap__push(struct perf_mmap *md, bool backward, 94int perf_mmap__push(struct perf_mmap *md, void *to,
94 void *to, int push(void *to, void *buf, size_t size)); 95 int push(void *to, void *buf, size_t size));
95 96
96size_t perf_mmap__mmap_len(struct perf_mmap *map); 97size_t perf_mmap__mmap_len(struct perf_mmap *map);
97 98
98int perf_mmap__read_init(struct perf_mmap *md, bool overwrite, 99int perf_mmap__read_init(struct perf_mmap *md);
99 u64 *startp, u64 *endp);
100void perf_mmap__read_done(struct perf_mmap *map); 100void perf_mmap__read_done(struct perf_mmap *map);
101#endif /*__PERF_MMAP_H */ 101#endif /*__PERF_MMAP_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 34589c427e52..2fb0272146d8 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -206,8 +206,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
206 206
207 for_each_event(sys_dirent, evt_dir, evt_dirent) { 207 for_each_event(sys_dirent, evt_dir, evt_dirent) {
208 208
209 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 209 scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
210 evt_dirent->d_name); 210 evt_dirent->d_name);
211 fd = open(evt_path, O_RDONLY); 211 fd = open(evt_path, O_RDONLY);
212 if (fd < 0) 212 if (fd < 0)
213 continue; 213 continue;
@@ -1217,7 +1217,7 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
1217 get_config_name(head_config), &config_terms); 1217 get_config_name(head_config), &config_terms);
1218} 1218}
1219 1219
1220static int __parse_events_add_pmu(struct parse_events_state *parse_state, 1220int parse_events_add_pmu(struct parse_events_state *parse_state,
1221 struct list_head *list, char *name, 1221 struct list_head *list, char *name,
1222 struct list_head *head_config, bool auto_merge_stats) 1222 struct list_head *head_config, bool auto_merge_stats)
1223{ 1223{
@@ -1247,7 +1247,12 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1247 if (!head_config) { 1247 if (!head_config) {
1248 attr.type = pmu->type; 1248 attr.type = pmu->type;
1249 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats); 1249 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats);
1250 return evsel ? 0 : -ENOMEM; 1250 if (evsel) {
1251 evsel->pmu_name = name;
1252 return 0;
1253 } else {
1254 return -ENOMEM;
1255 }
1251 } 1256 }
1252 1257
1253 if (perf_pmu__check_alias(pmu, head_config, &info)) 1258 if (perf_pmu__check_alias(pmu, head_config, &info))
@@ -1276,18 +1281,12 @@ static int __parse_events_add_pmu(struct parse_events_state *parse_state,
1276 evsel->snapshot = info.snapshot; 1281 evsel->snapshot = info.snapshot;
1277 evsel->metric_expr = info.metric_expr; 1282 evsel->metric_expr = info.metric_expr;
1278 evsel->metric_name = info.metric_name; 1283 evsel->metric_name = info.metric_name;
1284 evsel->pmu_name = name;
1279 } 1285 }
1280 1286
1281 return evsel ? 0 : -ENOMEM; 1287 return evsel ? 0 : -ENOMEM;
1282} 1288}
1283 1289
1284int parse_events_add_pmu(struct parse_events_state *parse_state,
1285 struct list_head *list, char *name,
1286 struct list_head *head_config)
1287{
1288 return __parse_events_add_pmu(parse_state, list, name, head_config, false);
1289}
1290
1291int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 1290int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1292 char *str, struct list_head **listp) 1291 char *str, struct list_head **listp)
1293{ 1292{
@@ -1317,8 +1316,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1317 return -1; 1316 return -1;
1318 list_add_tail(&term->list, head); 1317 list_add_tail(&term->list, head);
1319 1318
1320 if (!__parse_events_add_pmu(parse_state, list, 1319 if (!parse_events_add_pmu(parse_state, list,
1321 pmu->name, head, true)) { 1320 pmu->name, head, true)) {
1322 pr_debug("%s -> %s/%s/\n", str, 1321 pr_debug("%s -> %s/%s/\n", str,
1323 pmu->name, alias->str); 1322 pmu->name, alias->str);
1324 ok++; 1323 ok++;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 88108cd11b4c..5015cfd58277 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -167,7 +167,7 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
167 void *ptr, char *type, u64 len); 167 void *ptr, char *type, u64 len);
168int parse_events_add_pmu(struct parse_events_state *parse_state, 168int parse_events_add_pmu(struct parse_events_state *parse_state,
169 struct list_head *list, char *name, 169 struct list_head *list, char *name,
170 struct list_head *head_config); 170 struct list_head *head_config, bool auto_merge_stats);
171 171
172int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 172int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
173 char *str, 173 char *str,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 655ecff636a8..a1a01b1ac8b8 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -175,7 +175,7 @@ bpf_source [^,{}]+\.c[a-zA-Z0-9._]*
175num_dec [0-9]+ 175num_dec [0-9]+
176num_hex 0x[a-fA-F0-9]+ 176num_hex 0x[a-fA-F0-9]+
177num_raw_hex [a-fA-F0-9]+ 177num_raw_hex [a-fA-F0-9]+
178name [a-zA-Z_*?][a-zA-Z0-9_*?.]* 178name [a-zA-Z_*?\[\]][a-zA-Z0-9_*?.\[\]]*
179name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 179name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
180drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)? 180drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
181/* If you add a modifier you need to update check_modifier() */ 181/* If you add a modifier you need to update check_modifier() */
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index e81a20ea8d7d..7afeb80cc39e 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -8,6 +8,7 @@
8 8
9#define YYDEBUG 1 9#define YYDEBUG 1
10 10
11#include <fnmatch.h>
11#include <linux/compiler.h> 12#include <linux/compiler.h>
12#include <linux/list.h> 13#include <linux/list.h>
13#include <linux/types.h> 14#include <linux/types.h>
@@ -231,9 +232,13 @@ PE_NAME opt_event_config
231 YYABORT; 232 YYABORT;
232 233
233 ALLOC_LIST(list); 234 ALLOC_LIST(list);
234 if (parse_events_add_pmu(_parse_state, list, $1, $2)) { 235 if (parse_events_add_pmu(_parse_state, list, $1, $2, false)) {
235 struct perf_pmu *pmu = NULL; 236 struct perf_pmu *pmu = NULL;
236 int ok = 0; 237 int ok = 0;
238 char *pattern;
239
240 if (asprintf(&pattern, "%s*", $1) < 0)
241 YYABORT;
237 242
238 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 243 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
239 char *name = pmu->name; 244 char *name = pmu->name;
@@ -241,14 +246,19 @@ PE_NAME opt_event_config
241 if (!strncmp(name, "uncore_", 7) && 246 if (!strncmp(name, "uncore_", 7) &&
242 strncmp($1, "uncore_", 7)) 247 strncmp($1, "uncore_", 7))
243 name += 7; 248 name += 7;
244 if (!strncmp($1, name, strlen($1))) { 249 if (!fnmatch(pattern, name, 0)) {
245 if (parse_events_copy_term_list(orig_terms, &terms)) 250 if (parse_events_copy_term_list(orig_terms, &terms)) {
251 free(pattern);
246 YYABORT; 252 YYABORT;
247 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms)) 253 }
254 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true))
248 ok++; 255 ok++;
249 parse_events_terms__delete(terms); 256 parse_events_terms__delete(terms);
250 } 257 }
251 } 258 }
259
260 free(pattern);
261
252 if (!ok) 262 if (!ok)
253 YYABORT; 263 YYABORT;
254 } 264 }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 57e38fdf0b34..064bdcb7bd78 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -351,7 +351,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
351 if (pmu_alias_info_file(name)) 351 if (pmu_alias_info_file(name))
352 continue; 352 continue;
353 353
354 snprintf(path, PATH_MAX, "%s/%s", dir, name); 354 scnprintf(path, PATH_MAX, "%s/%s", dir, name);
355 355
356 file = fopen(path, "r"); 356 file = fopen(path, "r");
357 if (!file) { 357 if (!file) {
@@ -576,6 +576,34 @@ char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
576 return NULL; 576 return NULL;
577} 577}
578 578
579/* Return zero when the cpuid from the mapfile.csv matches the
580 * cpuid string generated on this platform.
581 * Otherwise return non-zero.
582 */
583int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
584{
585 regex_t re;
586 regmatch_t pmatch[1];
587 int match;
588
589 if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
590 /* Warn unable to generate match particular string. */
591 pr_info("Invalid regular expression %s\n", mapcpuid);
592 return 1;
593 }
594
595 match = !regexec(&re, cpuid, 1, pmatch, 0);
596 regfree(&re);
597 if (match) {
598 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
599
600 /* Verify the entire string matched. */
601 if (match_len == strlen(cpuid))
602 return 0;
603 }
604 return 1;
605}
606
579static char *perf_pmu__getcpuid(struct perf_pmu *pmu) 607static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
580{ 608{
581 char *cpuid; 609 char *cpuid;
@@ -610,31 +638,14 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
610 638
611 i = 0; 639 i = 0;
612 for (;;) { 640 for (;;) {
613 regex_t re;
614 regmatch_t pmatch[1];
615 int match;
616
617 map = &pmu_events_map[i++]; 641 map = &pmu_events_map[i++];
618 if (!map->table) { 642 if (!map->table) {
619 map = NULL; 643 map = NULL;
620 break; 644 break;
621 } 645 }
622 646
623 if (regcomp(&re, map->cpuid, REG_EXTENDED) != 0) { 647 if (!strcmp_cpuid_str(map->cpuid, cpuid))
624 /* Warn unable to generate match particular string. */
625 pr_info("Invalid regular expression %s\n", map->cpuid);
626 break; 648 break;
627 }
628
629 match = !regexec(&re, cpuid, 1, pmatch, 0);
630 regfree(&re);
631 if (match) {
632 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
633
634 /* Verify the entire string matched. */
635 if (match_len == strlen(cpuid))
636 break;
637 }
638 } 649 }
639 free(cpuid); 650 free(cpuid);
640 return map; 651 return map;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index a5731de0e5eb..c37fbef1711d 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -423,20 +423,20 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
423 pr_warning("Failed to get the type of %s.\n", varname); 423 pr_warning("Failed to get the type of %s.\n", varname);
424 return -ENOENT; 424 return -ENOENT;
425 } 425 }
426 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); 426 pr_debug2("Var real type: %s (%x)\n", dwarf_diename(&type),
427 (unsigned)dwarf_dieoffset(&type));
427 tag = dwarf_tag(&type); 428 tag = dwarf_tag(&type);
428 429
429 if (field->name[0] == '[' && 430 if (field->name[0] == '[' &&
430 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { 431 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
431 if (field->next) 432 /* Save original type for next field or type */
432 /* Save original type for next field */ 433 memcpy(die_mem, &type, sizeof(*die_mem));
433 memcpy(die_mem, &type, sizeof(*die_mem));
434 /* Get the type of this array */ 434 /* Get the type of this array */
435 if (die_get_real_type(&type, &type) == NULL) { 435 if (die_get_real_type(&type, &type) == NULL) {
436 pr_warning("Failed to get the type of %s.\n", varname); 436 pr_warning("Failed to get the type of %s.\n", varname);
437 return -ENOENT; 437 return -ENOENT;
438 } 438 }
439 pr_debug2("Array real type: (%x)\n", 439 pr_debug2("Array real type: %s (%x)\n", dwarf_diename(&type),
440 (unsigned)dwarf_dieoffset(&type)); 440 (unsigned)dwarf_dieoffset(&type));
441 if (tag == DW_TAG_pointer_type) { 441 if (tag == DW_TAG_pointer_type) {
442 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 442 ref = zalloc(sizeof(struct probe_trace_arg_ref));
@@ -448,9 +448,6 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
448 *ref_ptr = ref; 448 *ref_ptr = ref;
449 } 449 }
450 ref->offset += dwarf_bytesize(&type) * field->index; 450 ref->offset += dwarf_bytesize(&type) * field->index;
451 if (!field->next)
452 /* Save vr_die for converting types */
453 memcpy(die_mem, vr_die, sizeof(*die_mem));
454 goto next; 451 goto next;
455 } else if (tag == DW_TAG_pointer_type) { 452 } else if (tag == DW_TAG_pointer_type) {
456 /* Check the pointer and dereference */ 453 /* Check the pointer and dereference */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index b1e999bd21ef..863b61478edd 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -12,6 +12,30 @@
12#include "print_binary.h" 12#include "print_binary.h"
13#include "thread_map.h" 13#include "thread_map.h"
14 14
15#if PY_MAJOR_VERSION < 3
16#define _PyUnicode_FromString(arg) \
17 PyString_FromString(arg)
18#define _PyUnicode_AsString(arg) \
19 PyString_AsString(arg)
20#define _PyUnicode_FromFormat(...) \
21 PyString_FromFormat(__VA_ARGS__)
22#define _PyLong_FromLong(arg) \
23 PyInt_FromLong(arg)
24
25#else
26
27#define _PyUnicode_FromString(arg) \
28 PyUnicode_FromString(arg)
29#define _PyUnicode_FromFormat(...) \
30 PyUnicode_FromFormat(__VA_ARGS__)
31#define _PyLong_FromLong(arg) \
32 PyLong_FromLong(arg)
33#endif
34
35#ifndef Py_TYPE
36#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
37#endif
38
15/* 39/*
16 * Provide these two so that we don't have to link against callchain.c and 40 * Provide these two so that we don't have to link against callchain.c and
17 * start dragging hist.c, etc. 41 * start dragging hist.c, etc.
@@ -49,7 +73,11 @@ int eprintf(int level, int var, const char *fmt, ...)
49# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, 73# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
50#endif 74#endif
51 75
76#if PY_MAJOR_VERSION < 3
52PyMODINIT_FUNC initperf(void); 77PyMODINIT_FUNC initperf(void);
78#else
79PyMODINIT_FUNC PyInit_perf(void);
80#endif
53 81
54#define member_def(type, member, ptype, help) \ 82#define member_def(type, member, ptype, help) \
55 { #member, ptype, \ 83 { #member, ptype, \
@@ -107,7 +135,7 @@ static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
107 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { 135 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
108 ret = PyErr_NoMemory(); 136 ret = PyErr_NoMemory();
109 } else { 137 } else {
110 ret = PyString_FromString(s); 138 ret = _PyUnicode_FromString(s);
111 free(s); 139 free(s);
112 } 140 }
113 return ret; 141 return ret;
@@ -138,7 +166,7 @@ static PyMemberDef pyrf_task_event__members[] = {
138 166
139static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent) 167static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
140{ 168{
141 return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " 169 return _PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
142 "ptid: %u, time: %" PRIu64 "}", 170 "ptid: %u, time: %" PRIu64 "}",
143 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", 171 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
144 pevent->event.fork.pid, 172 pevent->event.fork.pid,
@@ -171,7 +199,7 @@ static PyMemberDef pyrf_comm_event__members[] = {
171 199
172static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent) 200static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
173{ 201{
174 return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", 202 return _PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
175 pevent->event.comm.pid, 203 pevent->event.comm.pid,
176 pevent->event.comm.tid, 204 pevent->event.comm.tid,
177 pevent->event.comm.comm); 205 pevent->event.comm.comm);
@@ -202,7 +230,7 @@ static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
202{ 230{
203 struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); 231 struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
204 232
205 return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 233 return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
206 ", stream_id: %" PRIu64 " }", 234 ", stream_id: %" PRIu64 " }",
207 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", 235 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
208 te->time, te->id, te->stream_id); 236 te->time, te->id, te->stream_id);
@@ -237,7 +265,7 @@ static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
237 pevent->event.lost.id, pevent->event.lost.lost) < 0) { 265 pevent->event.lost.id, pevent->event.lost.lost) < 0) {
238 ret = PyErr_NoMemory(); 266 ret = PyErr_NoMemory();
239 } else { 267 } else {
240 ret = PyString_FromString(s); 268 ret = _PyUnicode_FromString(s);
241 free(s); 269 free(s);
242 } 270 }
243 return ret; 271 return ret;
@@ -264,7 +292,7 @@ static PyMemberDef pyrf_read_event__members[] = {
264 292
265static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent) 293static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
266{ 294{
267 return PyString_FromFormat("{ type: read, pid: %u, tid: %u }", 295 return _PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }",
268 pevent->event.read.pid, 296 pevent->event.read.pid,
269 pevent->event.read.tid); 297 pevent->event.read.tid);
270 /* 298 /*
@@ -299,7 +327,7 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
299 if (asprintf(&s, "{ type: sample }") < 0) { 327 if (asprintf(&s, "{ type: sample }") < 0) {
300 ret = PyErr_NoMemory(); 328 ret = PyErr_NoMemory();
301 } else { 329 } else {
302 ret = PyString_FromString(s); 330 ret = _PyUnicode_FromString(s);
303 free(s); 331 free(s);
304 } 332 }
305 return ret; 333 return ret;
@@ -330,7 +358,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
330 } 358 }
331 if (field->flags & FIELD_IS_STRING && 359 if (field->flags & FIELD_IS_STRING &&
332 is_printable_array(data + offset, len)) { 360 is_printable_array(data + offset, len)) {
333 ret = PyString_FromString((char *)data + offset); 361 ret = _PyUnicode_FromString((char *)data + offset);
334 } else { 362 } else {
335 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); 363 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
336 field->flags &= ~FIELD_IS_STRING; 364 field->flags &= ~FIELD_IS_STRING;
@@ -352,7 +380,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
352static PyObject* 380static PyObject*
353get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) 381get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
354{ 382{
355 const char *str = PyString_AsString(PyObject_Str(attr_name)); 383 const char *str = _PyUnicode_AsString(PyObject_Str(attr_name));
356 struct perf_evsel *evsel = pevent->evsel; 384 struct perf_evsel *evsel = pevent->evsel;
357 struct format_field *field; 385 struct format_field *field;
358 386
@@ -416,7 +444,7 @@ static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent)
416 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { 444 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
417 ret = PyErr_NoMemory(); 445 ret = PyErr_NoMemory();
418 } else { 446 } else {
419 ret = PyString_FromString(s); 447 ret = _PyUnicode_FromString(s);
420 free(s); 448 free(s);
421 } 449 }
422 return ret; 450 return ret;
@@ -528,7 +556,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
528static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) 556static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
529{ 557{
530 cpu_map__put(pcpus->cpus); 558 cpu_map__put(pcpus->cpus);
531 pcpus->ob_type->tp_free((PyObject*)pcpus); 559 Py_TYPE(pcpus)->tp_free((PyObject*)pcpus);
532} 560}
533 561
534static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) 562static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
@@ -597,7 +625,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
597static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) 625static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
598{ 626{
599 thread_map__put(pthreads->threads); 627 thread_map__put(pthreads->threads);
600 pthreads->ob_type->tp_free((PyObject*)pthreads); 628 Py_TYPE(pthreads)->tp_free((PyObject*)pthreads);
601} 629}
602 630
603static Py_ssize_t pyrf_thread_map__length(PyObject *obj) 631static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
@@ -759,7 +787,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
759static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) 787static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
760{ 788{
761 perf_evsel__exit(&pevsel->evsel); 789 perf_evsel__exit(&pevsel->evsel);
762 pevsel->ob_type->tp_free((PyObject*)pevsel); 790 Py_TYPE(pevsel)->tp_free((PyObject*)pevsel);
763} 791}
764 792
765static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, 793static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
@@ -850,7 +878,7 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
850static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) 878static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
851{ 879{
852 perf_evlist__exit(&pevlist->evlist); 880 perf_evlist__exit(&pevlist->evlist);
853 pevlist->ob_type->tp_free((PyObject*)pevlist); 881 Py_TYPE(pevlist)->tp_free((PyObject*)pevlist);
854} 882}
855 883
856static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, 884static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
@@ -902,12 +930,16 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
902 930
903 for (i = 0; i < evlist->pollfd.nr; ++i) { 931 for (i = 0; i < evlist->pollfd.nr; ++i) {
904 PyObject *file; 932 PyObject *file;
933#if PY_MAJOR_VERSION < 3
905 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r"); 934 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
906 935
907 if (fp == NULL) 936 if (fp == NULL)
908 goto free_list; 937 goto free_list;
909 938
910 file = PyFile_FromFile(fp, "perf", "r", NULL); 939 file = PyFile_FromFile(fp, "perf", "r", NULL);
940#else
941 file = PyFile_FromFd(evlist->pollfd.entries[i].fd, "perf", "r", -1, NULL, NULL, NULL, 1);
942#endif
911 if (file == NULL) 943 if (file == NULL)
912 goto free_list; 944 goto free_list;
913 945
@@ -951,13 +983,18 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
951 union perf_event *event; 983 union perf_event *event;
952 int sample_id_all = 1, cpu; 984 int sample_id_all = 1, cpu;
953 static char *kwlist[] = { "cpu", "sample_id_all", NULL }; 985 static char *kwlist[] = { "cpu", "sample_id_all", NULL };
986 struct perf_mmap *md;
954 int err; 987 int err;
955 988
956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, 989 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
957 &cpu, &sample_id_all)) 990 &cpu, &sample_id_all))
958 return NULL; 991 return NULL;
959 992
960 event = perf_evlist__mmap_read(evlist, cpu); 993 md = &evlist->mmap[cpu];
994 if (perf_mmap__read_init(md) < 0)
995 goto end;
996
997 event = perf_mmap__read_event(md);
961 if (event != NULL) { 998 if (event != NULL) {
962 PyObject *pyevent = pyrf_event__new(event); 999 PyObject *pyevent = pyrf_event__new(event);
963 struct pyrf_event *pevent = (struct pyrf_event *)pyevent; 1000 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
@@ -967,22 +1004,24 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
967 return PyErr_NoMemory(); 1004 return PyErr_NoMemory();
968 1005
969 evsel = perf_evlist__event2evsel(evlist, event); 1006 evsel = perf_evlist__event2evsel(evlist, event);
970 if (!evsel) 1007 if (!evsel) {
1008 Py_INCREF(Py_None);
971 return Py_None; 1009 return Py_None;
1010 }
972 1011
973 pevent->evsel = evsel; 1012 pevent->evsel = evsel;
974 1013
975 err = perf_evsel__parse_sample(evsel, event, &pevent->sample); 1014 err = perf_evsel__parse_sample(evsel, event, &pevent->sample);
976 1015
977 /* Consume the even only after we parsed it out. */ 1016 /* Consume the even only after we parsed it out. */
978 perf_evlist__mmap_consume(evlist, cpu); 1017 perf_mmap__consume(md);
979 1018
980 if (err) 1019 if (err)
981 return PyErr_Format(PyExc_OSError, 1020 return PyErr_Format(PyExc_OSError,
982 "perf: can't parse sample, err=%d", err); 1021 "perf: can't parse sample, err=%d", err);
983 return pyevent; 1022 return pyevent;
984 } 1023 }
985 1024end:
986 Py_INCREF(Py_None); 1025 Py_INCREF(Py_None);
987 return Py_None; 1026 return Py_None;
988} 1027}
@@ -1194,9 +1233,9 @@ static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
1194 1233
1195 tp_format = trace_event__tp_format(sys, name); 1234 tp_format = trace_event__tp_format(sys, name);
1196 if (IS_ERR(tp_format)) 1235 if (IS_ERR(tp_format))
1197 return PyInt_FromLong(-1); 1236 return _PyLong_FromLong(-1);
1198 1237
1199 return PyInt_FromLong(tp_format->id); 1238 return _PyLong_FromLong(tp_format->id);
1200} 1239}
1201 1240
1202static PyMethodDef perf__methods[] = { 1241static PyMethodDef perf__methods[] = {
@@ -1209,11 +1248,31 @@ static PyMethodDef perf__methods[] = {
1209 { .ml_name = NULL, } 1248 { .ml_name = NULL, }
1210}; 1249};
1211 1250
1251#if PY_MAJOR_VERSION < 3
1212PyMODINIT_FUNC initperf(void) 1252PyMODINIT_FUNC initperf(void)
1253#else
1254PyMODINIT_FUNC PyInit_perf(void)
1255#endif
1213{ 1256{
1214 PyObject *obj; 1257 PyObject *obj;
1215 int i; 1258 int i;
1216 PyObject *dict, *module = Py_InitModule("perf", perf__methods); 1259 PyObject *dict;
1260#if PY_MAJOR_VERSION < 3
1261 PyObject *module = Py_InitModule("perf", perf__methods);
1262#else
1263 static struct PyModuleDef moduledef = {
1264 PyModuleDef_HEAD_INIT,
1265 "perf", /* m_name */
1266 "", /* m_doc */
1267 -1, /* m_size */
1268 perf__methods, /* m_methods */
1269 NULL, /* m_reload */
1270 NULL, /* m_traverse */
1271 NULL, /* m_clear */
1272 NULL, /* m_free */
1273 };
1274 PyObject *module = PyModule_Create(&moduledef);
1275#endif
1217 1276
1218 if (module == NULL || 1277 if (module == NULL ||
1219 pyrf_event__setup_types() < 0 || 1278 pyrf_event__setup_types() < 0 ||
@@ -1221,7 +1280,11 @@ PyMODINIT_FUNC initperf(void)
1221 pyrf_evsel__setup_types() < 0 || 1280 pyrf_evsel__setup_types() < 0 ||
1222 pyrf_thread_map__setup_types() < 0 || 1281 pyrf_thread_map__setup_types() < 0 ||
1223 pyrf_cpu_map__setup_types() < 0) 1282 pyrf_cpu_map__setup_types() < 0)
1283#if PY_MAJOR_VERSION < 3
1224 return; 1284 return;
1285#else
1286 return module;
1287#endif
1225 1288
1226 /* The page_size is placed in util object. */ 1289 /* The page_size is placed in util object. */
1227 page_size = sysconf(_SC_PAGE_SIZE); 1290 page_size = sysconf(_SC_PAGE_SIZE);
@@ -1270,7 +1333,7 @@ PyMODINIT_FUNC initperf(void)
1270 goto error; 1333 goto error;
1271 1334
1272 for (i = 0; perf__constants[i].name != NULL; i++) { 1335 for (i = 0; perf__constants[i].name != NULL; i++) {
1273 obj = PyInt_FromLong(perf__constants[i].value); 1336 obj = _PyLong_FromLong(perf__constants[i].value);
1274 if (obj == NULL) 1337 if (obj == NULL)
1275 goto error; 1338 goto error;
1276 PyDict_SetItemString(dict, perf__constants[i].name, obj); 1339 PyDict_SetItemString(dict, perf__constants[i].name, obj);
@@ -1280,6 +1343,9 @@ PyMODINIT_FUNC initperf(void)
1280error: 1343error:
1281 if (PyErr_Occurred()) 1344 if (PyErr_Occurred())
1282 PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); 1345 PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
1346#if PY_MAJOR_VERSION >= 3
1347 return module;
1348#endif
1283} 1349}
1284 1350
1285/* 1351/*
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 1e97937b03a9..9cfc7bf16531 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -5,6 +5,7 @@
5#include "parse-events.h" 5#include "parse-events.h"
6#include <errno.h> 6#include <errno.h>
7#include <api/fs/fs.h> 7#include <api/fs/fs.h>
8#include <subcmd/parse-options.h>
8#include "util.h" 9#include "util.h"
9#include "cloexec.h" 10#include "cloexec.h"
10 11
@@ -137,6 +138,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
137 struct perf_evsel *evsel; 138 struct perf_evsel *evsel;
138 bool use_sample_identifier = false; 139 bool use_sample_identifier = false;
139 bool use_comm_exec; 140 bool use_comm_exec;
141 bool sample_id = opts->sample_id;
140 142
141 /* 143 /*
142 * Set the evsel leader links before we configure attributes, 144 * Set the evsel leader links before we configure attributes,
@@ -163,8 +165,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
163 * match the id. 165 * match the id.
164 */ 166 */
165 use_sample_identifier = perf_can_sample_identifier(); 167 use_sample_identifier = perf_can_sample_identifier();
166 evlist__for_each_entry(evlist, evsel) 168 sample_id = true;
167 perf_evsel__set_sample_id(evsel, use_sample_identifier);
168 } else if (evlist->nr_entries > 1) { 169 } else if (evlist->nr_entries > 1) {
169 struct perf_evsel *first = perf_evlist__first(evlist); 170 struct perf_evsel *first = perf_evlist__first(evlist);
170 171
@@ -174,6 +175,10 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
174 use_sample_identifier = perf_can_sample_identifier(); 175 use_sample_identifier = perf_can_sample_identifier();
175 break; 176 break;
176 } 177 }
178 sample_id = true;
179 }
180
181 if (sample_id) {
177 evlist__for_each_entry(evlist, evsel) 182 evlist__for_each_entry(evlist, evsel)
178 perf_evsel__set_sample_id(evsel, use_sample_identifier); 183 perf_evsel__set_sample_id(evsel, use_sample_identifier);
179 } 184 }
@@ -215,11 +220,21 @@ static int record_opts__config_freq(struct record_opts *opts)
215 * User specified frequency is over current maximum. 220 * User specified frequency is over current maximum.
216 */ 221 */
217 if (user_freq && (max_rate < opts->freq)) { 222 if (user_freq && (max_rate < opts->freq)) {
218 pr_err("Maximum frequency rate (%u) reached.\n" 223 if (opts->strict_freq) {
219 "Please use -F freq option with lower value or consider\n" 224 pr_err("error: Maximum frequency rate (%'u Hz) exceeded.\n"
220 "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n", 225 " Please use -F freq option with a lower value or consider\n"
221 max_rate); 226 " tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
222 return -1; 227 max_rate);
228 return -1;
229 } else {
230 pr_warning("warning: Maximum frequency rate (%'u Hz) exceeded, throttling from %'u Hz to %'u Hz.\n"
231 " The limit can be raised via /proc/sys/kernel/perf_event_max_sample_rate.\n"
232 " The kernel will lower it when perf's interrupts take too long.\n"
233 " Use --strict-freq to disable this throttling, refusing to record.\n",
234 max_rate, opts->freq, max_rate);
235
236 opts->freq = max_rate;
237 }
223 } 238 }
224 239
225 /* 240 /*
@@ -287,3 +302,25 @@ out_delete:
287 perf_evlist__delete(temp_evlist); 302 perf_evlist__delete(temp_evlist);
288 return ret; 303 return ret;
289} 304}
305
306int record__parse_freq(const struct option *opt, const char *str, int unset __maybe_unused)
307{
308 unsigned int freq;
309 struct record_opts *opts = opt->value;
310
311 if (!str)
312 return -EINVAL;
313
314 if (strcasecmp(str, "max") == 0) {
315 if (get_max_rate(&freq)) {
316 pr_err("couldn't read /proc/sys/kernel/perf_event_max_sample_rate\n");
317 return -1;
318 }
319 pr_info("info: Using a maximum frequency rate of %'d Hz\n", freq);
320 } else {
321 freq = atoi(str);
322 }
323
324 opts->user_freq = freq;
325 return 0;
326}
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ea070883c593..10dd5fce082b 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -49,7 +49,37 @@
49#include "print_binary.h" 49#include "print_binary.h"
50#include "stat.h" 50#include "stat.h"
51 51
52#if PY_MAJOR_VERSION < 3
53#define _PyUnicode_FromString(arg) \
54 PyString_FromString(arg)
55#define _PyUnicode_FromStringAndSize(arg1, arg2) \
56 PyString_FromStringAndSize((arg1), (arg2))
57#define _PyBytes_FromStringAndSize(arg1, arg2) \
58 PyString_FromStringAndSize((arg1), (arg2))
59#define _PyLong_FromLong(arg) \
60 PyInt_FromLong(arg)
61#define _PyLong_AsLong(arg) \
62 PyInt_AsLong(arg)
63#define _PyCapsule_New(arg1, arg2, arg3) \
64 PyCObject_FromVoidPtr((arg1), (arg2))
65
52PyMODINIT_FUNC initperf_trace_context(void); 66PyMODINIT_FUNC initperf_trace_context(void);
67#else
68#define _PyUnicode_FromString(arg) \
69 PyUnicode_FromString(arg)
70#define _PyUnicode_FromStringAndSize(arg1, arg2) \
71 PyUnicode_FromStringAndSize((arg1), (arg2))
72#define _PyBytes_FromStringAndSize(arg1, arg2) \
73 PyBytes_FromStringAndSize((arg1), (arg2))
74#define _PyLong_FromLong(arg) \
75 PyLong_FromLong(arg)
76#define _PyLong_AsLong(arg) \
77 PyLong_AsLong(arg)
78#define _PyCapsule_New(arg1, arg2, arg3) \
79 PyCapsule_New((arg1), (arg2), (arg3))
80
81PyMODINIT_FUNC PyInit_perf_trace_context(void);
82#endif
53 83
54#define TRACE_EVENT_TYPE_MAX \ 84#define TRACE_EVENT_TYPE_MAX \
55 ((1 << (sizeof(unsigned short) * 8)) - 1) 85 ((1 << (sizeof(unsigned short) * 8)) - 1)
@@ -135,7 +165,7 @@ static int get_argument_count(PyObject *handler)
135 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, 165 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
136 "co_argcount"); 166 "co_argcount");
137 if (arg_count_obj) { 167 if (arg_count_obj) {
138 arg_count = (int) PyInt_AsLong(arg_count_obj); 168 arg_count = (int) _PyLong_AsLong(arg_count_obj);
139 Py_DECREF(arg_count_obj); 169 Py_DECREF(arg_count_obj);
140 } 170 }
141 Py_DECREF(code_obj); 171 Py_DECREF(code_obj);
@@ -182,10 +212,10 @@ static void define_value(enum print_arg_type field_type,
182 212
183 value = eval_flag(field_value); 213 value = eval_flag(field_value);
184 214
185 PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); 215 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
186 PyTuple_SetItem(t, n++, PyString_FromString(field_name)); 216 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
187 PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 217 PyTuple_SetItem(t, n++, _PyLong_FromLong(value));
188 PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 218 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str));
189 219
190 try_call_object(handler_name, t); 220 try_call_object(handler_name, t);
191 221
@@ -223,10 +253,10 @@ static void define_field(enum print_arg_type field_type,
223 if (!t) 253 if (!t)
224 Py_FatalError("couldn't create Python tuple"); 254 Py_FatalError("couldn't create Python tuple");
225 255
226 PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); 256 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
227 PyTuple_SetItem(t, n++, PyString_FromString(field_name)); 257 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
228 if (field_type == PRINT_FLAGS) 258 if (field_type == PRINT_FLAGS)
229 PyTuple_SetItem(t, n++, PyString_FromString(delim)); 259 PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim));
230 260
231 try_call_object(handler_name, t); 261 try_call_object(handler_name, t);
232 262
@@ -325,12 +355,12 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
325 if (field->flags & FIELD_IS_SIGNED) { 355 if (field->flags & FIELD_IS_SIGNED) {
326 if ((long long)val >= LONG_MIN && 356 if ((long long)val >= LONG_MIN &&
327 (long long)val <= LONG_MAX) 357 (long long)val <= LONG_MAX)
328 obj = PyInt_FromLong(val); 358 obj = _PyLong_FromLong(val);
329 else 359 else
330 obj = PyLong_FromLongLong(val); 360 obj = PyLong_FromLongLong(val);
331 } else { 361 } else {
332 if (val <= LONG_MAX) 362 if (val <= LONG_MAX)
333 obj = PyInt_FromLong(val); 363 obj = _PyLong_FromLong(val);
334 else 364 else
335 obj = PyLong_FromUnsignedLongLong(val); 365 obj = PyLong_FromUnsignedLongLong(val);
336 } 366 }
@@ -389,9 +419,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
389 pydict_set_item_string_decref(pysym, "end", 419 pydict_set_item_string_decref(pysym, "end",
390 PyLong_FromUnsignedLongLong(node->sym->end)); 420 PyLong_FromUnsignedLongLong(node->sym->end));
391 pydict_set_item_string_decref(pysym, "binding", 421 pydict_set_item_string_decref(pysym, "binding",
392 PyInt_FromLong(node->sym->binding)); 422 _PyLong_FromLong(node->sym->binding));
393 pydict_set_item_string_decref(pysym, "name", 423 pydict_set_item_string_decref(pysym, "name",
394 PyString_FromStringAndSize(node->sym->name, 424 _PyUnicode_FromStringAndSize(node->sym->name,
395 node->sym->namelen)); 425 node->sym->namelen));
396 pydict_set_item_string_decref(pyelem, "sym", pysym); 426 pydict_set_item_string_decref(pyelem, "sym", pysym);
397 } 427 }
@@ -406,7 +436,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
406 dsoname = map->dso->name; 436 dsoname = map->dso->name;
407 } 437 }
408 pydict_set_item_string_decref(pyelem, "dso", 438 pydict_set_item_string_decref(pyelem, "dso",
409 PyString_FromString(dsoname)); 439 _PyUnicode_FromString(dsoname));
410 } 440 }
411 441
412 callchain_cursor_advance(&callchain_cursor); 442 callchain_cursor_advance(&callchain_cursor);
@@ -483,16 +513,16 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
483 if (!dict_sample) 513 if (!dict_sample)
484 Py_FatalError("couldn't create Python dictionary"); 514 Py_FatalError("couldn't create Python dictionary");
485 515
486 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 516 pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(perf_evsel__name(evsel)));
487 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( 517 pydict_set_item_string_decref(dict, "attr", _PyUnicode_FromStringAndSize(
488 (const char *)&evsel->attr, sizeof(evsel->attr))); 518 (const char *)&evsel->attr, sizeof(evsel->attr)));
489 519
490 pydict_set_item_string_decref(dict_sample, "pid", 520 pydict_set_item_string_decref(dict_sample, "pid",
491 PyInt_FromLong(sample->pid)); 521 _PyLong_FromLong(sample->pid));
492 pydict_set_item_string_decref(dict_sample, "tid", 522 pydict_set_item_string_decref(dict_sample, "tid",
493 PyInt_FromLong(sample->tid)); 523 _PyLong_FromLong(sample->tid));
494 pydict_set_item_string_decref(dict_sample, "cpu", 524 pydict_set_item_string_decref(dict_sample, "cpu",
495 PyInt_FromLong(sample->cpu)); 525 _PyLong_FromLong(sample->cpu));
496 pydict_set_item_string_decref(dict_sample, "ip", 526 pydict_set_item_string_decref(dict_sample, "ip",
497 PyLong_FromUnsignedLongLong(sample->ip)); 527 PyLong_FromUnsignedLongLong(sample->ip));
498 pydict_set_item_string_decref(dict_sample, "time", 528 pydict_set_item_string_decref(dict_sample, "time",
@@ -504,17 +534,17 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
504 set_sample_read_in_dict(dict_sample, sample, evsel); 534 set_sample_read_in_dict(dict_sample, sample, evsel);
505 pydict_set_item_string_decref(dict, "sample", dict_sample); 535 pydict_set_item_string_decref(dict, "sample", dict_sample);
506 536
507 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 537 pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize(
508 (const char *)sample->raw_data, sample->raw_size)); 538 (const char *)sample->raw_data, sample->raw_size));
509 pydict_set_item_string_decref(dict, "comm", 539 pydict_set_item_string_decref(dict, "comm",
510 PyString_FromString(thread__comm_str(al->thread))); 540 _PyUnicode_FromString(thread__comm_str(al->thread)));
511 if (al->map) { 541 if (al->map) {
512 pydict_set_item_string_decref(dict, "dso", 542 pydict_set_item_string_decref(dict, "dso",
513 PyString_FromString(al->map->dso->name)); 543 _PyUnicode_FromString(al->map->dso->name));
514 } 544 }
515 if (al->sym) { 545 if (al->sym) {
516 pydict_set_item_string_decref(dict, "symbol", 546 pydict_set_item_string_decref(dict, "symbol",
517 PyString_FromString(al->sym->name)); 547 _PyUnicode_FromString(al->sym->name));
518 } 548 }
519 549
520 pydict_set_item_string_decref(dict, "callchain", callchain); 550 pydict_set_item_string_decref(dict, "callchain", callchain);
@@ -574,9 +604,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
574 scripting_context->event_data = data; 604 scripting_context->event_data = data;
575 scripting_context->pevent = evsel->tp_format->pevent; 605 scripting_context->pevent = evsel->tp_format->pevent;
576 606
577 context = PyCObject_FromVoidPtr(scripting_context, NULL); 607 context = _PyCapsule_New(scripting_context, NULL, NULL);
578 608
579 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 609 PyTuple_SetItem(t, n++, _PyUnicode_FromString(handler_name));
580 PyTuple_SetItem(t, n++, context); 610 PyTuple_SetItem(t, n++, context);
581 611
582 /* ip unwinding */ 612 /* ip unwinding */
@@ -585,18 +615,18 @@ static void python_process_tracepoint(struct perf_sample *sample,
585 Py_INCREF(callchain); 615 Py_INCREF(callchain);
586 616
587 if (!dict) { 617 if (!dict) {
588 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 618 PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu));
589 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 619 PyTuple_SetItem(t, n++, _PyLong_FromLong(s));
590 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 620 PyTuple_SetItem(t, n++, _PyLong_FromLong(ns));
591 PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 621 PyTuple_SetItem(t, n++, _PyLong_FromLong(pid));
592 PyTuple_SetItem(t, n++, PyString_FromString(comm)); 622 PyTuple_SetItem(t, n++, _PyUnicode_FromString(comm));
593 PyTuple_SetItem(t, n++, callchain); 623 PyTuple_SetItem(t, n++, callchain);
594 } else { 624 } else {
595 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); 625 pydict_set_item_string_decref(dict, "common_cpu", _PyLong_FromLong(cpu));
596 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); 626 pydict_set_item_string_decref(dict, "common_s", _PyLong_FromLong(s));
597 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); 627 pydict_set_item_string_decref(dict, "common_ns", _PyLong_FromLong(ns));
598 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); 628 pydict_set_item_string_decref(dict, "common_pid", _PyLong_FromLong(pid));
599 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); 629 pydict_set_item_string_decref(dict, "common_comm", _PyUnicode_FromString(comm));
600 pydict_set_item_string_decref(dict, "common_callchain", callchain); 630 pydict_set_item_string_decref(dict, "common_callchain", callchain);
601 } 631 }
602 for (field = event->format.fields; field; field = field->next) { 632 for (field = event->format.fields; field; field = field->next) {
@@ -615,7 +645,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
615 } 645 }
616 if (field->flags & FIELD_IS_STRING && 646 if (field->flags & FIELD_IS_STRING &&
617 is_printable_array(data + offset, len)) { 647 is_printable_array(data + offset, len)) {
618 obj = PyString_FromString((char *) data + offset); 648 obj = _PyUnicode_FromString((char *) data + offset);
619 } else { 649 } else {
620 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); 650 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
621 field->flags &= ~FIELD_IS_STRING; 651 field->flags &= ~FIELD_IS_STRING;
@@ -668,7 +698,7 @@ static PyObject *tuple_new(unsigned int sz)
668static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) 698static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
669{ 699{
670#if BITS_PER_LONG == 64 700#if BITS_PER_LONG == 64
671 return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); 701 return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
672#endif 702#endif
673#if BITS_PER_LONG == 32 703#if BITS_PER_LONG == 32
674 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); 704 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val));
@@ -677,12 +707,12 @@ static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
677 707
678static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) 708static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
679{ 709{
680 return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); 710 return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
681} 711}
682 712
683static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) 713static int tuple_set_string(PyObject *t, unsigned int pos, const char *s)
684{ 714{
685 return PyTuple_SetItem(t, pos, PyString_FromString(s)); 715 return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s));
686} 716}
687 717
688static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) 718static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel)
@@ -1029,8 +1059,8 @@ process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp,
1029 return; 1059 return;
1030 } 1060 }
1031 1061
1032 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 1062 PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu));
1033 PyTuple_SetItem(t, n++, PyInt_FromLong(thread)); 1063 PyTuple_SetItem(t, n++, _PyLong_FromLong(thread));
1034 1064
1035 tuple_set_u64(t, n++, tstamp); 1065 tuple_set_u64(t, n++, tstamp);
1036 tuple_set_u64(t, n++, count->val); 1066 tuple_set_u64(t, n++, count->val);
@@ -1212,27 +1242,58 @@ static void set_table_handlers(struct tables *tables)
1212 SET_TABLE_HANDLER(call_return); 1242 SET_TABLE_HANDLER(call_return);
1213} 1243}
1214 1244
1245#if PY_MAJOR_VERSION < 3
1246static void _free_command_line(const char **command_line, int num)
1247{
1248 free(command_line);
1249}
1250#else
1251static void _free_command_line(wchar_t **command_line, int num)
1252{
1253 int i;
1254 for (i = 0; i < num; i++)
1255 PyMem_RawFree(command_line[i]);
1256 free(command_line);
1257}
1258#endif
1259
1260
1215/* 1261/*
1216 * Start trace script 1262 * Start trace script
1217 */ 1263 */
1218static int python_start_script(const char *script, int argc, const char **argv) 1264static int python_start_script(const char *script, int argc, const char **argv)
1219{ 1265{
1220 struct tables *tables = &tables_global; 1266 struct tables *tables = &tables_global;
1267#if PY_MAJOR_VERSION < 3
1221 const char **command_line; 1268 const char **command_line;
1269#else
1270 wchar_t **command_line;
1271#endif
1222 char buf[PATH_MAX]; 1272 char buf[PATH_MAX];
1223 int i, err = 0; 1273 int i, err = 0;
1224 FILE *fp; 1274 FILE *fp;
1225 1275
1276#if PY_MAJOR_VERSION < 3
1226 command_line = malloc((argc + 1) * sizeof(const char *)); 1277 command_line = malloc((argc + 1) * sizeof(const char *));
1227 command_line[0] = script; 1278 command_line[0] = script;
1228 for (i = 1; i < argc + 1; i++) 1279 for (i = 1; i < argc + 1; i++)
1229 command_line[i] = argv[i - 1]; 1280 command_line[i] = argv[i - 1];
1281#else
1282 command_line = malloc((argc + 1) * sizeof(wchar_t *));
1283 command_line[0] = Py_DecodeLocale(script, NULL);
1284 for (i = 1; i < argc + 1; i++)
1285 command_line[i] = Py_DecodeLocale(argv[i - 1], NULL);
1286#endif
1230 1287
1231 Py_Initialize(); 1288 Py_Initialize();
1232 1289
1290#if PY_MAJOR_VERSION < 3
1233 initperf_trace_context(); 1291 initperf_trace_context();
1234
1235 PySys_SetArgv(argc + 1, (char **)command_line); 1292 PySys_SetArgv(argc + 1, (char **)command_line);
1293#else
1294 PyInit_perf_trace_context();
1295 PySys_SetArgv(argc + 1, command_line);
1296#endif
1236 1297
1237 fp = fopen(script, "r"); 1298 fp = fopen(script, "r");
1238 if (!fp) { 1299 if (!fp) {
@@ -1262,12 +1323,12 @@ static int python_start_script(const char *script, int argc, const char **argv)
1262 goto error; 1323 goto error;
1263 } 1324 }
1264 1325
1265 free(command_line); 1326 _free_command_line(command_line, argc + 1);
1266 1327
1267 return err; 1328 return err;
1268error: 1329error:
1269 Py_Finalize(); 1330 Py_Finalize();
1270 free(command_line); 1331 _free_command_line(command_line, argc + 1);
1271 1332
1272 return err; 1333 return err;
1273} 1334}
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index af415febbc46..001be4f9d3b9 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -1,4 +1,4 @@
1#!/usr/bin/python2 1#!/usr/bin/python
2 2
3from os import getenv 3from os import getenv
4 4
@@ -28,6 +28,8 @@ class install_lib(_install_lib):
28cflags = getenv('CFLAGS', '').split() 28cflags = getenv('CFLAGS', '').split()
29# switch off several checks (need to be at the end of cflags list) 29# switch off several checks (need to be at the end of cflags list)
30cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ] 30cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ]
31if cc != "clang":
32 cflags += ['-Wno-cast-function-type' ]
31 33
32src_perf = getenv('srctree') + '/tools/perf' 34src_perf = getenv('srctree') + '/tools/perf'
33build_lib = getenv('PYTHON_EXTBUILD_LIB') 35build_lib = getenv('PYTHON_EXTBUILD_LIB')
@@ -35,11 +37,11 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP')
35libtraceevent = getenv('LIBTRACEEVENT') 37libtraceevent = getenv('LIBTRACEEVENT')
36libapikfs = getenv('LIBAPI') 38libapikfs = getenv('LIBAPI')
37 39
38ext_sources = [f.strip() for f in file('util/python-ext-sources') 40ext_sources = [f.strip() for f in open('util/python-ext-sources')
39 if len(f.strip()) > 0 and f[0] != '#'] 41 if len(f.strip()) > 0 and f[0] != '#']
40 42
41# use full paths with source files 43# use full paths with source files
42ext_sources = map(lambda x: '%s/%s' % (src_perf, x) , ext_sources) 44ext_sources = list(map(lambda x: '%s/%s' % (src_perf, x) , ext_sources))
43 45
44perf = Extension('perf', 46perf = Extension('perf',
45 sources = ext_sources, 47 sources = ext_sources,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 2da4d0456a03..e8514f651865 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -111,17 +111,20 @@ struct sort_entry sort_thread = {
111 111
112/* --sort comm */ 112/* --sort comm */
113 113
114/*
115 * We can't use pointer comparison in functions below,
116 * because it gives different results based on pointer
117 * values, which could break some sorting assumptions.
118 */
114static int64_t 119static int64_t
115sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 120sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
116{ 121{
117 /* Compare the addr that should be unique among comm */
118 return strcmp(comm__str(right->comm), comm__str(left->comm)); 122 return strcmp(comm__str(right->comm), comm__str(left->comm));
119} 123}
120 124
121static int64_t 125static int64_t
122sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 126sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
123{ 127{
124 /* Compare the addr that should be unique among comm */
125 return strcmp(comm__str(right->comm), comm__str(left->comm)); 128 return strcmp(comm__str(right->comm), comm__str(left->comm));
126} 129}
127 130
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 32235657c1ac..a0061e0b0fad 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -92,7 +92,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
92}; 92};
93#undef ID 93#undef ID
94 94
95void perf_stat_evsel_id_init(struct perf_evsel *evsel) 95static void perf_stat_evsel_id_init(struct perf_evsel *evsel)
96{ 96{
97 struct perf_stat_evsel *ps = evsel->stats; 97 struct perf_stat_evsel *ps = evsel->stats;
98 int i; 98 int i;
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index dbc6f7134f61..8f56ba4fd258 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -90,6 +90,8 @@ struct perf_stat_config {
90 bool scale; 90 bool scale;
91 FILE *output; 91 FILE *output;
92 unsigned int interval; 92 unsigned int interval;
93 unsigned int timeout;
94 int times;
93 struct runtime_stat *stats; 95 struct runtime_stat *stats;
94 int stats_num; 96 int stats_num;
95}; 97};
@@ -126,8 +128,6 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
126#define perf_stat_evsel__is(evsel, id) \ 128#define perf_stat_evsel__is(evsel, id) \
127 __perf_evsel_stat__is(evsel, PERF_STAT_EVSEL_ID__ ## id) 129 __perf_evsel_stat__is(evsel, PERF_STAT_EVSEL_ID__ ## id)
128 130
129void perf_stat_evsel_id_init(struct perf_evsel *evsel);
130
131extern struct runtime_stat rt_stat; 131extern struct runtime_stat rt_stat;
132extern struct stats walltime_nsecs_stats; 132extern struct stats walltime_nsecs_stats;
133 133
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index cc065d4bfafc..62b2dd2253eb 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1582,7 +1582,7 @@ int dso__load(struct dso *dso, struct map *map)
1582 bool next_slot = false; 1582 bool next_slot = false;
1583 bool is_reg; 1583 bool is_reg;
1584 bool nsexit; 1584 bool nsexit;
1585 int sirc; 1585 int sirc = -1;
1586 1586
1587 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1587 enum dso_binary_type symtab_type = binary_type_symtab[i];
1588 1588
@@ -1600,16 +1600,14 @@ int dso__load(struct dso *dso, struct map *map)
1600 nsinfo__mountns_exit(&nsc); 1600 nsinfo__mountns_exit(&nsc);
1601 1601
1602 is_reg = is_regular_file(name); 1602 is_reg = is_regular_file(name);
1603 sirc = symsrc__init(ss, dso, name, symtab_type); 1603 if (is_reg)
1604 sirc = symsrc__init(ss, dso, name, symtab_type);
1604 1605
1605 if (nsexit) 1606 if (nsexit)
1606 nsinfo__mountns_enter(dso->nsinfo, &nsc); 1607 nsinfo__mountns_enter(dso->nsinfo, &nsc);
1607 1608
1608 if (!is_reg || sirc < 0) { 1609 if (!is_reg || sirc < 0)
1609 if (sirc >= 0)
1610 symsrc__destroy(ss);
1611 continue; 1610 continue;
1612 }
1613 1611
1614 if (!syms_ss && symsrc__has_symtab(ss)) { 1612 if (!syms_ss && symsrc__has_symtab(ss)) {
1615 syms_ss = ss; 1613 syms_ss = ss;
@@ -1960,8 +1958,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map)
1960 pr_debug("Using %s for symbols\n", kallsyms_filename); 1958 pr_debug("Using %s for symbols\n", kallsyms_filename);
1961 if (err > 0 && !dso__is_kcore(dso)) { 1959 if (err > 0 && !dso__is_kcore(dso)) {
1962 dso->binary_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; 1960 dso->binary_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
1963 machine__mmap_name(machine, path, sizeof(path)); 1961 dso__set_long_name(dso, machine->mmap_name, false);
1964 dso__set_long_name(dso, strdup(path), true);
1965 map__fixup_start(map); 1962 map__fixup_start(map);
1966 map__fixup_end(map); 1963 map__fixup_end(map);
1967 } 1964 }
@@ -2224,3 +2221,25 @@ int symbol__config_symfs(const struct option *opt __maybe_unused,
2224 free(bf); 2221 free(bf);
2225 return 0; 2222 return 0;
2226} 2223}
2224
2225struct mem_info *mem_info__get(struct mem_info *mi)
2226{
2227 if (mi)
2228 refcount_inc(&mi->refcnt);
2229 return mi;
2230}
2231
2232void mem_info__put(struct mem_info *mi)
2233{
2234 if (mi && refcount_dec_and_test(&mi->refcnt))
2235 free(mi);
2236}
2237
2238struct mem_info *mem_info__new(void)
2239{
2240 struct mem_info *mi = zalloc(sizeof(*mi));
2241
2242 if (mi)
2243 refcount_set(&mi->refcnt, 1);
2244 return mi;
2245}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0563f33c1eb3..70c16741f50a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -200,9 +200,10 @@ struct branch_info {
200}; 200};
201 201
202struct mem_info { 202struct mem_info {
203 struct addr_map_symbol iaddr; 203 struct addr_map_symbol iaddr;
204 struct addr_map_symbol daddr; 204 struct addr_map_symbol daddr;
205 union perf_mem_data_src data_src; 205 union perf_mem_data_src data_src;
206 refcount_t refcnt;
206}; 207};
207 208
208struct addr_location { 209struct addr_location {
@@ -389,4 +390,16 @@ int sdt_notes__get_count(struct list_head *start);
389#define SDT_NOTE_NAME "stapsdt" 390#define SDT_NOTE_NAME "stapsdt"
390#define NR_ADDR 3 391#define NR_ADDR 3
391 392
393struct mem_info *mem_info__new(void);
394struct mem_info *mem_info__get(struct mem_info *mi);
395void mem_info__put(struct mem_info *mi);
396
397static inline void __mem_info__zput(struct mem_info **mi)
398{
399 mem_info__put(*mi);
400 *mi = NULL;
401}
402
403#define mem_info__zput(mi) __mem_info__zput(&mi)
404
392#endif /* __PERF_SYMBOL */ 405#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
index 303bdb84ab5a..895122d638dd 100644
--- a/tools/perf/util/syscalltbl.c
+++ b/tools/perf/util/syscalltbl.c
@@ -30,6 +30,14 @@ static const char **syscalltbl_native = syscalltbl_x86_64;
30#include <asm/syscalls_64.c> 30#include <asm/syscalls_64.c>
31const int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID; 31const int syscalltbl_native_max_id = SYSCALLTBL_S390_64_MAX_ID;
32static const char **syscalltbl_native = syscalltbl_s390_64; 32static const char **syscalltbl_native = syscalltbl_s390_64;
33#elif defined(__powerpc64__)
34#include <asm/syscalls_64.c>
35const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_64_MAX_ID;
36static const char **syscalltbl_native = syscalltbl_powerpc_64;
37#elif defined(__powerpc__)
38#include <asm/syscalls_32.c>
39const int syscalltbl_native_max_id = SYSCALLTBL_POWERPC_32_MAX_ID;
40static const char **syscalltbl_native = syscalltbl_powerpc_32;
33#endif 41#endif
34 42
35struct syscall { 43struct syscall {
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 40cfa36c022a..14d44c3235b8 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -26,7 +26,6 @@ struct thread {
26 pid_t ppid; 26 pid_t ppid;
27 int cpu; 27 int cpu;
28 refcount_t refcnt; 28 refcount_t refcnt;
29 char shortname[3];
30 bool comm_set; 29 bool comm_set;
31 int comm_len; 30 int comm_len;
32 bool dead; /* if set thread has exited */ 31 bool dead; /* if set thread has exited */
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 3e1038f6491c..5d467d8ae9ab 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -32,6 +32,7 @@ static void thread_map__reset(struct thread_map *map, int start, int nr)
32 size_t size = (nr - start) * sizeof(map->map[0]); 32 size_t size = (nr - start) * sizeof(map->map[0]);
33 33
34 memset(&map->map[start], 0, size); 34 memset(&map->map[start], 0, size);
35 map->err_thread = -1;
35} 36}
36 37
37static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) 38static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
@@ -323,7 +324,7 @@ out_free_threads:
323} 324}
324 325
325struct thread_map *thread_map__new_str(const char *pid, const char *tid, 326struct thread_map *thread_map__new_str(const char *pid, const char *tid,
326 uid_t uid, bool per_thread) 327 uid_t uid, bool all_threads)
327{ 328{
328 if (pid) 329 if (pid)
329 return thread_map__new_by_pid_str(pid); 330 return thread_map__new_by_pid_str(pid);
@@ -331,7 +332,7 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid,
331 if (!tid && uid != UINT_MAX) 332 if (!tid && uid != UINT_MAX)
332 return thread_map__new_by_uid(uid); 333 return thread_map__new_by_uid(uid);
333 334
334 if (per_thread) 335 if (all_threads)
335 return thread_map__new_all_cpus(); 336 return thread_map__new_all_cpus();
336 337
337 return thread_map__new_by_tid_str(tid); 338 return thread_map__new_by_tid_str(tid);
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 0a806b99e73c..2f689c90a8c6 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -14,6 +14,7 @@ struct thread_map_data {
14struct thread_map { 14struct thread_map {
15 refcount_t refcnt; 15 refcount_t refcnt;
16 int nr; 16 int nr;
17 int err_thread;
17 struct thread_map_data map[]; 18 struct thread_map_data map[];
18}; 19};
19 20
@@ -31,7 +32,7 @@ struct thread_map *thread_map__get(struct thread_map *map);
31void thread_map__put(struct thread_map *map); 32void thread_map__put(struct thread_map *map);
32 33
33struct thread_map *thread_map__new_str(const char *pid, 34struct thread_map *thread_map__new_str(const char *pid,
34 const char *tid, uid_t uid, bool per_thread); 35 const char *tid, uid_t uid, bool all_threads);
35 36
36struct thread_map *thread_map__new_by_tid_str(const char *tid_str); 37struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
37 38
diff --git a/tools/perf/util/trigger.h b/tools/perf/util/trigger.h
index 370138e7e35c..88223bc7c82b 100644
--- a/tools/perf/util/trigger.h
+++ b/tools/perf/util/trigger.h
@@ -12,7 +12,7 @@
12 * States and transits: 12 * States and transits:
13 * 13 *
14 * 14 *
15 * OFF--(on)--> READY --(hit)--> HIT 15 * OFF--> ON --> READY --(hit)--> HIT
16 * ^ | 16 * ^ |
17 * | (ready) 17 * | (ready)
18 * | | 18 * | |
@@ -27,8 +27,9 @@ struct trigger {
27 volatile enum { 27 volatile enum {
28 TRIGGER_ERROR = -2, 28 TRIGGER_ERROR = -2,
29 TRIGGER_OFF = -1, 29 TRIGGER_OFF = -1,
30 TRIGGER_READY = 0, 30 TRIGGER_ON = 0,
31 TRIGGER_HIT = 1, 31 TRIGGER_READY = 1,
32 TRIGGER_HIT = 2,
32 } state; 33 } state;
33 const char *name; 34 const char *name;
34}; 35};
@@ -50,7 +51,7 @@ static inline bool trigger_is_error(struct trigger *t)
50static inline void trigger_on(struct trigger *t) 51static inline void trigger_on(struct trigger *t)
51{ 52{
52 TRIGGER_WARN_ONCE(t, TRIGGER_OFF); 53 TRIGGER_WARN_ONCE(t, TRIGGER_OFF);
53 t->state = TRIGGER_READY; 54 t->state = TRIGGER_ON;
54} 55}
55 56
56static inline void trigger_ready(struct trigger *t) 57static inline void trigger_ready(struct trigger *t)
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 1e9c974faf67..7bdd239c795c 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -50,7 +50,7 @@ static int __report_module(struct addr_location *al, u64 ip,
50 50
51 if (!mod) 51 if (!mod)
52 mod = dwfl_report_elf(ui->dwfl, dso->short_name, 52 mod = dwfl_report_elf(ui->dwfl, dso->short_name,
53 dso->long_name, -1, al->map->start, 53 (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start,
54 false); 54 false);
55 55
56 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; 56 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
@@ -236,7 +236,8 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
236 if (err) 236 if (err)
237 goto out; 237 goto out;
238 238
239 if (!dwfl_attach_state(ui->dwfl, EM_NONE, thread->tid, &callbacks, ui)) 239 err = !dwfl_attach_state(ui->dwfl, EM_NONE, thread->tid, &callbacks, ui);
240 if (err)
240 goto out; 241 goto out;
241 242
242 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui); 243 err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui);