aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2018-11-20 06:14:08 -0500
committerJani Nikula <jani.nikula@intel.com>2018-11-20 06:14:08 -0500
commit2ac5e38ea4203852d6e99edd3cf11f044b0a409f (patch)
tree1ef02da98d56309368ad2b6a4e492bafe5bb4faf /tools/perf
parentf48cc647f3e196a3179d695d3c2d56c13e9dec98 (diff)
parent9235dd441af43599b9cdcce599a3da4083fcad3c (diff)
Merge drm/drm-next into drm-intel-next-queued
Pull in v4.20-rc3 via drm-next. Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/build-xed.txt19
-rw-r--r--tools/perf/Documentation/intel-pt.txt2
-rw-r--r--tools/perf/Documentation/itrace.txt7
-rw-r--r--tools/perf/Documentation/perf-list.txt1
-rw-r--r--tools/perf/Documentation/perf-script.txt18
-rw-r--r--tools/perf/Documentation/perf-top.txt10
-rw-r--r--tools/perf/Documentation/perf-trace.txt67
-rw-r--r--tools/perf/Makefile.config2
-rw-r--r--tools/perf/Makefile.perf25
-rw-r--r--tools/perf/arch/arm64/annotate/instructions.c59
-rwxr-xr-xtools/perf/arch/arm64/entry/syscalls/mksyscalltbl2
-rw-r--r--tools/perf/arch/powerpc/util/book3s_hv_exits.h1
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c2
-rw-r--r--tools/perf/arch/sparc/Makefile2
-rw-r--r--tools/perf/arch/sparc/annotate/instructions.c169
-rw-r--r--tools/perf/builtin-annotate.c7
-rw-r--r--tools/perf/builtin-inject.c40
-rw-r--r--tools/perf/builtin-record.c84
-rw-r--r--tools/perf/builtin-report.c12
-rw-r--r--tools/perf/builtin-script.c274
-rw-r--r--tools/perf/builtin-stat.c1503
-rw-r--r--tools/perf/builtin-top.c24
-rw-r--r--tools/perf/builtin-trace.c295
-rwxr-xr-xtools/perf/check-headers.sh2
-rw-r--r--tools/perf/command-list.txt1
-rw-r--r--tools/perf/examples/bpf/augmented_raw_syscalls.c131
-rw-r--r--tools/perf/examples/bpf/augmented_syscalls.c154
-rw-r--r--tools/perf/examples/bpf/etcsnoop.c80
-rw-r--r--tools/perf/include/bpf/bpf.h3
-rw-r--r--tools/perf/include/bpf/linux/socket.h24
-rw-r--r--tools/perf/jvmti/jvmti_agent.c49
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json23
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json26
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json191
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json20
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json32
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json50
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json89
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json14
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json29
-rw-r--r--tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json50
-rw-r--r--tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json16
-rw-r--r--tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json16
-rw-r--r--tools/perf/scripts/python/call-graph-from-sql.py339
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py11
-rw-r--r--tools/perf/scripts/python/export-to-sqlite.py8
-rwxr-xr-xtools/perf/scripts/python/exported-sql-viewer.py2615
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/attr/test-record-group-sampling1
-rw-r--r--tools/perf/tests/builtin-test.c10
-rw-r--r--tools/perf/tests/evsel-tp-sched.c4
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh2
-rw-r--r--tools/perf/tests/tests.h4
-rw-r--r--tools/perf/tests/wp.c241
-rw-r--r--tools/perf/trace/beauty/Build2
-rw-r--r--tools/perf/trace/beauty/beauty.h41
-rw-r--r--tools/perf/trace/beauty/clone.c3
-rwxr-xr-xtools/perf/trace/beauty/drm_ioctl.sh1
-rw-r--r--tools/perf/trace/beauty/eventfd.c2
-rw-r--r--tools/perf/trace/beauty/fcntl.c3
-rw-r--r--tools/perf/trace/beauty/flock.c2
-rw-r--r--tools/perf/trace/beauty/futex_op.c2
-rw-r--r--tools/perf/trace/beauty/futex_val3.c2
-rw-r--r--tools/perf/trace/beauty/ioctl.c3
-rw-r--r--tools/perf/trace/beauty/kcmp.c3
-rwxr-xr-xtools/perf/trace/beauty/kcmp_type.sh1
-rwxr-xr-xtools/perf/trace/beauty/kvm_ioctl.sh1
-rwxr-xr-xtools/perf/trace/beauty/madvise_behavior.sh1
-rw-r--r--tools/perf/trace/beauty/mmap.c50
-rwxr-xr-xtools/perf/trace/beauty/mmap_flags.sh32
-rw-r--r--tools/perf/trace/beauty/mode_t.c2
-rw-r--r--tools/perf/trace/beauty/mount_flags.c43
-rwxr-xr-xtools/perf/trace/beauty/mount_flags.sh15
-rw-r--r--tools/perf/trace/beauty/msg_flags.c2
-rw-r--r--tools/perf/trace/beauty/open_flags.c2
-rw-r--r--tools/perf/trace/beauty/perf_event_open.c2
-rwxr-xr-xtools/perf/trace/beauty/perf_ioctl.sh1
-rw-r--r--tools/perf/trace/beauty/pid.c3
-rw-r--r--tools/perf/trace/beauty/pkey_alloc.c30
-rwxr-xr-xtools/perf/trace/beauty/pkey_alloc_access_rights.sh1
-rw-r--r--tools/perf/trace/beauty/prctl.c3
-rwxr-xr-xtools/perf/trace/beauty/prctl_option.sh1
-rw-r--r--tools/perf/trace/beauty/sched_policy.c2
-rw-r--r--tools/perf/trace/beauty/seccomp.c2
-rw-r--r--tools/perf/trace/beauty/signum.c2
-rwxr-xr-xtools/perf/trace/beauty/sndrv_ctl_ioctl.sh1
-rwxr-xr-xtools/perf/trace/beauty/sndrv_pcm_ioctl.sh1
-rw-r--r--tools/perf/trace/beauty/sockaddr.c76
-rw-r--r--tools/perf/trace/beauty/socket.c2
-rwxr-xr-xtools/perf/trace/beauty/socket_ipproto.sh1
-rw-r--r--tools/perf/trace/beauty/socket_type.c2
-rw-r--r--tools/perf/trace/beauty/statx.c3
-rwxr-xr-xtools/perf/trace/beauty/vhost_virtio_ioctl.sh1
-rw-r--r--tools/perf/trace/beauty/waitid_options.c2
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c8
-rw-r--r--tools/perf/util/auxtrace.c47
-rw-r--r--tools/perf/util/auxtrace.h46
-rw-r--r--tools/perf/util/bpf-loader.c2
-rw-r--r--tools/perf/util/cs-etm.c42
-rw-r--r--tools/perf/util/data-convert-bt.c58
-rw-r--r--tools/perf/util/db-export.c22
-rw-r--r--tools/perf/util/env.h1
-rw-r--r--tools/perf/util/event.c23
-rw-r--r--tools/perf/util/evlist.c29
-rw-r--r--tools/perf/util/evlist.h3
-rw-r--r--tools/perf/util/evsel.c70
-rw-r--r--tools/perf/util/evsel.h16
-rw-r--r--tools/perf/util/evsel_fprintf.c2
-rw-r--r--tools/perf/util/genelf.h6
-rw-r--r--tools/perf/util/header.c47
-rw-r--r--tools/perf/util/header.h18
-rw-r--r--tools/perf/util/intel-bts.c20
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c38
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.c5
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-log.h1
-rw-r--r--tools/perf/util/intel-pt.c52
-rw-r--r--tools/perf/util/llvm-utils.c2
-rw-r--r--tools/perf/util/machine.c62
-rw-r--r--tools/perf/util/map.c15
-rw-r--r--tools/perf/util/mmap.c6
-rw-r--r--tools/perf/util/mmap.h17
-rw-r--r--tools/perf/util/ordered-events.c87
-rw-r--r--tools/perf/util/ordered-events.h37
-rw-r--r--tools/perf/util/parse-events.c8
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/parse-events.l1
-rw-r--r--tools/perf/util/pmu.c15
-rw-r--r--tools/perf/util/probe-event.c39
-rw-r--r--tools/perf/util/probe-event.h1
-rw-r--r--tools/perf/util/probe-file.c34
-rw-r--r--tools/perf/util/probe-file.h1
-rw-r--r--tools/perf/util/python.c20
-rw-r--r--tools/perf/util/s390-cpumsf.c94
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c66
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c100
-rw-r--r--tools/perf/util/session.c75
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/setup.py18
-rw-r--r--tools/perf/util/sort.c22
-rw-r--r--tools/perf/util/srcline.c3
-rw-r--r--tools/perf/util/stat-display.c1166
-rw-r--r--tools/perf/util/stat-shadow.c147
-rw-r--r--tools/perf/util/stat.c100
-rw-r--r--tools/perf/util/stat.h77
-rw-r--r--tools/perf/util/strbuf.c10
-rw-r--r--tools/perf/util/symbol-elf.c58
-rw-r--r--tools/perf/util/symbol.h10
-rw-r--r--tools/perf/util/thread-stack.c95
-rw-r--r--tools/perf/util/thread-stack.h2
-rw-r--r--tools/perf/util/thread.c13
-rw-r--r--tools/perf/util/thread.h4
-rw-r--r--tools/perf/util/tool.h7
-rw-r--r--tools/perf/util/trace-event-info.c2
-rw-r--r--tools/perf/util/trace-event-parse.c44
-rw-r--r--tools/perf/util/trace-event-read.c15
-rw-r--r--tools/perf/util/trace-event.c8
-rw-r--r--tools/perf/util/trace-event.h21
-rw-r--r--tools/perf/util/unwind-libdw.c4
-rw-r--r--tools/perf/util/util.c2
-rw-r--r--tools/perf/util/util.h2
163 files changed, 7641 insertions, 2645 deletions
diff --git a/tools/perf/Documentation/build-xed.txt b/tools/perf/Documentation/build-xed.txt
new file mode 100644
index 000000000000..6222c1e7231f
--- /dev/null
+++ b/tools/perf/Documentation/build-xed.txt
@@ -0,0 +1,19 @@
1
2For --xed the xed tool is needed. Here is how to install it:
3
4 $ git clone https://github.com/intelxed/mbuild.git mbuild
5 $ git clone https://github.com/intelxed/xed
6 $ cd xed
7 $ ./mfile.py --share
8 $ ./mfile.py examples
9 $ sudo ./mfile.py --prefix=/usr/local install
10 $ sudo ldconfig
11 $ sudo cp obj/examples/xed /usr/local/bin
12
13Basic xed testing:
14
15 $ xed | head -3
16 ERROR: required argument(s) were missing
17 Copyright (C) 2017, Intel Corporation. All rights reserved.
18 XED version: [v10.0-328-g7d62c8c49b7b]
19 $
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index 76971d2e4164..115eaacc455f 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -106,7 +106,7 @@ in transaction, respectively.
106While it is possible to create scripts to analyze the data, an alternative 106While it is possible to create scripts to analyze the data, an alternative
107approach is available to export the data to a sqlite or postgresql database. 107approach is available to export the data to a sqlite or postgresql database.
108Refer to script export-to-sqlite.py or export-to-postgresql.py for more details, 108Refer to script export-to-sqlite.py or export-to-postgresql.py for more details,
109and to script call-graph-from-sql.py for an example of using the database. 109and to script exported-sql-viewer.py for an example of using the database.
110 110
111There is also script intel-pt-events.py which provides an example of how to 111There is also script intel-pt-events.py which provides an example of how to
112unpack the raw data for power events and PTWRITE. 112unpack the raw data for power events and PTWRITE.
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index a3abe04c779d..c2182cbabde3 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -11,10 +11,11 @@
11 l synthesize last branch entries (use with i or x) 11 l synthesize last branch entries (use with i or x)
12 s skip initial number of events 12 s skip initial number of events
13 13
14 The default is all events i.e. the same as --itrace=ibxwpe 14 The default is all events i.e. the same as --itrace=ibxwpe,
15 except for perf script where it is --itrace=ce
15 16
16 In addition, the period (default 100000) for instructions events 17 In addition, the period (default 100000, except for perf script where it is 1)
17 can be specified in units of: 18 for instructions events can be specified in units of:
18 19
19 i instructions 20 i instructions
20 t ticks 21 t ticks
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 236b9b97dfdb..667c14e56031 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -55,7 +55,6 @@ counted. The following modifiers exist:
55 S - read sample value (PERF_SAMPLE_READ) 55 S - read sample value (PERF_SAMPLE_READ)
56 D - pin the event to the PMU 56 D - pin the event to the PMU
57 W - group is weak and will fallback to non-group if not schedulable, 57 W - group is weak and will fallback to non-group if not schedulable,
58 only supported in 'perf stat' for now.
59 58
60The 'p' modifier can be used for specifying how precise the instruction 59The 'p' modifier can be used for specifying how precise the instruction
61address should be. The 'p' modifier can be specified multiple times: 60address should be. The 'p' modifier can be specified multiple times:
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index afdafe2110a1..a2b37ce48094 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -383,6 +383,24 @@ include::itrace.txt[]
383 will be printed. Each entry has function name and file/line. Enabled by 383 will be printed. Each entry has function name and file/line. Enabled by
384 default, disable with --no-inline. 384 default, disable with --no-inline.
385 385
386--insn-trace::
387 Show instruction stream for intel_pt traces. Combine with --xed to
388 show disassembly.
389
390--xed::
391 Run xed disassembler on output. Requires installing the xed disassembler.
392
393--call-trace::
394 Show call stream for intel_pt traces. The CPUs are interleaved, but
395 can be filtered with -C.
396
397--call-ret-trace::
398 Show call and return stream for intel_pt traces.
399
400--graph-function::
401 For itrace only show specified functions and their callees for
402 itrace. Multiple functions can be separated by comma.
403
386SEE ALSO 404SEE ALSO
387-------- 405--------
388linkperf:perf-record[1], linkperf:perf-script-perl[1], 406linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 114fda12aa49..808b664343c9 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -242,6 +242,16 @@ Default is to monitor all CPUS.
242--hierarchy:: 242--hierarchy::
243 Enable hierarchy output. 243 Enable hierarchy output.
244 244
245--overwrite::
246 Enable this to use just the most recent records, which helps in high core count
247 machines such as Knights Landing/Mill, but right now is disabled by default as
248 the pausing used in this technique is leading to loss of metadata events such
249 as PERF_RECORD_MMAP which makes 'perf top' unable to resolve samples, leading
250 to lots of unknown samples appearing on the UI. Enable this if you are in such
251 machines and profiling a workload that doesn't creates short lived threads and/or
252 doesn't uses many executable mmap operations. Work is being planed to solve
253 this situation, till then, this will remain disabled by default.
254
245--force:: 255--force::
246 Don't do ownership validation. 256 Don't do ownership validation.
247 257
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 115db9e06ecd..e113450503d2 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -171,6 +171,11 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
171--kernel-syscall-graph:: 171--kernel-syscall-graph::
172 Show the kernel callchains on the syscall exit path. 172 Show the kernel callchains on the syscall exit path.
173 173
174--max-events=N::
175 Stop after processing N events. Note that strace-like events are considered
176 only at exit time or when a syscall is interrupted, i.e. in those cases this
177 option is equivalent to the number of lines printed.
178
174--max-stack:: 179--max-stack::
175 Set the stack depth limit when parsing the callchain, anything 180 Set the stack depth limit when parsing the callchain, anything
176 beyond the specified depth will be ignored. Note that at this point 181 beyond the specified depth will be ignored. Note that at this point
@@ -238,6 +243,68 @@ Trace syscalls, major and minor pagefaults:
238 As you can see, there was major pagefault in python process, from 243 As you can see, there was major pagefault in python process, from
239 CRYPTO_push_info_ routine which faulted somewhere in libcrypto.so. 244 CRYPTO_push_info_ routine which faulted somewhere in libcrypto.so.
240 245
246Trace the first 4 open, openat or open_by_handle_at syscalls (in the future more syscalls may match here):
247
248 $ perf trace -e open* --max-events 4
249 [root@jouet perf]# trace -e open* --max-events 4
250 2272.992 ( 0.037 ms): gnome-shell/1370 openat(dfd: CWD, filename: /proc/self/stat) = 31
251 2277.481 ( 0.139 ms): gnome-shell/3039 openat(dfd: CWD, filename: /proc/self/stat) = 65
252 3026.398 ( 0.076 ms): gnome-shell/3039 openat(dfd: CWD, filename: /proc/self/stat) = 65
253 4294.665 ( 0.015 ms): sed/15879 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC) = 3
254 $
255
256Trace the first minor page fault when running a workload:
257
258 # perf trace -F min --max-stack=7 --max-events 1 sleep 1
259 0.000 ( 0.000 ms): sleep/18006 minfault [__clear_user+0x1a] => 0x5626efa56080 (?k)
260 __clear_user ([kernel.kallsyms])
261 load_elf_binary ([kernel.kallsyms])
262 search_binary_handler ([kernel.kallsyms])
263 __do_execve_file.isra.33 ([kernel.kallsyms])
264 __x64_sys_execve ([kernel.kallsyms])
265 do_syscall_64 ([kernel.kallsyms])
266 entry_SYSCALL_64 ([kernel.kallsyms])
267 #
268
269Trace the next min page page fault to take place on the first CPU:
270
271 # perf trace -F min --call-graph=dwarf --max-events 1 --cpu 0
272 0.000 ( 0.000 ms): Web Content/17136 minfault [js::gc::Chunk::fetchNextDecommittedArena+0x4b] => 0x7fbe6181b000 (?.)
273 js::gc::FreeSpan::initAsEmpty (inlined)
274 js::gc::Arena::setAsNotAllocated (inlined)
275 js::gc::Chunk::fetchNextDecommittedArena (/usr/lib64/firefox/libxul.so)
276 js::gc::Chunk::allocateArena (/usr/lib64/firefox/libxul.so)
277 js::gc::GCRuntime::allocateArena (/usr/lib64/firefox/libxul.so)
278 js::gc::ArenaLists::allocateFromArena (/usr/lib64/firefox/libxul.so)
279 js::gc::GCRuntime::tryNewTenuredThing<JSString, (js::AllowGC)1> (inlined)
280 js::AllocateString<JSString, (js::AllowGC)1> (/usr/lib64/firefox/libxul.so)
281 js::Allocate<JSThinInlineString, (js::AllowGC)1> (inlined)
282 JSThinInlineString::new_<(js::AllowGC)1> (inlined)
283 AllocateInlineString<(js::AllowGC)1, unsigned char> (inlined)
284 js::ConcatStrings<(js::AllowGC)1> (/usr/lib64/firefox/libxul.so)
285 [0x18b26e6bc2bd] (/tmp/perf-17136.map)
286 #
287
288Trace the next two sched:sched_switch events, four block:*_plug events, the
289next block:*_unplug and the next three net:*dev_queue events, this last one
290with a backtrace of at most 16 entries, system wide:
291
292 # perf trace -e sched:*switch/nr=2/,block:*_plug/nr=4/,block:*_unplug/nr=1/,net:*dev_queue/nr=3,max-stack=16/
293 0.000 :0/0 sched:sched_switch:swapper/2:0 [120] S ==> rcu_sched:10 [120]
294 0.015 rcu_sched/10 sched:sched_switch:rcu_sched:10 [120] R ==> swapper/2:0 [120]
295 254.198 irq/50-iwlwifi/680 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051f600 len=66
296 __dev_queue_xmit ([kernel.kallsyms])
297 273.977 :0/0 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051f600 len=78
298 __dev_queue_xmit ([kernel.kallsyms])
299 274.007 :0/0 net:net_dev_queue:dev=wlp3s0 skbaddr=0xffff93498051ff00 len=78
300 __dev_queue_xmit ([kernel.kallsyms])
301 2930.140 kworker/u16:58/2722 block:block_plug:[kworker/u16:58]
302 2930.162 kworker/u16:58/2722 block:block_unplug:[kworker/u16:58] 1
303 4466.094 jbd2/dm-2-8/748 block:block_plug:[jbd2/dm-2-8]
304 8050.123 kworker/u16:30/2694 block:block_plug:[kworker/u16:30]
305 8050.271 kworker/u16:30/2694 block:block_plug:[kworker/u16:30]
306 #
307
241SEE ALSO 308SEE ALSO
242-------- 309--------
243linkperf:perf-record[1], linkperf:perf-script[1] 310linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index f6d1a03c7523..e30d20fb482d 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -833,7 +833,7 @@ ifndef NO_JVMTI
833 JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}') 833 JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | awk '{print $$3}')
834 else 834 else
835 ifneq (,$(wildcard /usr/sbin/alternatives)) 835 ifneq (,$(wildcard /usr/sbin/alternatives))
836 JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g') 836 JDIR=$(shell /usr/sbin/alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
837 endif 837 endif
838 endif 838 endif
839 ifndef JDIR 839 ifndef JDIR
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 5224ade3d5af..d95655489f7e 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -1,4 +1,5 @@
1include ../scripts/Makefile.include 1include ../scripts/Makefile.include
2include ../scripts/Makefile.arch
2 3
3# The default target of this Makefile is... 4# The default target of this Makefile is...
4all: 5all:
@@ -385,6 +386,8 @@ export INSTALL SHELL_PATH
385SHELL = $(SHELL_PATH) 386SHELL = $(SHELL_PATH)
386 387
387linux_uapi_dir := $(srctree)/tools/include/uapi/linux 388linux_uapi_dir := $(srctree)/tools/include/uapi/linux
389asm_generic_uapi_dir := $(srctree)/tools/include/uapi/asm-generic
390arch_asm_uapi_dir := $(srctree)/tools/arch/$(SRCARCH)/include/uapi/asm/
388 391
389beauty_outdir := $(OUTPUT)trace/beauty/generated 392beauty_outdir := $(OUTPUT)trace/beauty/generated
390beauty_ioctl_outdir := $(beauty_outdir)/ioctl 393beauty_ioctl_outdir := $(beauty_outdir)/ioctl
@@ -460,6 +463,18 @@ madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh
460$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) 463$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl)
461 $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ 464 $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@
462 465
466mmap_flags_array := $(beauty_outdir)/mmap_flags_array.c
467mmap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mmap_flags.sh
468
469$(mmap_flags_array): $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(arch_asm_uapi_dir)/mman.h $(mmap_flags_tbl)
470 $(Q)$(SHELL) '$(mmap_flags_tbl)' $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@
471
472mount_flags_array := $(beauty_outdir)/mount_flags_array.c
473mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh
474
475$(mount_flags_array): $(linux_uapi_dir)/fs.h $(mount_flags_tbl)
476 $(Q)$(SHELL) '$(mount_flags_tbl)' $(linux_uapi_dir) > $@
477
463prctl_option_array := $(beauty_outdir)/prctl_option_array.c 478prctl_option_array := $(beauty_outdir)/prctl_option_array.c
464prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/ 479prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/
465prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh 480prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh
@@ -577,6 +592,8 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc
577 $(socket_ipproto_array) \ 592 $(socket_ipproto_array) \
578 $(vhost_virtio_ioctl_array) \ 593 $(vhost_virtio_ioctl_array) \
579 $(madvise_behavior_array) \ 594 $(madvise_behavior_array) \
595 $(mmap_flags_array) \
596 $(mount_flags_array) \
580 $(perf_ioctl_array) \ 597 $(perf_ioctl_array) \
581 $(prctl_option_array) \ 598 $(prctl_option_array) \
582 $(arch_errno_name_array) 599 $(arch_errno_name_array)
@@ -635,7 +652,7 @@ $(LIBPERF_IN): prepare FORCE
635$(LIB_FILE): $(LIBPERF_IN) 652$(LIB_FILE): $(LIBPERF_IN)
636 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS) 653 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS)
637 654
638LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 655LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 'EXTRA_CFLAGS=$(EXTRA_CFLAGS)' 'LDFLAGS=$(LDFLAGS)'
639 656
640$(LIBTRACEEVENT): FORCE 657$(LIBTRACEEVENT): FORCE
641 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a 658 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a
@@ -779,7 +796,9 @@ endif
779ifndef NO_LIBBPF 796ifndef NO_LIBBPF
780 $(call QUIET_INSTALL, bpf-headers) \ 797 $(call QUIET_INSTALL, bpf-headers) \
781 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \ 798 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
782 $(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf' 799 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'; \
800 $(INSTALL) include/bpf/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
801 $(INSTALL) include/bpf/linux/*.h -t '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf/linux'
783 $(call QUIET_INSTALL, bpf-examples) \ 802 $(call QUIET_INSTALL, bpf-examples) \
784 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'; \ 803 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'; \
785 $(INSTALL) examples/bpf/*.c -t '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf' 804 $(INSTALL) examples/bpf/*.c -t '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
@@ -861,6 +880,8 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
861 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \ 880 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
862 $(OUTPUT)pmu-events/pmu-events.c \ 881 $(OUTPUT)pmu-events/pmu-events.c \
863 $(OUTPUT)$(madvise_behavior_array) \ 882 $(OUTPUT)$(madvise_behavior_array) \
883 $(OUTPUT)$(mmap_flags_array) \
884 $(OUTPUT)$(mount_flags_array) \
864 $(OUTPUT)$(drm_ioctl_array) \ 885 $(OUTPUT)$(drm_ioctl_array) \
865 $(OUTPUT)$(pkey_alloc_access_rights_array) \ 886 $(OUTPUT)$(pkey_alloc_access_rights_array) \
866 $(OUTPUT)$(sndrv_ctl_ioctl_array) \ 887 $(OUTPUT)$(sndrv_ctl_ioctl_array) \
diff --git a/tools/perf/arch/arm64/annotate/instructions.c b/tools/perf/arch/arm64/annotate/instructions.c
index 6688977e4ac7..76c6345a57d5 100644
--- a/tools/perf/arch/arm64/annotate/instructions.c
+++ b/tools/perf/arch/arm64/annotate/instructions.c
@@ -8,6 +8,63 @@ struct arm64_annotate {
8 jump_insn; 8 jump_insn;
9}; 9};
10 10
11static int arm64_mov__parse(struct arch *arch __maybe_unused,
12 struct ins_operands *ops,
13 struct map_symbol *ms __maybe_unused)
14{
15 char *s = strchr(ops->raw, ','), *target, *endptr;
16
17 if (s == NULL)
18 return -1;
19
20 *s = '\0';
21 ops->source.raw = strdup(ops->raw);
22 *s = ',';
23
24 if (ops->source.raw == NULL)
25 return -1;
26
27 target = ++s;
28 ops->target.raw = strdup(target);
29 if (ops->target.raw == NULL)
30 goto out_free_source;
31
32 ops->target.addr = strtoull(target, &endptr, 16);
33 if (endptr == target)
34 goto out_free_target;
35
36 s = strchr(endptr, '<');
37 if (s == NULL)
38 goto out_free_target;
39 endptr = strchr(s + 1, '>');
40 if (endptr == NULL)
41 goto out_free_target;
42
43 *endptr = '\0';
44 *s = ' ';
45 ops->target.name = strdup(s);
46 *s = '<';
47 *endptr = '>';
48 if (ops->target.name == NULL)
49 goto out_free_target;
50
51 return 0;
52
53out_free_target:
54 zfree(&ops->target.raw);
55out_free_source:
56 zfree(&ops->source.raw);
57 return -1;
58}
59
60static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
61 struct ins_operands *ops);
62
63static struct ins_ops arm64_mov_ops = {
64 .parse = arm64_mov__parse,
65 .scnprintf = mov__scnprintf,
66};
67
11static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name) 68static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const char *name)
12{ 69{
13 struct arm64_annotate *arm = arch->priv; 70 struct arm64_annotate *arm = arch->priv;
@@ -21,7 +78,7 @@ static struct ins_ops *arm64__associate_instruction_ops(struct arch *arch, const
21 else if (!strcmp(name, "ret")) 78 else if (!strcmp(name, "ret"))
22 ops = &ret_ops; 79 ops = &ret_ops;
23 else 80 else
24 return NULL; 81 ops = &arm64_mov_ops;
25 82
26 arch__associate_ins_ops(arch, name, ops); 83 arch__associate_ins_ops(arch, name, ops);
27 return ops; 84 return ops;
diff --git a/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl b/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
index 2dbb8cade048..c88fd32563eb 100755
--- a/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
+++ b/tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
@@ -23,7 +23,7 @@ create_table_from_c()
23{ 23{
24 local sc nr last_sc 24 local sc nr last_sc
25 25
26 create_table_exe=`mktemp /tmp/create-table-XXXXXX` 26 create_table_exe=`mktemp ${TMPDIR:-/tmp}/create-table-XXXXXX`
27 27
28 { 28 {
29 29
diff --git a/tools/perf/arch/powerpc/util/book3s_hv_exits.h b/tools/perf/arch/powerpc/util/book3s_hv_exits.h
index 853b95d1e139..2011376c7ab5 100644
--- a/tools/perf/arch/powerpc/util/book3s_hv_exits.h
+++ b/tools/perf/arch/powerpc/util/book3s_hv_exits.h
@@ -15,7 +15,6 @@
15 {0x400, "INST_STORAGE"}, \ 15 {0x400, "INST_STORAGE"}, \
16 {0x480, "INST_SEGMENT"}, \ 16 {0x480, "INST_SEGMENT"}, \
17 {0x500, "EXTERNAL"}, \ 17 {0x500, "EXTERNAL"}, \
18 {0x501, "EXTERNAL_LEVEL"}, \
19 {0x502, "EXTERNAL_HV"}, \ 18 {0x502, "EXTERNAL_HV"}, \
20 {0x600, "ALIGNMENT"}, \ 19 {0x600, "ALIGNMENT"}, \
21 {0x700, "PROGRAM"}, \ 20 {0x700, "PROGRAM"}, \
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index cee4e2f7c057..de0dd66dbb48 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -100,8 +100,6 @@ out_free_source:
100 return -1; 100 return -1;
101} 101}
102 102
103static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
104 struct ins_operands *ops);
105 103
106static struct ins_ops s390_mov_ops = { 104static struct ins_ops s390_mov_ops = {
107 .parse = s390_mov__parse, 105 .parse = s390_mov__parse,
diff --git a/tools/perf/arch/sparc/Makefile b/tools/perf/arch/sparc/Makefile
index 7fbca175099e..275dea7ff59a 100644
--- a/tools/perf/arch/sparc/Makefile
+++ b/tools/perf/arch/sparc/Makefile
@@ -1,3 +1,5 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3endif 3endif
4
5PERF_HAVE_JITDUMP := 1
diff --git a/tools/perf/arch/sparc/annotate/instructions.c b/tools/perf/arch/sparc/annotate/instructions.c
new file mode 100644
index 000000000000..2614c010c235
--- /dev/null
+++ b/tools/perf/arch/sparc/annotate/instructions.c
@@ -0,0 +1,169 @@
1// SPDX-License-Identifier: GPL-2.0
2
3static int is_branch_cond(const char *cond)
4{
5 if (cond[0] == '\0')
6 return 1;
7
8 if (cond[0] == 'a' && cond[1] == '\0')
9 return 1;
10
11 if (cond[0] == 'c' &&
12 (cond[1] == 'c' || cond[1] == 's') &&
13 cond[2] == '\0')
14 return 1;
15
16 if (cond[0] == 'e' &&
17 (cond[1] == '\0' ||
18 (cond[1] == 'q' && cond[2] == '\0')))
19 return 1;
20
21 if (cond[0] == 'g' &&
22 (cond[1] == '\0' ||
23 (cond[1] == 't' && cond[2] == '\0') ||
24 (cond[1] == 'e' && cond[2] == '\0') ||
25 (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
26 return 1;
27
28 if (cond[0] == 'l' &&
29 (cond[1] == '\0' ||
30 (cond[1] == 't' && cond[2] == '\0') ||
31 (cond[1] == 'u' && cond[2] == '\0') ||
32 (cond[1] == 'e' && cond[2] == '\0') ||
33 (cond[1] == 'e' && cond[2] == 'u' && cond[3] == '\0')))
34 return 1;
35
36 if (cond[0] == 'n' &&
37 (cond[1] == '\0' ||
38 (cond[1] == 'e' && cond[2] == '\0') ||
39 (cond[1] == 'z' && cond[2] == '\0') ||
40 (cond[1] == 'e' && cond[2] == 'g' && cond[3] == '\0')))
41 return 1;
42
43 if (cond[0] == 'b' &&
44 cond[1] == 'p' &&
45 cond[2] == 'o' &&
46 cond[3] == 's' &&
47 cond[4] == '\0')
48 return 1;
49
50 if (cond[0] == 'v' &&
51 (cond[1] == 'c' || cond[1] == 's') &&
52 cond[2] == '\0')
53 return 1;
54
55 if (cond[0] == 'b' &&
56 cond[1] == 'z' &&
57 cond[2] == '\0')
58 return 1;
59
60 return 0;
61}
62
63static int is_branch_reg_cond(const char *cond)
64{
65 if ((cond[0] == 'n' || cond[0] == 'l') &&
66 cond[1] == 'z' &&
67 cond[2] == '\0')
68 return 1;
69
70 if (cond[0] == 'z' &&
71 cond[1] == '\0')
72 return 1;
73
74 if ((cond[0] == 'g' || cond[0] == 'l') &&
75 cond[1] == 'e' &&
76 cond[2] == 'z' &&
77 cond[3] == '\0')
78 return 1;
79
80 if (cond[0] == 'g' &&
81 cond[1] == 'z' &&
82 cond[2] == '\0')
83 return 1;
84
85 return 0;
86}
87
88static int is_branch_float_cond(const char *cond)
89{
90 if (cond[0] == '\0')
91 return 1;
92
93 if ((cond[0] == 'a' || cond[0] == 'e' ||
94 cond[0] == 'z' || cond[0] == 'g' ||
95 cond[0] == 'l' || cond[0] == 'n' ||
96 cond[0] == 'o' || cond[0] == 'u') &&
97 cond[1] == '\0')
98 return 1;
99
100 if (((cond[0] == 'g' && cond[1] == 'e') ||
101 (cond[0] == 'l' && (cond[1] == 'e' ||
102 cond[1] == 'g')) ||
103 (cond[0] == 'n' && (cond[1] == 'e' ||
104 cond[1] == 'z')) ||
105 (cond[0] == 'u' && (cond[1] == 'e' ||
106 cond[1] == 'g' ||
107 cond[1] == 'l'))) &&
108 cond[2] == '\0')
109 return 1;
110
111 if (cond[0] == 'u' &&
112 (cond[1] == 'g' || cond[1] == 'l') &&
113 cond[2] == 'e' &&
114 cond[3] == '\0')
115 return 1;
116
117 return 0;
118}
119
120static struct ins_ops *sparc__associate_instruction_ops(struct arch *arch, const char *name)
121{
122 struct ins_ops *ops = NULL;
123
124 if (!strcmp(name, "call") ||
125 !strcmp(name, "jmp") ||
126 !strcmp(name, "jmpl")) {
127 ops = &call_ops;
128 } else if (!strcmp(name, "ret") ||
129 !strcmp(name, "retl") ||
130 !strcmp(name, "return")) {
131 ops = &ret_ops;
132 } else if (!strcmp(name, "mov")) {
133 ops = &mov_ops;
134 } else {
135 if (name[0] == 'c' &&
136 (name[1] == 'w' || name[1] == 'x'))
137 name += 2;
138
139 if (name[0] == 'b') {
140 const char *cond = name + 1;
141
142 if (cond[0] == 'r') {
143 if (is_branch_reg_cond(cond + 1))
144 ops = &jump_ops;
145 } else if (is_branch_cond(cond)) {
146 ops = &jump_ops;
147 }
148 } else if (name[0] == 'f' && name[1] == 'b') {
149 if (is_branch_float_cond(name + 2))
150 ops = &jump_ops;
151 }
152 }
153
154 if (ops)
155 arch__associate_ins_ops(arch, name, ops);
156
157 return ops;
158}
159
160static int sparc__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
161{
162 if (!arch->initialized) {
163 arch->initialized = true;
164 arch->associate_instruction_ops = sparc__associate_instruction_ops;
165 arch->objdump.comment_char = '#';
166 }
167
168 return 0;
169}
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 830481b8db26..93d679eaf1f4 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -283,12 +283,11 @@ out_put:
283 return ret; 283 return ret;
284} 284}
285 285
286static int process_feature_event(struct perf_tool *tool, 286static int process_feature_event(struct perf_session *session,
287 union perf_event *event, 287 union perf_event *event)
288 struct perf_session *session)
289{ 288{
290 if (event->feat.feat_id < HEADER_LAST_FEATURE) 289 if (event->feat.feat_id < HEADER_LAST_FEATURE)
291 return perf_event__process_feature(tool, event, session); 290 return perf_event__process_feature(session, event);
292 return 0; 291 return 0;
293} 292}
294 293
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index a3b346359ba0..eda41673c4f3 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -86,12 +86,10 @@ static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused,
86} 86}
87#endif 87#endif
88 88
89static int perf_event__repipe_op2_synth(struct perf_tool *tool, 89static int perf_event__repipe_op2_synth(struct perf_session *session,
90 union perf_event *event, 90 union perf_event *event)
91 struct perf_session *session
92 __maybe_unused)
93{ 91{
94 return perf_event__repipe_synth(tool, event); 92 return perf_event__repipe_synth(session->tool, event);
95} 93}
96 94
97static int perf_event__repipe_attr(struct perf_tool *tool, 95static int perf_event__repipe_attr(struct perf_tool *tool,
@@ -133,10 +131,10 @@ static int copy_bytes(struct perf_inject *inject, int fd, off_t size)
133 return 0; 131 return 0;
134} 132}
135 133
136static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, 134static s64 perf_event__repipe_auxtrace(struct perf_session *session,
137 union perf_event *event, 135 union perf_event *event)
138 struct perf_session *session)
139{ 136{
137 struct perf_tool *tool = session->tool;
140 struct perf_inject *inject = container_of(tool, struct perf_inject, 138 struct perf_inject *inject = container_of(tool, struct perf_inject,
141 tool); 139 tool);
142 int ret; 140 int ret;
@@ -174,9 +172,8 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool,
174#else 172#else
175 173
176static s64 174static s64
177perf_event__repipe_auxtrace(struct perf_tool *tool __maybe_unused, 175perf_event__repipe_auxtrace(struct perf_session *session __maybe_unused,
178 union perf_event *event __maybe_unused, 176 union perf_event *event __maybe_unused)
179 struct perf_session *session __maybe_unused)
180{ 177{
181 pr_err("AUX area tracing not supported\n"); 178 pr_err("AUX area tracing not supported\n");
182 return -EINVAL; 179 return -EINVAL;
@@ -362,26 +359,24 @@ static int perf_event__repipe_exit(struct perf_tool *tool,
362 return err; 359 return err;
363} 360}
364 361
365static int perf_event__repipe_tracing_data(struct perf_tool *tool, 362static int perf_event__repipe_tracing_data(struct perf_session *session,
366 union perf_event *event, 363 union perf_event *event)
367 struct perf_session *session)
368{ 364{
369 int err; 365 int err;
370 366
371 perf_event__repipe_synth(tool, event); 367 perf_event__repipe_synth(session->tool, event);
372 err = perf_event__process_tracing_data(tool, event, session); 368 err = perf_event__process_tracing_data(session, event);
373 369
374 return err; 370 return err;
375} 371}
376 372
377static int perf_event__repipe_id_index(struct perf_tool *tool, 373static int perf_event__repipe_id_index(struct perf_session *session,
378 union perf_event *event, 374 union perf_event *event)
379 struct perf_session *session)
380{ 375{
381 int err; 376 int err;
382 377
383 perf_event__repipe_synth(tool, event); 378 perf_event__repipe_synth(session->tool, event);
384 err = perf_event__process_id_index(tool, event, session); 379 err = perf_event__process_id_index(session, event);
385 380
386 return err; 381 return err;
387} 382}
@@ -803,7 +798,8 @@ int cmd_inject(int argc, const char **argv)
803 "kallsyms pathname"), 798 "kallsyms pathname"),
804 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), 799 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
805 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, 800 OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts,
806 NULL, "opts", "Instruction Tracing options", 801 NULL, "opts", "Instruction Tracing options\n"
802 ITRACE_HELP,
807 itrace_parse_synth_opts), 803 itrace_parse_synth_opts),
808 OPT_BOOLEAN(0, "strip", &inject.strip, 804 OPT_BOOLEAN(0, "strip", &inject.strip,
809 "strip non-synthesized events (use with --itrace)"), 805 "strip non-synthesized events (use with --itrace)"),
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 22ebeb92ac51..488779bc4c8d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -106,9 +106,12 @@ static bool switch_output_time(struct record *rec)
106 trigger_is_ready(&switch_output_trigger); 106 trigger_is_ready(&switch_output_trigger);
107} 107}
108 108
109static int record__write(struct record *rec, void *bf, size_t size) 109static int record__write(struct record *rec, struct perf_mmap *map __maybe_unused,
110 void *bf, size_t size)
110{ 111{
111 if (perf_data__write(rec->session->data, bf, size) < 0) { 112 struct perf_data_file *file = &rec->session->data->file;
113
114 if (perf_data_file__write(file, bf, size) < 0) {
112 pr_err("failed to write perf data, error: %m\n"); 115 pr_err("failed to write perf data, error: %m\n");
113 return -1; 116 return -1;
114 } 117 }
@@ -127,15 +130,15 @@ static int process_synthesized_event(struct perf_tool *tool,
127 struct machine *machine __maybe_unused) 130 struct machine *machine __maybe_unused)
128{ 131{
129 struct record *rec = container_of(tool, struct record, tool); 132 struct record *rec = container_of(tool, struct record, tool);
130 return record__write(rec, event, event->header.size); 133 return record__write(rec, NULL, event, event->header.size);
131} 134}
132 135
133static int record__pushfn(void *to, void *bf, size_t size) 136static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size)
134{ 137{
135 struct record *rec = to; 138 struct record *rec = to;
136 139
137 rec->samples++; 140 rec->samples++;
138 return record__write(rec, bf, size); 141 return record__write(rec, map, bf, size);
139} 142}
140 143
141static volatile int done; 144static volatile int done;
@@ -170,6 +173,7 @@ static void record__sig_exit(void)
170#ifdef HAVE_AUXTRACE_SUPPORT 173#ifdef HAVE_AUXTRACE_SUPPORT
171 174
172static int record__process_auxtrace(struct perf_tool *tool, 175static int record__process_auxtrace(struct perf_tool *tool,
176 struct perf_mmap *map,
173 union perf_event *event, void *data1, 177 union perf_event *event, void *data1,
174 size_t len1, void *data2, size_t len2) 178 size_t len1, void *data2, size_t len2)
175{ 179{
@@ -197,21 +201,21 @@ static int record__process_auxtrace(struct perf_tool *tool,
197 if (padding) 201 if (padding)
198 padding = 8 - padding; 202 padding = 8 - padding;
199 203
200 record__write(rec, event, event->header.size); 204 record__write(rec, map, event, event->header.size);
201 record__write(rec, data1, len1); 205 record__write(rec, map, data1, len1);
202 if (len2) 206 if (len2)
203 record__write(rec, data2, len2); 207 record__write(rec, map, data2, len2);
204 record__write(rec, &pad, padding); 208 record__write(rec, map, &pad, padding);
205 209
206 return 0; 210 return 0;
207} 211}
208 212
209static int record__auxtrace_mmap_read(struct record *rec, 213static int record__auxtrace_mmap_read(struct record *rec,
210 struct auxtrace_mmap *mm) 214 struct perf_mmap *map)
211{ 215{
212 int ret; 216 int ret;
213 217
214 ret = auxtrace_mmap__read(mm, rec->itr, &rec->tool, 218 ret = auxtrace_mmap__read(map, rec->itr, &rec->tool,
215 record__process_auxtrace); 219 record__process_auxtrace);
216 if (ret < 0) 220 if (ret < 0)
217 return ret; 221 return ret;
@@ -223,11 +227,11 @@ static int record__auxtrace_mmap_read(struct record *rec,
223} 227}
224 228
225static int record__auxtrace_mmap_read_snapshot(struct record *rec, 229static int record__auxtrace_mmap_read_snapshot(struct record *rec,
226 struct auxtrace_mmap *mm) 230 struct perf_mmap *map)
227{ 231{
228 int ret; 232 int ret;
229 233
230 ret = auxtrace_mmap__read_snapshot(mm, rec->itr, &rec->tool, 234 ret = auxtrace_mmap__read_snapshot(map, rec->itr, &rec->tool,
231 record__process_auxtrace, 235 record__process_auxtrace,
232 rec->opts.auxtrace_snapshot_size); 236 rec->opts.auxtrace_snapshot_size);
233 if (ret < 0) 237 if (ret < 0)
@@ -245,13 +249,12 @@ static int record__auxtrace_read_snapshot_all(struct record *rec)
245 int rc = 0; 249 int rc = 0;
246 250
247 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 251 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
248 struct auxtrace_mmap *mm = 252 struct perf_mmap *map = &rec->evlist->mmap[i];
249 &rec->evlist->mmap[i].auxtrace_mmap;
250 253
251 if (!mm->base) 254 if (!map->auxtrace_mmap.base)
252 continue; 255 continue;
253 256
254 if (record__auxtrace_mmap_read_snapshot(rec, mm) != 0) { 257 if (record__auxtrace_mmap_read_snapshot(rec, map) != 0) {
255 rc = -1; 258 rc = -1;
256 goto out; 259 goto out;
257 } 260 }
@@ -295,7 +298,7 @@ static int record__auxtrace_init(struct record *rec)
295 298
296static inline 299static inline
297int record__auxtrace_mmap_read(struct record *rec __maybe_unused, 300int record__auxtrace_mmap_read(struct record *rec __maybe_unused,
298 struct auxtrace_mmap *mm __maybe_unused) 301 struct perf_mmap *map __maybe_unused)
299{ 302{
300 return 0; 303 return 0;
301} 304}
@@ -388,7 +391,12 @@ try_again:
388 ui__warning("%s\n", msg); 391 ui__warning("%s\n", msg);
389 goto try_again; 392 goto try_again;
390 } 393 }
391 394 if ((errno == EINVAL || errno == EBADF) &&
395 pos->leader != pos &&
396 pos->weak_group) {
397 pos = perf_evlist__reset_weak_group(evlist, pos);
398 goto try_again;
399 }
392 rc = -errno; 400 rc = -errno;
393 perf_evsel__open_strerror(pos, &opts->target, 401 perf_evsel__open_strerror(pos, &opts->target,
394 errno, msg, sizeof(msg)); 402 errno, msg, sizeof(msg));
@@ -529,17 +537,17 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
529 return 0; 537 return 0;
530 538
531 for (i = 0; i < evlist->nr_mmaps; i++) { 539 for (i = 0; i < evlist->nr_mmaps; i++) {
532 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; 540 struct perf_mmap *map = &maps[i];
533 541
534 if (maps[i].base) { 542 if (map->base) {
535 if (perf_mmap__push(&maps[i], rec, record__pushfn) != 0) { 543 if (perf_mmap__push(map, rec, record__pushfn) != 0) {
536 rc = -1; 544 rc = -1;
537 goto out; 545 goto out;
538 } 546 }
539 } 547 }
540 548
541 if (mm->base && !rec->opts.auxtrace_snapshot_mode && 549 if (map->auxtrace_mmap.base && !rec->opts.auxtrace_snapshot_mode &&
542 record__auxtrace_mmap_read(rec, mm) != 0) { 550 record__auxtrace_mmap_read(rec, map) != 0) {
543 rc = -1; 551 rc = -1;
544 goto out; 552 goto out;
545 } 553 }
@@ -550,7 +558,7 @@ static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evli
550 * at least one event. 558 * at least one event.
551 */ 559 */
552 if (bytes_written != rec->bytes_written) 560 if (bytes_written != rec->bytes_written)
553 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 561 rc = record__write(rec, NULL, &finished_round_event, sizeof(finished_round_event));
554 562
555 if (overwrite) 563 if (overwrite)
556 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); 564 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
@@ -589,6 +597,9 @@ static void record__init_features(struct record *rec)
589 if (!rec->opts.full_auxtrace) 597 if (!rec->opts.full_auxtrace)
590 perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 598 perf_header__clear_feat(&session->header, HEADER_AUXTRACE);
591 599
600 if (!(rec->opts.use_clockid && rec->opts.clockid_res_ns))
601 perf_header__clear_feat(&session->header, HEADER_CLOCKID);
602
592 perf_header__clear_feat(&session->header, HEADER_STAT); 603 perf_header__clear_feat(&session->header, HEADER_STAT);
593} 604}
594 605
@@ -758,7 +769,7 @@ static int record__synthesize(struct record *rec, bool tail)
758 * We need to synthesize events first, because some 769 * We need to synthesize events first, because some
759 * features works on top of them (on report side). 770 * features works on top of them (on report side).
760 */ 771 */
761 err = perf_event__synthesize_attrs(tool, session, 772 err = perf_event__synthesize_attrs(tool, rec->evlist,
762 process_synthesized_event); 773 process_synthesized_event);
763 if (err < 0) { 774 if (err < 0) {
764 pr_err("Couldn't synthesize attrs.\n"); 775 pr_err("Couldn't synthesize attrs.\n");
@@ -894,6 +905,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
894 905
895 record__init_features(rec); 906 record__init_features(rec);
896 907
908 if (rec->opts.use_clockid && rec->opts.clockid_res_ns)
909 session->header.env.clockid_res_ns = rec->opts.clockid_res_ns;
910
897 if (forks) { 911 if (forks) {
898 err = perf_evlist__prepare_workload(rec->evlist, &opts->target, 912 err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
899 argv, data->is_pipe, 913 argv, data->is_pipe,
@@ -1334,6 +1348,19 @@ static const struct clockid_map clockids[] = {
1334 CLOCKID_END, 1348 CLOCKID_END,
1335}; 1349};
1336 1350
1351static int get_clockid_res(clockid_t clk_id, u64 *res_ns)
1352{
1353 struct timespec res;
1354
1355 *res_ns = 0;
1356 if (!clock_getres(clk_id, &res))
1357 *res_ns = res.tv_nsec + res.tv_sec * NSEC_PER_SEC;
1358 else
1359 pr_warning("WARNING: Failed to determine specified clock resolution.\n");
1360
1361 return 0;
1362}
1363
1337static int parse_clockid(const struct option *opt, const char *str, int unset) 1364static int parse_clockid(const struct option *opt, const char *str, int unset)
1338{ 1365{
1339 struct record_opts *opts = (struct record_opts *)opt->value; 1366 struct record_opts *opts = (struct record_opts *)opt->value;
@@ -1357,7 +1384,7 @@ static int parse_clockid(const struct option *opt, const char *str, int unset)
1357 1384
1358 /* if its a number, we're done */ 1385 /* if its a number, we're done */
1359 if (sscanf(str, "%d", &opts->clockid) == 1) 1386 if (sscanf(str, "%d", &opts->clockid) == 1)
1360 return 0; 1387 return get_clockid_res(opts->clockid, &opts->clockid_res_ns);
1361 1388
1362 /* allow a "CLOCK_" prefix to the name */ 1389 /* allow a "CLOCK_" prefix to the name */
1363 if (!strncasecmp(str, "CLOCK_", 6)) 1390 if (!strncasecmp(str, "CLOCK_", 6))
@@ -1366,7 +1393,8 @@ static int parse_clockid(const struct option *opt, const char *str, int unset)
1366 for (cm = clockids; cm->name; cm++) { 1393 for (cm = clockids; cm->name; cm++) {
1367 if (!strcasecmp(str, cm->name)) { 1394 if (!strcasecmp(str, cm->name)) {
1368 opts->clockid = cm->clockid; 1395 opts->clockid = cm->clockid;
1369 return 0; 1396 return get_clockid_res(opts->clockid,
1397 &opts->clockid_res_ns);
1370 } 1398 }
1371 } 1399 }
1372 1400
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 76e12bcd1765..257c9c18cb7e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -201,14 +201,13 @@ static void setup_forced_leader(struct report *report,
201 perf_evlist__force_leader(evlist); 201 perf_evlist__force_leader(evlist);
202} 202}
203 203
204static int process_feature_event(struct perf_tool *tool, 204static int process_feature_event(struct perf_session *session,
205 union perf_event *event, 205 union perf_event *event)
206 struct perf_session *session __maybe_unused)
207{ 206{
208 struct report *rep = container_of(tool, struct report, tool); 207 struct report *rep = container_of(session->tool, struct report, tool);
209 208
210 if (event->feat.feat_id < HEADER_LAST_FEATURE) 209 if (event->feat.feat_id < HEADER_LAST_FEATURE)
211 return perf_event__process_feature(tool, event, session); 210 return perf_event__process_feature(session, event);
212 211
213 if (event->feat.feat_id != HEADER_LAST_FEATURE) { 212 if (event->feat.feat_id != HEADER_LAST_FEATURE) {
214 pr_err("failed: wrong feature ID: %" PRIu64 "\n", 213 pr_err("failed: wrong feature ID: %" PRIu64 "\n",
@@ -981,6 +980,7 @@ int cmd_report(int argc, const char **argv)
981 .id_index = perf_event__process_id_index, 980 .id_index = perf_event__process_id_index,
982 .auxtrace_info = perf_event__process_auxtrace_info, 981 .auxtrace_info = perf_event__process_auxtrace_info,
983 .auxtrace = perf_event__process_auxtrace, 982 .auxtrace = perf_event__process_auxtrace,
983 .event_update = perf_event__process_event_update,
984 .feature = process_feature_event, 984 .feature = process_feature_event,
985 .ordered_events = true, 985 .ordered_events = true,
986 .ordering_requires_timestamps = true, 986 .ordering_requires_timestamps = true,
@@ -1105,7 +1105,7 @@ int cmd_report(int argc, const char **argv)
1105 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 1105 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1106 "how to display percentage of filtered entries", parse_filter_percentage), 1106 "how to display percentage of filtered entries", parse_filter_percentage),
1107 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 1107 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
1108 "Instruction Tracing options", 1108 "Instruction Tracing options\n" ITRACE_HELP,
1109 itrace_parse_synth_opts), 1109 itrace_parse_synth_opts),
1110 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, 1110 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
1111 "Show full source file name path for source lines"), 1111 "Show full source file name path for source lines"),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ba481d73f910..b5bc85bd0bbe 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -44,6 +44,7 @@
44#include <sys/stat.h> 44#include <sys/stat.h>
45#include <fcntl.h> 45#include <fcntl.h>
46#include <unistd.h> 46#include <unistd.h>
47#include <subcmd/pager.h>
47 48
48#include "sane_ctype.h" 49#include "sane_ctype.h"
49 50
@@ -406,9 +407,10 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
406 PERF_OUTPUT_WEIGHT)) 407 PERF_OUTPUT_WEIGHT))
407 return -EINVAL; 408 return -EINVAL;
408 409
409 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { 410 if (PRINT_FIELD(SYM) &&
411 !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
410 pr_err("Display of symbols requested but neither sample IP nor " 412 pr_err("Display of symbols requested but neither sample IP nor "
411 "sample address\nis selected. Hence, no addresses to convert " 413 "sample address\navailable. Hence, no addresses to convert "
412 "to symbols.\n"); 414 "to symbols.\n");
413 return -EINVAL; 415 return -EINVAL;
414 } 416 }
@@ -417,10 +419,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
417 "selected.\n"); 419 "selected.\n");
418 return -EINVAL; 420 return -EINVAL;
419 } 421 }
420 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR) && 422 if (PRINT_FIELD(DSO) &&
421 !PRINT_FIELD(BRSTACK) && !PRINT_FIELD(BRSTACKSYM) && !PRINT_FIELD(BRSTACKOFF)) { 423 !(evsel->attr.sample_type & (PERF_SAMPLE_IP|PERF_SAMPLE_ADDR))) {
422 pr_err("Display of DSO requested but no address to convert. Select\n" 424 pr_err("Display of DSO requested but no address to convert.\n");
423 "sample IP, sample address, brstack, brstacksym, or brstackoff.\n");
424 return -EINVAL; 425 return -EINVAL;
425 } 426 }
426 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) { 427 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
@@ -912,7 +913,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
912 913
913static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, 914static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
914 struct perf_insn *x, u8 *inbuf, int len, 915 struct perf_insn *x, u8 *inbuf, int len,
915 int insn, FILE *fp) 916 int insn, FILE *fp, int *total_cycles)
916{ 917{
917 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip, 918 int printed = fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip,
918 dump_insn(x, ip, inbuf, len, NULL), 919 dump_insn(x, ip, inbuf, len, NULL),
@@ -921,7 +922,8 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
921 en->flags.in_tx ? " INTX" : "", 922 en->flags.in_tx ? " INTX" : "",
922 en->flags.abort ? " ABORT" : ""); 923 en->flags.abort ? " ABORT" : "");
923 if (en->flags.cycles) { 924 if (en->flags.cycles) {
924 printed += fprintf(fp, " %d cycles", en->flags.cycles); 925 *total_cycles += en->flags.cycles;
926 printed += fprintf(fp, " %d cycles [%d]", en->flags.cycles, *total_cycles);
925 if (insn) 927 if (insn)
926 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles); 928 printed += fprintf(fp, " %.2f IPC", (float)insn / en->flags.cycles);
927 } 929 }
@@ -978,6 +980,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
978 u8 buffer[MAXBB]; 980 u8 buffer[MAXBB];
979 unsigned off; 981 unsigned off;
980 struct symbol *lastsym = NULL; 982 struct symbol *lastsym = NULL;
983 int total_cycles = 0;
981 984
982 if (!(br && br->nr)) 985 if (!(br && br->nr))
983 return 0; 986 return 0;
@@ -998,7 +1001,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
998 printed += ip__fprintf_sym(br->entries[nr - 1].from, thread, 1001 printed += ip__fprintf_sym(br->entries[nr - 1].from, thread,
999 x.cpumode, x.cpu, &lastsym, attr, fp); 1002 x.cpumode, x.cpu, &lastsym, attr, fp);
1000 printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1], 1003 printed += ip__fprintf_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
1001 &x, buffer, len, 0, fp); 1004 &x, buffer, len, 0, fp, &total_cycles);
1002 } 1005 }
1003 1006
1004 /* Print all blocks */ 1007 /* Print all blocks */
@@ -1026,7 +1029,8 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample,
1026 1029
1027 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp); 1030 printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp);
1028 if (ip == end) { 1031 if (ip == end) {
1029 printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp); 1032 printed += ip__fprintf_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn, fp,
1033 &total_cycles);
1030 break; 1034 break;
1031 } else { 1035 } else {
1032 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip, 1036 printed += fprintf(fp, "\t%016" PRIx64 "\t%s\n", ip,
@@ -1104,6 +1108,35 @@ out:
1104 return printed; 1108 return printed;
1105} 1109}
1106 1110
1111static const char *resolve_branch_sym(struct perf_sample *sample,
1112 struct perf_evsel *evsel,
1113 struct thread *thread,
1114 struct addr_location *al,
1115 u64 *ip)
1116{
1117 struct addr_location addr_al;
1118 struct perf_event_attr *attr = &evsel->attr;
1119 const char *name = NULL;
1120
1121 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
1122 if (sample_addr_correlates_sym(attr)) {
1123 thread__resolve(thread, &addr_al, sample);
1124 if (addr_al.sym)
1125 name = addr_al.sym->name;
1126 else
1127 *ip = sample->addr;
1128 } else {
1129 *ip = sample->addr;
1130 }
1131 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1132 if (al->sym)
1133 name = al->sym->name;
1134 else
1135 *ip = sample->ip;
1136 }
1137 return name;
1138}
1139
1107static int perf_sample__fprintf_callindent(struct perf_sample *sample, 1140static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1108 struct perf_evsel *evsel, 1141 struct perf_evsel *evsel,
1109 struct thread *thread, 1142 struct thread *thread,
@@ -1111,10 +1144,10 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1111{ 1144{
1112 struct perf_event_attr *attr = &evsel->attr; 1145 struct perf_event_attr *attr = &evsel->attr;
1113 size_t depth = thread_stack__depth(thread); 1146 size_t depth = thread_stack__depth(thread);
1114 struct addr_location addr_al;
1115 const char *name = NULL; 1147 const char *name = NULL;
1116 static int spacing; 1148 static int spacing;
1117 int len = 0; 1149 int len = 0;
1150 int dlen = 0;
1118 u64 ip = 0; 1151 u64 ip = 0;
1119 1152
1120 /* 1153 /*
@@ -1124,21 +1157,12 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1124 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN) 1157 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
1125 depth += 1; 1158 depth += 1;
1126 1159
1127 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) { 1160 name = resolve_branch_sym(sample, evsel, thread, al, &ip);
1128 if (sample_addr_correlates_sym(attr)) { 1161
1129 thread__resolve(thread, &addr_al, sample); 1162 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
1130 if (addr_al.sym) 1163 dlen += fprintf(fp, "(");
1131 name = addr_al.sym->name; 1164 dlen += map__fprintf_dsoname(al->map, fp);
1132 else 1165 dlen += fprintf(fp, ")\t");
1133 ip = sample->addr;
1134 } else {
1135 ip = sample->addr;
1136 }
1137 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1138 if (al->sym)
1139 name = al->sym->name;
1140 else
1141 ip = sample->ip;
1142 } 1166 }
1143 1167
1144 if (name) 1168 if (name)
@@ -1159,7 +1183,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1159 if (len < spacing) 1183 if (len < spacing)
1160 len += fprintf(fp, "%*s", spacing - len, ""); 1184 len += fprintf(fp, "%*s", spacing - len, "");
1161 1185
1162 return len; 1186 return len + dlen;
1163} 1187}
1164 1188
1165static int perf_sample__fprintf_insn(struct perf_sample *sample, 1189static int perf_sample__fprintf_insn(struct perf_sample *sample,
@@ -1255,6 +1279,18 @@ static struct {
1255 {0, NULL} 1279 {0, NULL}
1256}; 1280};
1257 1281
1282static const char *sample_flags_to_name(u32 flags)
1283{
1284 int i;
1285
1286 for (i = 0; sample_flags[i].name ; i++) {
1287 if (sample_flags[i].flags == flags)
1288 return sample_flags[i].name;
1289 }
1290
1291 return NULL;
1292}
1293
1258static int perf_sample__fprintf_flags(u32 flags, FILE *fp) 1294static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
1259{ 1295{
1260 const char *chars = PERF_IP_FLAG_CHARS; 1296 const char *chars = PERF_IP_FLAG_CHARS;
@@ -1264,11 +1300,20 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
1264 char str[33]; 1300 char str[33];
1265 int i, pos = 0; 1301 int i, pos = 0;
1266 1302
1267 for (i = 0; sample_flags[i].name ; i++) { 1303 name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX);
1268 if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) { 1304 if (name)
1269 name = sample_flags[i].name; 1305 return fprintf(fp, " %-15s%4s ", name, in_tx ? "(x)" : "");
1270 break; 1306
1271 } 1307 if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
1308 name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN));
1309 if (name)
1310 return fprintf(fp, " tr strt %-7s%4s ", name, in_tx ? "(x)" : "");
1311 }
1312
1313 if (flags & PERF_IP_FLAG_TRACE_END) {
1314 name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END));
1315 if (name)
1316 return fprintf(fp, " tr end %-7s%4s ", name, in_tx ? "(x)" : "");
1272 } 1317 }
1273 1318
1274 for (i = 0; i < n; i++, flags >>= 1) { 1319 for (i = 0; i < n; i++, flags >>= 1) {
@@ -1281,10 +1326,7 @@ static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
1281 } 1326 }
1282 str[pos] = 0; 1327 str[pos] = 0;
1283 1328
1284 if (name) 1329 return fprintf(fp, " %-19s ", str);
1285 return fprintf(fp, " %-7s%4s ", name, in_tx ? "(x)" : "");
1286
1287 return fprintf(fp, " %-11s ", str);
1288} 1330}
1289 1331
1290struct printer_data { 1332struct printer_data {
@@ -1544,7 +1586,8 @@ struct metric_ctx {
1544 FILE *fp; 1586 FILE *fp;
1545}; 1587};
1546 1588
1547static void script_print_metric(void *ctx, const char *color, 1589static void script_print_metric(struct perf_stat_config *config __maybe_unused,
1590 void *ctx, const char *color,
1548 const char *fmt, 1591 const char *fmt,
1549 const char *unit, double val) 1592 const char *unit, double val)
1550{ 1593{
@@ -1562,7 +1605,8 @@ static void script_print_metric(void *ctx, const char *color,
1562 fprintf(mctx->fp, " %s\n", unit); 1605 fprintf(mctx->fp, " %s\n", unit);
1563} 1606}
1564 1607
1565static void script_new_line(void *ctx) 1608static void script_new_line(struct perf_stat_config *config __maybe_unused,
1609 void *ctx)
1566{ 1610{
1567 struct metric_ctx *mctx = ctx; 1611 struct metric_ctx *mctx = ctx;
1568 1612
@@ -1608,7 +1652,7 @@ static void perf_sample__fprint_metric(struct perf_script *script,
1608 evsel_script(evsel)->val = val; 1652 evsel_script(evsel)->val = val;
1609 if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) { 1653 if (evsel_script(evsel->leader)->gnum == evsel->leader->nr_members) {
1610 for_each_group_member (ev2, evsel->leader) { 1654 for_each_group_member (ev2, evsel->leader) {
1611 perf_stat__print_shadow_stats(ev2, 1655 perf_stat__print_shadow_stats(&stat_config, ev2,
1612 evsel_script(ev2)->val, 1656 evsel_script(ev2)->val,
1613 sample->cpu, 1657 sample->cpu,
1614 &ctx, 1658 &ctx,
@@ -1619,6 +1663,47 @@ static void perf_sample__fprint_metric(struct perf_script *script,
1619 } 1663 }
1620} 1664}
1621 1665
1666static bool show_event(struct perf_sample *sample,
1667 struct perf_evsel *evsel,
1668 struct thread *thread,
1669 struct addr_location *al)
1670{
1671 int depth = thread_stack__depth(thread);
1672
1673 if (!symbol_conf.graph_function)
1674 return true;
1675
1676 if (thread->filter) {
1677 if (depth <= thread->filter_entry_depth) {
1678 thread->filter = false;
1679 return false;
1680 }
1681 return true;
1682 } else {
1683 const char *s = symbol_conf.graph_function;
1684 u64 ip;
1685 const char *name = resolve_branch_sym(sample, evsel, thread, al,
1686 &ip);
1687 unsigned nlen;
1688
1689 if (!name)
1690 return false;
1691 nlen = strlen(name);
1692 while (*s) {
1693 unsigned len = strcspn(s, ",");
1694 if (nlen == len && !strncmp(name, s, len)) {
1695 thread->filter = true;
1696 thread->filter_entry_depth = depth;
1697 return true;
1698 }
1699 s += len;
1700 if (*s == ',')
1701 s++;
1702 }
1703 return false;
1704 }
1705}
1706
1622static void process_event(struct perf_script *script, 1707static void process_event(struct perf_script *script,
1623 struct perf_sample *sample, struct perf_evsel *evsel, 1708 struct perf_sample *sample, struct perf_evsel *evsel,
1624 struct addr_location *al, 1709 struct addr_location *al,
@@ -1633,6 +1718,9 @@ static void process_event(struct perf_script *script,
1633 if (output[type].fields == 0) 1718 if (output[type].fields == 0)
1634 return; 1719 return;
1635 1720
1721 if (!show_event(sample, evsel, thread, al))
1722 return;
1723
1636 ++es->samples; 1724 ++es->samples;
1637 1725
1638 perf_sample__fprintf_start(sample, thread, evsel, 1726 perf_sample__fprintf_start(sample, thread, evsel,
@@ -1710,6 +1798,9 @@ static void process_event(struct perf_script *script,
1710 1798
1711 if (PRINT_FIELD(METRIC)) 1799 if (PRINT_FIELD(METRIC))
1712 perf_sample__fprint_metric(script, thread, evsel, sample, fp); 1800 perf_sample__fprint_metric(script, thread, evsel, sample, fp);
1801
1802 if (verbose)
1803 fflush(fp);
1713} 1804}
1714 1805
1715static struct scripting_ops *scripting_ops; 1806static struct scripting_ops *scripting_ops;
@@ -2489,6 +2580,8 @@ parse:
2489 output[j].fields &= ~all_output_options[i].field; 2580 output[j].fields &= ~all_output_options[i].field;
2490 else 2581 else
2491 output[j].fields |= all_output_options[i].field; 2582 output[j].fields |= all_output_options[i].field;
2583 output[j].user_set = true;
2584 output[j].wildcard_set = true;
2492 } 2585 }
2493 } 2586 }
2494 } else { 2587 } else {
@@ -2499,7 +2592,8 @@ parse:
2499 rc = -EINVAL; 2592 rc = -EINVAL;
2500 goto out; 2593 goto out;
2501 } 2594 }
2502 output[type].fields |= all_output_options[i].field; 2595 output[type].user_set = true;
2596 output[type].wildcard_set = true;
2503 } 2597 }
2504 } 2598 }
2505 2599
@@ -2963,9 +3057,8 @@ static void script__setup_sample_type(struct perf_script *script)
2963 } 3057 }
2964} 3058}
2965 3059
2966static int process_stat_round_event(struct perf_tool *tool __maybe_unused, 3060static int process_stat_round_event(struct perf_session *session,
2967 union perf_event *event, 3061 union perf_event *event)
2968 struct perf_session *session)
2969{ 3062{
2970 struct stat_round_event *round = &event->stat_round; 3063 struct stat_round_event *round = &event->stat_round;
2971 struct perf_evsel *counter; 3064 struct perf_evsel *counter;
@@ -2979,9 +3072,8 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2979 return 0; 3072 return 0;
2980} 3073}
2981 3074
2982static int process_stat_config_event(struct perf_tool *tool __maybe_unused, 3075static int process_stat_config_event(struct perf_session *session __maybe_unused,
2983 union perf_event *event, 3076 union perf_event *event)
2984 struct perf_session *session __maybe_unused)
2985{ 3077{
2986 perf_event__read_stat_config(&stat_config, &event->stat_config); 3078 perf_event__read_stat_config(&stat_config, &event->stat_config);
2987 return 0; 3079 return 0;
@@ -3007,10 +3099,10 @@ static int set_maps(struct perf_script *script)
3007} 3099}
3008 3100
3009static 3101static
3010int process_thread_map_event(struct perf_tool *tool, 3102int process_thread_map_event(struct perf_session *session,
3011 union perf_event *event, 3103 union perf_event *event)
3012 struct perf_session *session __maybe_unused)
3013{ 3104{
3105 struct perf_tool *tool = session->tool;
3014 struct perf_script *script = container_of(tool, struct perf_script, tool); 3106 struct perf_script *script = container_of(tool, struct perf_script, tool);
3015 3107
3016 if (script->threads) { 3108 if (script->threads) {
@@ -3026,10 +3118,10 @@ int process_thread_map_event(struct perf_tool *tool,
3026} 3118}
3027 3119
3028static 3120static
3029int process_cpu_map_event(struct perf_tool *tool __maybe_unused, 3121int process_cpu_map_event(struct perf_session *session,
3030 union perf_event *event, 3122 union perf_event *event)
3031 struct perf_session *session __maybe_unused)
3032{ 3123{
3124 struct perf_tool *tool = session->tool;
3033 struct perf_script *script = container_of(tool, struct perf_script, tool); 3125 struct perf_script *script = container_of(tool, struct perf_script, tool);
3034 3126
3035 if (script->cpus) { 3127 if (script->cpus) {
@@ -3044,21 +3136,21 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
3044 return set_maps(script); 3136 return set_maps(script);
3045} 3137}
3046 3138
3047static int process_feature_event(struct perf_tool *tool, 3139static int process_feature_event(struct perf_session *session,
3048 union perf_event *event, 3140 union perf_event *event)
3049 struct perf_session *session)
3050{ 3141{
3051 if (event->feat.feat_id < HEADER_LAST_FEATURE) 3142 if (event->feat.feat_id < HEADER_LAST_FEATURE)
3052 return perf_event__process_feature(tool, event, session); 3143 return perf_event__process_feature(session, event);
3053 return 0; 3144 return 0;
3054} 3145}
3055 3146
3056#ifdef HAVE_AUXTRACE_SUPPORT 3147#ifdef HAVE_AUXTRACE_SUPPORT
3057static int perf_script__process_auxtrace_info(struct perf_tool *tool, 3148static int perf_script__process_auxtrace_info(struct perf_session *session,
3058 union perf_event *event, 3149 union perf_event *event)
3059 struct perf_session *session)
3060{ 3150{
3061 int ret = perf_event__process_auxtrace_info(tool, event, session); 3151 struct perf_tool *tool = session->tool;
3152
3153 int ret = perf_event__process_auxtrace_info(session, event);
3062 3154
3063 if (ret == 0) { 3155 if (ret == 0) {
3064 struct perf_script *script = container_of(tool, struct perf_script, tool); 3156 struct perf_script *script = container_of(tool, struct perf_script, tool);
@@ -3072,6 +3164,44 @@ static int perf_script__process_auxtrace_info(struct perf_tool *tool,
3072#define perf_script__process_auxtrace_info 0 3164#define perf_script__process_auxtrace_info 0
3073#endif 3165#endif
3074 3166
3167static int parse_insn_trace(const struct option *opt __maybe_unused,
3168 const char *str __maybe_unused,
3169 int unset __maybe_unused)
3170{
3171 parse_output_fields(NULL, "+insn,-event,-period", 0);
3172 itrace_parse_synth_opts(opt, "i0ns", 0);
3173 nanosecs = true;
3174 return 0;
3175}
3176
3177static int parse_xed(const struct option *opt __maybe_unused,
3178 const char *str __maybe_unused,
3179 int unset __maybe_unused)
3180{
3181 force_pager("xed -F insn: -A -64 | less");
3182 return 0;
3183}
3184
3185static int parse_call_trace(const struct option *opt __maybe_unused,
3186 const char *str __maybe_unused,
3187 int unset __maybe_unused)
3188{
3189 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent", 0);
3190 itrace_parse_synth_opts(opt, "cewp", 0);
3191 nanosecs = true;
3192 return 0;
3193}
3194
3195static int parse_callret_trace(const struct option *opt __maybe_unused,
3196 const char *str __maybe_unused,
3197 int unset __maybe_unused)
3198{
3199 parse_output_fields(NULL, "-ip,-addr,-event,-period,+callindent,+flags", 0);
3200 itrace_parse_synth_opts(opt, "crewp", 0);
3201 nanosecs = true;
3202 return 0;
3203}
3204
3075int cmd_script(int argc, const char **argv) 3205int cmd_script(int argc, const char **argv)
3076{ 3206{
3077 bool show_full_info = false; 3207 bool show_full_info = false;
@@ -3081,7 +3211,10 @@ int cmd_script(int argc, const char **argv)
3081 char *rec_script_path = NULL; 3211 char *rec_script_path = NULL;
3082 char *rep_script_path = NULL; 3212 char *rep_script_path = NULL;
3083 struct perf_session *session; 3213 struct perf_session *session;
3084 struct itrace_synth_opts itrace_synth_opts = { .set = false, }; 3214 struct itrace_synth_opts itrace_synth_opts = {
3215 .set = false,
3216 .default_no_sample = true,
3217 };
3085 char *script_path = NULL; 3218 char *script_path = NULL;
3086 const char **__argv; 3219 const char **__argv;
3087 int i, j, err = 0; 3220 int i, j, err = 0;
@@ -3156,6 +3289,16 @@ int cmd_script(int argc, const char **argv)
3156 "system-wide collection from all CPUs"), 3289 "system-wide collection from all CPUs"),
3157 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 3290 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
3158 "only consider these symbols"), 3291 "only consider these symbols"),
3292 OPT_CALLBACK_OPTARG(0, "insn-trace", &itrace_synth_opts, NULL, NULL,
3293 "Decode instructions from itrace", parse_insn_trace),
3294 OPT_CALLBACK_OPTARG(0, "xed", NULL, NULL, NULL,
3295 "Run xed disassembler on output", parse_xed),
3296 OPT_CALLBACK_OPTARG(0, "call-trace", &itrace_synth_opts, NULL, NULL,
3297 "Decode calls from from itrace", parse_call_trace),
3298 OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,
3299 "Decode calls and returns from itrace", parse_callret_trace),
3300 OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",
3301 "Only print symbols and callees with --call-trace/--call-ret-trace"),
3159 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]", 3302 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
3160 "Stop display of callgraph at these symbols"), 3303 "Stop display of callgraph at these symbols"),
3161 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 3304 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
@@ -3193,7 +3336,7 @@ int cmd_script(int argc, const char **argv)
3193 OPT_BOOLEAN(0, "ns", &nanosecs, 3336 OPT_BOOLEAN(0, "ns", &nanosecs,
3194 "Use 9 decimal places when displaying time"), 3337 "Use 9 decimal places when displaying time"),
3195 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 3338 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
3196 "Instruction Tracing options", 3339 "Instruction Tracing options\n" ITRACE_HELP,
3197 itrace_parse_synth_opts), 3340 itrace_parse_synth_opts),
3198 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, 3341 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename,
3199 "Show full source file name path for source lines"), 3342 "Show full source file name path for source lines"),
@@ -3389,8 +3532,10 @@ int cmd_script(int argc, const char **argv)
3389 exit(-1); 3532 exit(-1);
3390 } 3533 }
3391 3534
3392 if (!script_name) 3535 if (!script_name) {
3393 setup_pager(); 3536 setup_pager();
3537 use_browser = 0;
3538 }
3394 3539
3395 session = perf_session__new(&data, false, &script.tool); 3540 session = perf_session__new(&data, false, &script.tool);
3396 if (session == NULL) 3541 if (session == NULL)
@@ -3411,7 +3556,8 @@ int cmd_script(int argc, const char **argv)
3411 script.session = session; 3556 script.session = session;
3412 script__setup_sample_type(&script); 3557 script__setup_sample_type(&script);
3413 3558
3414 if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) 3559 if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||
3560 symbol_conf.graph_function)
3415 itrace_synth_opts.thread_stack = true; 3561 itrace_synth_opts.thread_stack = true;
3416 3562
3417 session->itrace_synth_opts = &itrace_synth_opts; 3563 session->itrace_synth_opts = &itrace_synth_opts;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d097b5b47eb8..a635abfa77b6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -88,8 +88,6 @@
88#include "sane_ctype.h" 88#include "sane_ctype.h"
89 89
90#define DEFAULT_SEPARATOR " " 90#define DEFAULT_SEPARATOR " "
91#define CNTR_NOT_SUPPORTED "<not supported>"
92#define CNTR_NOT_COUNTED "<not counted>"
93#define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi" 91#define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi"
94 92
95static void print_counters(struct timespec *ts, int argc, const char **argv); 93static void print_counters(struct timespec *ts, int argc, const char **argv);
@@ -137,54 +135,30 @@ static const char *smi_cost_attrs = {
137 135
138static struct perf_evlist *evsel_list; 136static struct perf_evlist *evsel_list;
139 137
140static struct rblist metric_events;
141
142static struct target target = { 138static struct target target = {
143 .uid = UINT_MAX, 139 .uid = UINT_MAX,
144}; 140};
145 141
146typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu);
147
148#define METRIC_ONLY_LEN 20 142#define METRIC_ONLY_LEN 20
149 143
150static int run_count = 1;
151static bool no_inherit = false;
152static volatile pid_t child_pid = -1; 144static volatile pid_t child_pid = -1;
153static bool null_run = false;
154static int detailed_run = 0; 145static int detailed_run = 0;
155static bool transaction_run; 146static bool transaction_run;
156static bool topdown_run = false; 147static bool topdown_run = false;
157static bool smi_cost = false; 148static bool smi_cost = false;
158static bool smi_reset = false; 149static bool smi_reset = false;
159static bool big_num = true;
160static int big_num_opt = -1; 150static int big_num_opt = -1;
161static const char *csv_sep = NULL;
162static bool csv_output = false;
163static bool group = false; 151static bool group = false;
164static const char *pre_cmd = NULL; 152static const char *pre_cmd = NULL;
165static const char *post_cmd = NULL; 153static const char *post_cmd = NULL;
166static bool sync_run = false; 154static bool sync_run = false;
167static unsigned int initial_delay = 0;
168static unsigned int unit_width = 4; /* strlen("unit") */
169static bool forever = false; 155static bool forever = false;
170static bool metric_only = false;
171static bool force_metric_only = false; 156static bool force_metric_only = false;
172static bool no_merge = false;
173static bool walltime_run_table = false;
174static struct timespec ref_time; 157static struct timespec ref_time;
175static struct cpu_map *aggr_map;
176static aggr_get_id_t aggr_get_id;
177static bool append_file; 158static bool append_file;
178static bool interval_count; 159static bool interval_count;
179static bool interval_clear;
180static const char *output_name; 160static const char *output_name;
181static int output_fd; 161static int output_fd;
182static int print_free_counters_hint;
183static int print_mixed_hw_group_error;
184static u64 *walltime_run;
185static bool ru_display = false;
186static struct rusage ru_data;
187static unsigned int metric_only_len = METRIC_ONLY_LEN;
188 162
189struct perf_stat { 163struct perf_stat {
190 bool record; 164 bool record;
@@ -204,15 +178,15 @@ static struct perf_stat perf_stat;
204static volatile int done = 0; 178static volatile int done = 0;
205 179
206static struct perf_stat_config stat_config = { 180static struct perf_stat_config stat_config = {
207 .aggr_mode = AGGR_GLOBAL, 181 .aggr_mode = AGGR_GLOBAL,
208 .scale = true, 182 .scale = true,
183 .unit_width = 4, /* strlen("unit") */
184 .run_count = 1,
185 .metric_only_len = METRIC_ONLY_LEN,
186 .walltime_nsecs_stats = &walltime_nsecs_stats,
187 .big_num = true,
209}; 188};
210 189
211static bool is_duration_time(struct perf_evsel *evsel)
212{
213 return !strcmp(evsel->name, "duration_time");
214}
215
216static inline void diff_timespec(struct timespec *r, struct timespec *a, 190static inline void diff_timespec(struct timespec *r, struct timespec *a,
217 struct timespec *b) 191 struct timespec *b)
218{ 192{
@@ -236,66 +210,6 @@ static void perf_stat__reset_stats(void)
236 perf_stat__reset_shadow_per_stat(&stat_config.stats[i]); 210 perf_stat__reset_shadow_per_stat(&stat_config.stats[i]);
237} 211}
238 212
239static int create_perf_stat_counter(struct perf_evsel *evsel)
240{
241 struct perf_event_attr *attr = &evsel->attr;
242 struct perf_evsel *leader = evsel->leader;
243
244 if (stat_config.scale) {
245 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
246 PERF_FORMAT_TOTAL_TIME_RUNNING;
247 }
248
249 /*
250 * The event is part of non trivial group, let's enable
251 * the group read (for leader) and ID retrieval for all
252 * members.
253 */
254 if (leader->nr_members > 1)
255 attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
256
257 attr->inherit = !no_inherit;
258
259 /*
260 * Some events get initialized with sample_(period/type) set,
261 * like tracepoints. Clear it up for counting.
262 */
263 attr->sample_period = 0;
264
265 /*
266 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
267 * while avoiding that older tools show confusing messages.
268 *
269 * However for pipe sessions we need to keep it zero,
270 * because script's perf_evsel__check_attr is triggered
271 * by attr->sample_type != 0, and we can't run it on
272 * stat sessions.
273 */
274 if (!(STAT_RECORD && perf_stat.data.is_pipe))
275 attr->sample_type = PERF_SAMPLE_IDENTIFIER;
276
277 /*
278 * Disabling all counters initially, they will be enabled
279 * either manually by us or by kernel via enable_on_exec
280 * set later.
281 */
282 if (perf_evsel__is_group_leader(evsel)) {
283 attr->disabled = 1;
284
285 /*
286 * In case of initial_delay we enable tracee
287 * events manually.
288 */
289 if (target__none(&target) && !initial_delay)
290 attr->enable_on_exec = 1;
291 }
292
293 if (target__has_cpu(&target) && !target__has_per_thread(&target))
294 return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
295
296 return perf_evsel__open_per_thread(evsel, evsel_list->threads);
297}
298
299static int process_synthesized_event(struct perf_tool *tool __maybe_unused, 213static int process_synthesized_event(struct perf_tool *tool __maybe_unused,
300 union perf_event *event, 214 union perf_event *event,
301 struct perf_sample *sample __maybe_unused, 215 struct perf_sample *sample __maybe_unused,
@@ -428,15 +342,15 @@ static void process_interval(void)
428 342
429static void enable_counters(void) 343static void enable_counters(void)
430{ 344{
431 if (initial_delay) 345 if (stat_config.initial_delay)
432 usleep(initial_delay * USEC_PER_MSEC); 346 usleep(stat_config.initial_delay * USEC_PER_MSEC);
433 347
434 /* 348 /*
435 * We need to enable counters only if: 349 * We need to enable counters only if:
436 * - we don't have tracee (attaching to task or cpu) 350 * - we don't have tracee (attaching to task or cpu)
437 * - we have initial delay configured 351 * - we have initial delay configured
438 */ 352 */
439 if (!target__none(&target) || initial_delay) 353 if (!target__none(&target) || stat_config.initial_delay)
440 perf_evlist__enable(evsel_list); 354 perf_evlist__enable(evsel_list);
441} 355}
442 356
@@ -464,109 +378,31 @@ static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *inf
464 workload_exec_errno = info->si_value.sival_int; 378 workload_exec_errno = info->si_value.sival_int;
465} 379}
466 380
467static int perf_stat_synthesize_config(bool is_pipe)
468{
469 int err;
470
471 if (is_pipe) {
472 err = perf_event__synthesize_attrs(NULL, perf_stat.session,
473 process_synthesized_event);
474 if (err < 0) {
475 pr_err("Couldn't synthesize attrs.\n");
476 return err;
477 }
478 }
479
480 err = perf_event__synthesize_extra_attr(NULL,
481 evsel_list,
482 process_synthesized_event,
483 is_pipe);
484
485 err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads,
486 process_synthesized_event,
487 NULL);
488 if (err < 0) {
489 pr_err("Couldn't synthesize thread map.\n");
490 return err;
491 }
492
493 err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus,
494 process_synthesized_event, NULL);
495 if (err < 0) {
496 pr_err("Couldn't synthesize thread map.\n");
497 return err;
498 }
499
500 err = perf_event__synthesize_stat_config(NULL, &stat_config,
501 process_synthesized_event, NULL);
502 if (err < 0) {
503 pr_err("Couldn't synthesize config.\n");
504 return err;
505 }
506
507 return 0;
508}
509
510#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
511
512static int __store_counter_ids(struct perf_evsel *counter)
513{
514 int cpu, thread;
515
516 for (cpu = 0; cpu < xyarray__max_x(counter->fd); cpu++) {
517 for (thread = 0; thread < xyarray__max_y(counter->fd);
518 thread++) {
519 int fd = FD(counter, cpu, thread);
520
521 if (perf_evlist__id_add_fd(evsel_list, counter,
522 cpu, thread, fd) < 0)
523 return -1;
524 }
525 }
526
527 return 0;
528}
529
530static int store_counter_ids(struct perf_evsel *counter)
531{
532 struct cpu_map *cpus = counter->cpus;
533 struct thread_map *threads = counter->threads;
534
535 if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr))
536 return -ENOMEM;
537
538 return __store_counter_ids(counter);
539}
540
541static bool perf_evsel__should_store_id(struct perf_evsel *counter) 381static bool perf_evsel__should_store_id(struct perf_evsel *counter)
542{ 382{
543 return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID; 383 return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
544} 384}
545 385
546static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel) 386static bool is_target_alive(struct target *_target,
387 struct thread_map *threads)
547{ 388{
548 struct perf_evsel *c2, *leader; 389 struct stat st;
549 bool is_open = true; 390 int i;
550 391
551 leader = evsel->leader; 392 if (!target__has_task(_target))
552 pr_debug("Weak group for %s/%d failed\n", 393 return true;
553 leader->name, leader->nr_members);
554 394
555 /* 395 for (i = 0; i < threads->nr; i++) {
556 * for_each_group_member doesn't work here because it doesn't 396 char path[PATH_MAX];
557 * include the first entry. 397
558 */ 398 scnprintf(path, PATH_MAX, "%s/%d", procfs__mountpoint(),
559 evlist__for_each_entry(evsel_list, c2) { 399 threads->map[i].pid);
560 if (c2 == evsel) 400
561 is_open = false; 401 if (!stat(path, &st))
562 if (c2->leader == leader) { 402 return true;
563 if (is_open)
564 perf_evsel__close(c2);
565 c2->leader = c2;
566 c2->nr_members = 0;
567 }
568 } 403 }
569 return leader; 404
405 return false;
570} 406}
571 407
572static int __run_perf_stat(int argc, const char **argv, int run_idx) 408static int __run_perf_stat(int argc, const char **argv, int run_idx)
@@ -609,13 +445,13 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
609 445
610 evlist__for_each_entry(evsel_list, counter) { 446 evlist__for_each_entry(evsel_list, counter) {
611try_again: 447try_again:
612 if (create_perf_stat_counter(counter) < 0) { 448 if (create_perf_stat_counter(counter, &stat_config, &target) < 0) {
613 449
614 /* Weak group failed. Reset the group. */ 450 /* Weak group failed. Reset the group. */
615 if ((errno == EINVAL || errno == EBADF) && 451 if ((errno == EINVAL || errno == EBADF) &&
616 counter->leader != counter && 452 counter->leader != counter &&
617 counter->weak_group) { 453 counter->weak_group) {
618 counter = perf_evsel__reset_weak_group(counter); 454 counter = perf_evlist__reset_weak_group(evsel_list, counter);
619 goto try_again; 455 goto try_again;
620 } 456 }
621 457
@@ -664,11 +500,11 @@ try_again:
664 counter->supported = true; 500 counter->supported = true;
665 501
666 l = strlen(counter->unit); 502 l = strlen(counter->unit);
667 if (l > unit_width) 503 if (l > stat_config.unit_width)
668 unit_width = l; 504 stat_config.unit_width = l;
669 505
670 if (perf_evsel__should_store_id(counter) && 506 if (perf_evsel__should_store_id(counter) &&
671 store_counter_ids(counter)) 507 perf_evsel__store_ids(counter, evsel_list))
672 return -1; 508 return -1;
673 } 509 }
674 510
@@ -699,7 +535,8 @@ try_again:
699 if (err < 0) 535 if (err < 0)
700 return err; 536 return err;
701 537
702 err = perf_stat_synthesize_config(is_pipe); 538 err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list,
539 process_synthesized_event, is_pipe);
703 if (err < 0) 540 if (err < 0)
704 return err; 541 return err;
705 } 542 }
@@ -724,7 +561,7 @@ try_again:
724 break; 561 break;
725 } 562 }
726 } 563 }
727 wait4(child_pid, &status, 0, &ru_data); 564 wait4(child_pid, &status, 0, &stat_config.ru_data);
728 565
729 if (workload_exec_errno) { 566 if (workload_exec_errno) {
730 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 567 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
@@ -738,6 +575,8 @@ try_again:
738 enable_counters(); 575 enable_counters();
739 while (!done) { 576 while (!done) {
740 nanosleep(&ts, NULL); 577 nanosleep(&ts, NULL);
578 if (!is_target_alive(&target, evsel_list->threads))
579 break;
741 if (timeout) 580 if (timeout)
742 break; 581 break;
743 if (interval) { 582 if (interval) {
@@ -752,8 +591,8 @@ try_again:
752 591
753 t1 = rdclock(); 592 t1 = rdclock();
754 593
755 if (walltime_run_table) 594 if (stat_config.walltime_run_table)
756 walltime_run[run_idx] = t1 - t0; 595 stat_config.walltime_run[run_idx] = t1 - t0;
757 596
758 update_stats(&walltime_nsecs_stats, t1 - t0); 597 update_stats(&walltime_nsecs_stats, t1 - t0);
759 598
@@ -795,1105 +634,14 @@ static int run_perf_stat(int argc, const char **argv, int run_idx)
795 return ret; 634 return ret;
796} 635}
797 636
798static void print_running(u64 run, u64 ena)
799{
800 if (csv_output) {
801 fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f",
802 csv_sep,
803 run,
804 csv_sep,
805 ena ? 100.0 * run / ena : 100.0);
806 } else if (run != ena) {
807 fprintf(stat_config.output, " (%.2f%%)", 100.0 * run / ena);
808 }
809}
810
811static void print_noise_pct(double total, double avg)
812{
813 double pct = rel_stddev_stats(total, avg);
814
815 if (csv_output)
816 fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct);
817 else if (pct)
818 fprintf(stat_config.output, " ( +-%6.2f%% )", pct);
819}
820
821static void print_noise(struct perf_evsel *evsel, double avg)
822{
823 struct perf_stat_evsel *ps;
824
825 if (run_count == 1)
826 return;
827
828 ps = evsel->stats;
829 print_noise_pct(stddev_stats(&ps->res_stats[0]), avg);
830}
831
832static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
833{
834 switch (stat_config.aggr_mode) {
835 case AGGR_CORE:
836 fprintf(stat_config.output, "S%d-C%*d%s%*d%s",
837 cpu_map__id_to_socket(id),
838 csv_output ? 0 : -8,
839 cpu_map__id_to_cpu(id),
840 csv_sep,
841 csv_output ? 0 : 4,
842 nr,
843 csv_sep);
844 break;
845 case AGGR_SOCKET:
846 fprintf(stat_config.output, "S%*d%s%*d%s",
847 csv_output ? 0 : -5,
848 id,
849 csv_sep,
850 csv_output ? 0 : 4,
851 nr,
852 csv_sep);
853 break;
854 case AGGR_NONE:
855 fprintf(stat_config.output, "CPU%*d%s",
856 csv_output ? 0 : -4,
857 perf_evsel__cpus(evsel)->map[id], csv_sep);
858 break;
859 case AGGR_THREAD:
860 fprintf(stat_config.output, "%*s-%*d%s",
861 csv_output ? 0 : 16,
862 thread_map__comm(evsel->threads, id),
863 csv_output ? 0 : -8,
864 thread_map__pid(evsel->threads, id),
865 csv_sep);
866 break;
867 case AGGR_GLOBAL:
868 case AGGR_UNSET:
869 default:
870 break;
871 }
872}
873
874struct outstate {
875 FILE *fh;
876 bool newline;
877 const char *prefix;
878 int nfields;
879 int id, nr;
880 struct perf_evsel *evsel;
881};
882
883#define METRIC_LEN 35
884
885static void new_line_std(void *ctx)
886{
887 struct outstate *os = ctx;
888
889 os->newline = true;
890}
891
892static void do_new_line_std(struct outstate *os)
893{
894 fputc('\n', os->fh);
895 fputs(os->prefix, os->fh);
896 aggr_printout(os->evsel, os->id, os->nr);
897 if (stat_config.aggr_mode == AGGR_NONE)
898 fprintf(os->fh, " ");
899 fprintf(os->fh, " ");
900}
901
902static void print_metric_std(void *ctx, const char *color, const char *fmt,
903 const char *unit, double val)
904{
905 struct outstate *os = ctx;
906 FILE *out = os->fh;
907 int n;
908 bool newline = os->newline;
909
910 os->newline = false;
911
912 if (unit == NULL || fmt == NULL) {
913 fprintf(out, "%-*s", METRIC_LEN, "");
914 return;
915 }
916
917 if (newline)
918 do_new_line_std(os);
919
920 n = fprintf(out, " # ");
921 if (color)
922 n += color_fprintf(out, color, fmt, val);
923 else
924 n += fprintf(out, fmt, val);
925 fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
926}
927
928static void new_line_csv(void *ctx)
929{
930 struct outstate *os = ctx;
931 int i;
932
933 fputc('\n', os->fh);
934 if (os->prefix)
935 fprintf(os->fh, "%s%s", os->prefix, csv_sep);
936 aggr_printout(os->evsel, os->id, os->nr);
937 for (i = 0; i < os->nfields; i++)
938 fputs(csv_sep, os->fh);
939}
940
941static void print_metric_csv(void *ctx,
942 const char *color __maybe_unused,
943 const char *fmt, const char *unit, double val)
944{
945 struct outstate *os = ctx;
946 FILE *out = os->fh;
947 char buf[64], *vals, *ends;
948
949 if (unit == NULL || fmt == NULL) {
950 fprintf(out, "%s%s", csv_sep, csv_sep);
951 return;
952 }
953 snprintf(buf, sizeof(buf), fmt, val);
954 ends = vals = ltrim(buf);
955 while (isdigit(*ends) || *ends == '.')
956 ends++;
957 *ends = 0;
958 while (isspace(*unit))
959 unit++;
960 fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit);
961}
962
963/* Filter out some columns that don't work well in metrics only mode */
964
965static bool valid_only_metric(const char *unit)
966{
967 if (!unit)
968 return false;
969 if (strstr(unit, "/sec") ||
970 strstr(unit, "hz") ||
971 strstr(unit, "Hz") ||
972 strstr(unit, "CPUs utilized"))
973 return false;
974 return true;
975}
976
977static const char *fixunit(char *buf, struct perf_evsel *evsel,
978 const char *unit)
979{
980 if (!strncmp(unit, "of all", 6)) {
981 snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
982 unit);
983 return buf;
984 }
985 return unit;
986}
987
988static void print_metric_only(void *ctx, const char *color, const char *fmt,
989 const char *unit, double val)
990{
991 struct outstate *os = ctx;
992 FILE *out = os->fh;
993 char buf[1024], str[1024];
994 unsigned mlen = metric_only_len;
995
996 if (!valid_only_metric(unit))
997 return;
998 unit = fixunit(buf, os->evsel, unit);
999 if (mlen < strlen(unit))
1000 mlen = strlen(unit) + 1;
1001
1002 if (color)
1003 mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
1004
1005 color_snprintf(str, sizeof(str), color ?: "", fmt, val);
1006 fprintf(out, "%*s ", mlen, str);
1007}
1008
1009static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
1010 const char *fmt,
1011 const char *unit, double val)
1012{
1013 struct outstate *os = ctx;
1014 FILE *out = os->fh;
1015 char buf[64], *vals, *ends;
1016 char tbuf[1024];
1017
1018 if (!valid_only_metric(unit))
1019 return;
1020 unit = fixunit(tbuf, os->evsel, unit);
1021 snprintf(buf, sizeof buf, fmt, val);
1022 ends = vals = ltrim(buf);
1023 while (isdigit(*ends) || *ends == '.')
1024 ends++;
1025 *ends = 0;
1026 fprintf(out, "%s%s", vals, csv_sep);
1027}
1028
1029static void new_line_metric(void *ctx __maybe_unused)
1030{
1031}
1032
1033static void print_metric_header(void *ctx, const char *color __maybe_unused,
1034 const char *fmt __maybe_unused,
1035 const char *unit, double val __maybe_unused)
1036{
1037 struct outstate *os = ctx;
1038 char tbuf[1024];
1039
1040 if (!valid_only_metric(unit))
1041 return;
1042 unit = fixunit(tbuf, os->evsel, unit);
1043 if (csv_output)
1044 fprintf(os->fh, "%s%s", unit, csv_sep);
1045 else
1046 fprintf(os->fh, "%*s ", metric_only_len, unit);
1047}
1048
1049static int first_shadow_cpu(struct perf_evsel *evsel, int id)
1050{
1051 int i;
1052
1053 if (!aggr_get_id)
1054 return 0;
1055
1056 if (stat_config.aggr_mode == AGGR_NONE)
1057 return id;
1058
1059 if (stat_config.aggr_mode == AGGR_GLOBAL)
1060 return 0;
1061
1062 for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
1063 int cpu2 = perf_evsel__cpus(evsel)->map[i];
1064
1065 if (aggr_get_id(evsel_list->cpus, cpu2) == id)
1066 return cpu2;
1067 }
1068 return 0;
1069}
1070
1071static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1072{
1073 FILE *output = stat_config.output;
1074 double sc = evsel->scale;
1075 const char *fmt;
1076
1077 if (csv_output) {
1078 fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
1079 } else {
1080 if (big_num)
1081 fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
1082 else
1083 fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
1084 }
1085
1086 aggr_printout(evsel, id, nr);
1087
1088 fprintf(output, fmt, avg, csv_sep);
1089
1090 if (evsel->unit)
1091 fprintf(output, "%-*s%s",
1092 csv_output ? 0 : unit_width,
1093 evsel->unit, csv_sep);
1094
1095 fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));
1096
1097 if (evsel->cgrp)
1098 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
1099}
1100
1101static bool is_mixed_hw_group(struct perf_evsel *counter)
1102{
1103 struct perf_evlist *evlist = counter->evlist;
1104 u32 pmu_type = counter->attr.type;
1105 struct perf_evsel *pos;
1106
1107 if (counter->nr_members < 2)
1108 return false;
1109
1110 evlist__for_each_entry(evlist, pos) {
1111 /* software events can be part of any hardware group */
1112 if (pos->attr.type == PERF_TYPE_SOFTWARE)
1113 continue;
1114 if (pmu_type == PERF_TYPE_SOFTWARE) {
1115 pmu_type = pos->attr.type;
1116 continue;
1117 }
1118 if (pmu_type != pos->attr.type)
1119 return true;
1120 }
1121
1122 return false;
1123}
1124
1125static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1126 char *prefix, u64 run, u64 ena, double noise,
1127 struct runtime_stat *st)
1128{
1129 struct perf_stat_output_ctx out;
1130 struct outstate os = {
1131 .fh = stat_config.output,
1132 .prefix = prefix ? prefix : "",
1133 .id = id,
1134 .nr = nr,
1135 .evsel = counter,
1136 };
1137 print_metric_t pm = print_metric_std;
1138 void (*nl)(void *);
1139
1140 if (metric_only) {
1141 nl = new_line_metric;
1142 if (csv_output)
1143 pm = print_metric_only_csv;
1144 else
1145 pm = print_metric_only;
1146 } else
1147 nl = new_line_std;
1148
1149 if (csv_output && !metric_only) {
1150 static int aggr_fields[] = {
1151 [AGGR_GLOBAL] = 0,
1152 [AGGR_THREAD] = 1,
1153 [AGGR_NONE] = 1,
1154 [AGGR_SOCKET] = 2,
1155 [AGGR_CORE] = 2,
1156 };
1157
1158 pm = print_metric_csv;
1159 nl = new_line_csv;
1160 os.nfields = 3;
1161 os.nfields += aggr_fields[stat_config.aggr_mode];
1162 if (counter->cgrp)
1163 os.nfields++;
1164 }
1165 if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
1166 if (metric_only) {
1167 pm(&os, NULL, "", "", 0);
1168 return;
1169 }
1170 aggr_printout(counter, id, nr);
1171
1172 fprintf(stat_config.output, "%*s%s",
1173 csv_output ? 0 : 18,
1174 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
1175 csv_sep);
1176
1177 if (counter->supported) {
1178 print_free_counters_hint = 1;
1179 if (is_mixed_hw_group(counter))
1180 print_mixed_hw_group_error = 1;
1181 }
1182
1183 fprintf(stat_config.output, "%-*s%s",
1184 csv_output ? 0 : unit_width,
1185 counter->unit, csv_sep);
1186
1187 fprintf(stat_config.output, "%*s",
1188 csv_output ? 0 : -25,
1189 perf_evsel__name(counter));
1190
1191 if (counter->cgrp)
1192 fprintf(stat_config.output, "%s%s",
1193 csv_sep, counter->cgrp->name);
1194
1195 if (!csv_output)
1196 pm(&os, NULL, NULL, "", 0);
1197 print_noise(counter, noise);
1198 print_running(run, ena);
1199 if (csv_output)
1200 pm(&os, NULL, NULL, "", 0);
1201 return;
1202 }
1203
1204 if (!metric_only)
1205 abs_printout(id, nr, counter, uval);
1206
1207 out.print_metric = pm;
1208 out.new_line = nl;
1209 out.ctx = &os;
1210 out.force_header = false;
1211
1212 if (csv_output && !metric_only) {
1213 print_noise(counter, noise);
1214 print_running(run, ena);
1215 }
1216
1217 perf_stat__print_shadow_stats(counter, uval,
1218 first_shadow_cpu(counter, id),
1219 &out, &metric_events, st);
1220 if (!csv_output && !metric_only) {
1221 print_noise(counter, noise);
1222 print_running(run, ena);
1223 }
1224}
1225
1226static void aggr_update_shadow(void)
1227{
1228 int cpu, s2, id, s;
1229 u64 val;
1230 struct perf_evsel *counter;
1231
1232 for (s = 0; s < aggr_map->nr; s++) {
1233 id = aggr_map->map[s];
1234 evlist__for_each_entry(evsel_list, counter) {
1235 val = 0;
1236 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1237 s2 = aggr_get_id(evsel_list->cpus, cpu);
1238 if (s2 != id)
1239 continue;
1240 val += perf_counts(counter->counts, cpu, 0)->val;
1241 }
1242 perf_stat__update_shadow_stats(counter, val,
1243 first_shadow_cpu(counter, id),
1244 &rt_stat);
1245 }
1246 }
1247}
1248
1249static void uniquify_event_name(struct perf_evsel *counter)
1250{
1251 char *new_name;
1252 char *config;
1253
1254 if (counter->uniquified_name ||
1255 !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
1256 strlen(counter->pmu_name)))
1257 return;
1258
1259 config = strchr(counter->name, '/');
1260 if (config) {
1261 if (asprintf(&new_name,
1262 "%s%s", counter->pmu_name, config) > 0) {
1263 free(counter->name);
1264 counter->name = new_name;
1265 }
1266 } else {
1267 if (asprintf(&new_name,
1268 "%s [%s]", counter->name, counter->pmu_name) > 0) {
1269 free(counter->name);
1270 counter->name = new_name;
1271 }
1272 }
1273
1274 counter->uniquified_name = true;
1275}
1276
1277static void collect_all_aliases(struct perf_evsel *counter,
1278 void (*cb)(struct perf_evsel *counter, void *data,
1279 bool first),
1280 void *data)
1281{
1282 struct perf_evsel *alias;
1283
1284 alias = list_prepare_entry(counter, &(evsel_list->entries), node);
1285 list_for_each_entry_continue (alias, &evsel_list->entries, node) {
1286 if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
1287 alias->scale != counter->scale ||
1288 alias->cgrp != counter->cgrp ||
1289 strcmp(alias->unit, counter->unit) ||
1290 perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
1291 break;
1292 alias->merged_stat = true;
1293 cb(alias, data, false);
1294 }
1295}
1296
1297static bool collect_data(struct perf_evsel *counter,
1298 void (*cb)(struct perf_evsel *counter, void *data,
1299 bool first),
1300 void *data)
1301{
1302 if (counter->merged_stat)
1303 return false;
1304 cb(counter, data, true);
1305 if (no_merge)
1306 uniquify_event_name(counter);
1307 else if (counter->auto_merge_stats)
1308 collect_all_aliases(counter, cb, data);
1309 return true;
1310}
1311
1312struct aggr_data {
1313 u64 ena, run, val;
1314 int id;
1315 int nr;
1316 int cpu;
1317};
1318
1319static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
1320{
1321 struct aggr_data *ad = data;
1322 int cpu, s2;
1323
1324 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1325 struct perf_counts_values *counts;
1326
1327 s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
1328 if (s2 != ad->id)
1329 continue;
1330 if (first)
1331 ad->nr++;
1332 counts = perf_counts(counter->counts, cpu, 0);
1333 /*
1334 * When any result is bad, make them all to give
1335 * consistent output in interval mode.
1336 */
1337 if (counts->ena == 0 || counts->run == 0 ||
1338 counter->counts->scaled == -1) {
1339 ad->ena = 0;
1340 ad->run = 0;
1341 break;
1342 }
1343 ad->val += counts->val;
1344 ad->ena += counts->ena;
1345 ad->run += counts->run;
1346 }
1347}
1348
1349static void print_aggr(char *prefix)
1350{
1351 FILE *output = stat_config.output;
1352 struct perf_evsel *counter;
1353 int s, id, nr;
1354 double uval;
1355 u64 ena, run, val;
1356 bool first;
1357
1358 if (!(aggr_map || aggr_get_id))
1359 return;
1360
1361 aggr_update_shadow();
1362
1363 /*
1364 * With metric_only everything is on a single line.
1365 * Without each counter has its own line.
1366 */
1367 for (s = 0; s < aggr_map->nr; s++) {
1368 struct aggr_data ad;
1369 if (prefix && metric_only)
1370 fprintf(output, "%s", prefix);
1371
1372 ad.id = id = aggr_map->map[s];
1373 first = true;
1374 evlist__for_each_entry(evsel_list, counter) {
1375 if (is_duration_time(counter))
1376 continue;
1377
1378 ad.val = ad.ena = ad.run = 0;
1379 ad.nr = 0;
1380 if (!collect_data(counter, aggr_cb, &ad))
1381 continue;
1382 nr = ad.nr;
1383 ena = ad.ena;
1384 run = ad.run;
1385 val = ad.val;
1386 if (first && metric_only) {
1387 first = false;
1388 aggr_printout(counter, id, nr);
1389 }
1390 if (prefix && !metric_only)
1391 fprintf(output, "%s", prefix);
1392
1393 uval = val * counter->scale;
1394 printout(id, nr, counter, uval, prefix, run, ena, 1.0,
1395 &rt_stat);
1396 if (!metric_only)
1397 fputc('\n', output);
1398 }
1399 if (metric_only)
1400 fputc('\n', output);
1401 }
1402}
1403
1404static int cmp_val(const void *a, const void *b)
1405{
1406 return ((struct perf_aggr_thread_value *)b)->val -
1407 ((struct perf_aggr_thread_value *)a)->val;
1408}
1409
1410static struct perf_aggr_thread_value *sort_aggr_thread(
1411 struct perf_evsel *counter,
1412 int nthreads, int ncpus,
1413 int *ret)
1414{
1415 int cpu, thread, i = 0;
1416 double uval;
1417 struct perf_aggr_thread_value *buf;
1418
1419 buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
1420 if (!buf)
1421 return NULL;
1422
1423 for (thread = 0; thread < nthreads; thread++) {
1424 u64 ena = 0, run = 0, val = 0;
1425
1426 for (cpu = 0; cpu < ncpus; cpu++) {
1427 val += perf_counts(counter->counts, cpu, thread)->val;
1428 ena += perf_counts(counter->counts, cpu, thread)->ena;
1429 run += perf_counts(counter->counts, cpu, thread)->run;
1430 }
1431
1432 uval = val * counter->scale;
1433
1434 /*
1435 * Skip value 0 when enabling --per-thread globally,
1436 * otherwise too many 0 output.
1437 */
1438 if (uval == 0.0 && target__has_per_thread(&target))
1439 continue;
1440
1441 buf[i].counter = counter;
1442 buf[i].id = thread;
1443 buf[i].uval = uval;
1444 buf[i].val = val;
1445 buf[i].run = run;
1446 buf[i].ena = ena;
1447 i++;
1448 }
1449
1450 qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
1451
1452 if (ret)
1453 *ret = i;
1454
1455 return buf;
1456}
1457
1458static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
1459{
1460 FILE *output = stat_config.output;
1461 int nthreads = thread_map__nr(counter->threads);
1462 int ncpus = cpu_map__nr(counter->cpus);
1463 int thread, sorted_threads, id;
1464 struct perf_aggr_thread_value *buf;
1465
1466 buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads);
1467 if (!buf) {
1468 perror("cannot sort aggr thread");
1469 return;
1470 }
1471
1472 for (thread = 0; thread < sorted_threads; thread++) {
1473 if (prefix)
1474 fprintf(output, "%s", prefix);
1475
1476 id = buf[thread].id;
1477 if (stat_config.stats)
1478 printout(id, 0, buf[thread].counter, buf[thread].uval,
1479 prefix, buf[thread].run, buf[thread].ena, 1.0,
1480 &stat_config.stats[id]);
1481 else
1482 printout(id, 0, buf[thread].counter, buf[thread].uval,
1483 prefix, buf[thread].run, buf[thread].ena, 1.0,
1484 &rt_stat);
1485 fputc('\n', output);
1486 }
1487
1488 free(buf);
1489}
1490
1491struct caggr_data {
1492 double avg, avg_enabled, avg_running;
1493};
1494
1495static void counter_aggr_cb(struct perf_evsel *counter, void *data,
1496 bool first __maybe_unused)
1497{
1498 struct caggr_data *cd = data;
1499 struct perf_stat_evsel *ps = counter->stats;
1500
1501 cd->avg += avg_stats(&ps->res_stats[0]);
1502 cd->avg_enabled += avg_stats(&ps->res_stats[1]);
1503 cd->avg_running += avg_stats(&ps->res_stats[2]);
1504}
1505
1506/*
1507 * Print out the results of a single counter:
1508 * aggregated counts in system-wide mode
1509 */
1510static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1511{
1512 FILE *output = stat_config.output;
1513 double uval;
1514 struct caggr_data cd = { .avg = 0.0 };
1515
1516 if (!collect_data(counter, counter_aggr_cb, &cd))
1517 return;
1518
1519 if (prefix && !metric_only)
1520 fprintf(output, "%s", prefix);
1521
1522 uval = cd.avg * counter->scale;
1523 printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
1524 cd.avg, &rt_stat);
1525 if (!metric_only)
1526 fprintf(output, "\n");
1527}
1528
1529static void counter_cb(struct perf_evsel *counter, void *data,
1530 bool first __maybe_unused)
1531{
1532 struct aggr_data *ad = data;
1533
1534 ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
1535 ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
1536 ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
1537}
1538
1539/*
1540 * Print out the results of a single counter:
1541 * does not use aggregated count in system-wide
1542 */
1543static void print_counter(struct perf_evsel *counter, char *prefix)
1544{
1545 FILE *output = stat_config.output;
1546 u64 ena, run, val;
1547 double uval;
1548 int cpu;
1549
1550 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1551 struct aggr_data ad = { .cpu = cpu };
1552
1553 if (!collect_data(counter, counter_cb, &ad))
1554 return;
1555 val = ad.val;
1556 ena = ad.ena;
1557 run = ad.run;
1558
1559 if (prefix)
1560 fprintf(output, "%s", prefix);
1561
1562 uval = val * counter->scale;
1563 printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
1564 &rt_stat);
1565
1566 fputc('\n', output);
1567 }
1568}
1569
1570static void print_no_aggr_metric(char *prefix)
1571{
1572 int cpu;
1573 int nrcpus = 0;
1574 struct perf_evsel *counter;
1575 u64 ena, run, val;
1576 double uval;
1577
1578 nrcpus = evsel_list->cpus->nr;
1579 for (cpu = 0; cpu < nrcpus; cpu++) {
1580 bool first = true;
1581
1582 if (prefix)
1583 fputs(prefix, stat_config.output);
1584 evlist__for_each_entry(evsel_list, counter) {
1585 if (is_duration_time(counter))
1586 continue;
1587 if (first) {
1588 aggr_printout(counter, cpu, 0);
1589 first = false;
1590 }
1591 val = perf_counts(counter->counts, cpu, 0)->val;
1592 ena = perf_counts(counter->counts, cpu, 0)->ena;
1593 run = perf_counts(counter->counts, cpu, 0)->run;
1594
1595 uval = val * counter->scale;
1596 printout(cpu, 0, counter, uval, prefix, run, ena, 1.0,
1597 &rt_stat);
1598 }
1599 fputc('\n', stat_config.output);
1600 }
1601}
1602
1603static int aggr_header_lens[] = {
1604 [AGGR_CORE] = 18,
1605 [AGGR_SOCKET] = 12,
1606 [AGGR_NONE] = 6,
1607 [AGGR_THREAD] = 24,
1608 [AGGR_GLOBAL] = 0,
1609};
1610
1611static const char *aggr_header_csv[] = {
1612 [AGGR_CORE] = "core,cpus,",
1613 [AGGR_SOCKET] = "socket,cpus",
1614 [AGGR_NONE] = "cpu,",
1615 [AGGR_THREAD] = "comm-pid,",
1616 [AGGR_GLOBAL] = ""
1617};
1618
1619static void print_metric_headers(const char *prefix, bool no_indent)
1620{
1621 struct perf_stat_output_ctx out;
1622 struct perf_evsel *counter;
1623 struct outstate os = {
1624 .fh = stat_config.output
1625 };
1626
1627 if (prefix)
1628 fprintf(stat_config.output, "%s", prefix);
1629
1630 if (!csv_output && !no_indent)
1631 fprintf(stat_config.output, "%*s",
1632 aggr_header_lens[stat_config.aggr_mode], "");
1633 if (csv_output) {
1634 if (stat_config.interval)
1635 fputs("time,", stat_config.output);
1636 fputs(aggr_header_csv[stat_config.aggr_mode],
1637 stat_config.output);
1638 }
1639
1640 /* Print metrics headers only */
1641 evlist__for_each_entry(evsel_list, counter) {
1642 if (is_duration_time(counter))
1643 continue;
1644 os.evsel = counter;
1645 out.ctx = &os;
1646 out.print_metric = print_metric_header;
1647 out.new_line = new_line_metric;
1648 out.force_header = true;
1649 os.evsel = counter;
1650 perf_stat__print_shadow_stats(counter, 0,
1651 0,
1652 &out,
1653 &metric_events,
1654 &rt_stat);
1655 }
1656 fputc('\n', stat_config.output);
1657}
1658
1659static void print_interval(char *prefix, struct timespec *ts)
1660{
1661 FILE *output = stat_config.output;
1662 static int num_print_interval;
1663
1664 if (interval_clear)
1665 puts(CONSOLE_CLEAR);
1666
1667 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
1668
1669 if ((num_print_interval == 0 && !csv_output) || interval_clear) {
1670 switch (stat_config.aggr_mode) {
1671 case AGGR_SOCKET:
1672 fprintf(output, "# time socket cpus");
1673 if (!metric_only)
1674 fprintf(output, " counts %*s events\n", unit_width, "unit");
1675 break;
1676 case AGGR_CORE:
1677 fprintf(output, "# time core cpus");
1678 if (!metric_only)
1679 fprintf(output, " counts %*s events\n", unit_width, "unit");
1680 break;
1681 case AGGR_NONE:
1682 fprintf(output, "# time CPU ");
1683 if (!metric_only)
1684 fprintf(output, " counts %*s events\n", unit_width, "unit");
1685 break;
1686 case AGGR_THREAD:
1687 fprintf(output, "# time comm-pid");
1688 if (!metric_only)
1689 fprintf(output, " counts %*s events\n", unit_width, "unit");
1690 break;
1691 case AGGR_GLOBAL:
1692 default:
1693 fprintf(output, "# time");
1694 if (!metric_only)
1695 fprintf(output, " counts %*s events\n", unit_width, "unit");
1696 case AGGR_UNSET:
1697 break;
1698 }
1699 }
1700
1701 if ((num_print_interval == 0 || interval_clear) && metric_only)
1702 print_metric_headers(" ", true);
1703 if (++num_print_interval == 25)
1704 num_print_interval = 0;
1705}
1706
1707static void print_header(int argc, const char **argv)
1708{
1709 FILE *output = stat_config.output;
1710 int i;
1711
1712 fflush(stdout);
1713
1714 if (!csv_output) {
1715 fprintf(output, "\n");
1716 fprintf(output, " Performance counter stats for ");
1717 if (target.system_wide)
1718 fprintf(output, "\'system wide");
1719 else if (target.cpu_list)
1720 fprintf(output, "\'CPU(s) %s", target.cpu_list);
1721 else if (!target__has_task(&target)) {
1722 fprintf(output, "\'%s", argv ? argv[0] : "pipe");
1723 for (i = 1; argv && (i < argc); i++)
1724 fprintf(output, " %s", argv[i]);
1725 } else if (target.pid)
1726 fprintf(output, "process id \'%s", target.pid);
1727 else
1728 fprintf(output, "thread id \'%s", target.tid);
1729
1730 fprintf(output, "\'");
1731 if (run_count > 1)
1732 fprintf(output, " (%d runs)", run_count);
1733 fprintf(output, ":\n\n");
1734 }
1735}
1736
1737static int get_precision(double num)
1738{
1739 if (num > 1)
1740 return 0;
1741
1742 return lround(ceil(-log10(num)));
1743}
1744
1745static void print_table(FILE *output, int precision, double avg)
1746{
1747 char tmp[64];
1748 int idx, indent = 0;
1749
1750 scnprintf(tmp, 64, " %17.*f", precision, avg);
1751 while (tmp[indent] == ' ')
1752 indent++;
1753
1754 fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
1755
1756 for (idx = 0; idx < run_count; idx++) {
1757 double run = (double) walltime_run[idx] / NSEC_PER_SEC;
1758 int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
1759
1760 fprintf(output, " %17.*f (%+.*f) ",
1761 precision, run, precision, run - avg);
1762
1763 for (h = 0; h < n; h++)
1764 fprintf(output, "#");
1765
1766 fprintf(output, "\n");
1767 }
1768
1769 fprintf(output, "\n%*s# Final result:\n", indent, "");
1770}
1771
1772static double timeval2double(struct timeval *t)
1773{
1774 return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
1775}
1776
1777static void print_footer(void)
1778{
1779 double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
1780 FILE *output = stat_config.output;
1781 int n;
1782
1783 if (!null_run)
1784 fprintf(output, "\n");
1785
1786 if (run_count == 1) {
1787 fprintf(output, " %17.9f seconds time elapsed", avg);
1788
1789 if (ru_display) {
1790 double ru_utime = timeval2double(&ru_data.ru_utime);
1791 double ru_stime = timeval2double(&ru_data.ru_stime);
1792
1793 fprintf(output, "\n\n");
1794 fprintf(output, " %17.9f seconds user\n", ru_utime);
1795 fprintf(output, " %17.9f seconds sys\n", ru_stime);
1796 }
1797 } else {
1798 double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
1799 /*
1800 * Display at most 2 more significant
1801 * digits than the stddev inaccuracy.
1802 */
1803 int precision = get_precision(sd) + 2;
1804
1805 if (walltime_run_table)
1806 print_table(output, precision, avg);
1807
1808 fprintf(output, " %17.*f +- %.*f seconds time elapsed",
1809 precision, avg, precision, sd);
1810
1811 print_noise_pct(sd, avg);
1812 }
1813 fprintf(output, "\n\n");
1814
1815 if (print_free_counters_hint &&
1816 sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
1817 n > 0)
1818 fprintf(output,
1819"Some events weren't counted. Try disabling the NMI watchdog:\n"
1820" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1821" perf stat ...\n"
1822" echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1823
1824 if (print_mixed_hw_group_error)
1825 fprintf(output,
1826 "The events in group usually have to be from "
1827 "the same PMU. Try reorganizing the group.\n");
1828}
1829
1830static void print_counters(struct timespec *ts, int argc, const char **argv) 637static void print_counters(struct timespec *ts, int argc, const char **argv)
1831{ 638{
1832 int interval = stat_config.interval;
1833 struct perf_evsel *counter;
1834 char buf[64], *prefix = NULL;
1835
1836 /* Do not print anything if we record to the pipe. */ 639 /* Do not print anything if we record to the pipe. */
1837 if (STAT_RECORD && perf_stat.data.is_pipe) 640 if (STAT_RECORD && perf_stat.data.is_pipe)
1838 return; 641 return;
1839 642
1840 if (interval) 643 perf_evlist__print_counters(evsel_list, &stat_config, &target,
1841 print_interval(prefix = buf, ts); 644 ts, argc, argv);
1842 else
1843 print_header(argc, argv);
1844
1845 if (metric_only) {
1846 static int num_print_iv;
1847
1848 if (num_print_iv == 0 && !interval)
1849 print_metric_headers(prefix, false);
1850 if (num_print_iv++ == 25)
1851 num_print_iv = 0;
1852 if (stat_config.aggr_mode == AGGR_GLOBAL && prefix)
1853 fprintf(stat_config.output, "%s", prefix);
1854 }
1855
1856 switch (stat_config.aggr_mode) {
1857 case AGGR_CORE:
1858 case AGGR_SOCKET:
1859 print_aggr(prefix);
1860 break;
1861 case AGGR_THREAD:
1862 evlist__for_each_entry(evsel_list, counter) {
1863 if (is_duration_time(counter))
1864 continue;
1865 print_aggr_thread(counter, prefix);
1866 }
1867 break;
1868 case AGGR_GLOBAL:
1869 evlist__for_each_entry(evsel_list, counter) {
1870 if (is_duration_time(counter))
1871 continue;
1872 print_counter_aggr(counter, prefix);
1873 }
1874 if (metric_only)
1875 fputc('\n', stat_config.output);
1876 break;
1877 case AGGR_NONE:
1878 if (metric_only)
1879 print_no_aggr_metric(prefix);
1880 else {
1881 evlist__for_each_entry(evsel_list, counter) {
1882 if (is_duration_time(counter))
1883 continue;
1884 print_counter(counter, prefix);
1885 }
1886 }
1887 break;
1888 case AGGR_UNSET:
1889 default:
1890 break;
1891 }
1892
1893 if (!interval && !csv_output)
1894 print_footer();
1895
1896 fflush(stat_config.output);
1897} 645}
1898 646
1899static volatile int signr = -1; 647static volatile int signr = -1;
@@ -1950,7 +698,7 @@ static int enable_metric_only(const struct option *opt __maybe_unused,
1950 const char *s __maybe_unused, int unset) 698 const char *s __maybe_unused, int unset)
1951{ 699{
1952 force_metric_only = true; 700 force_metric_only = true;
1953 metric_only = !unset; 701 stat_config.metric_only = !unset;
1954 return 0; 702 return 0;
1955} 703}
1956 704
@@ -1958,7 +706,7 @@ static int parse_metric_groups(const struct option *opt,
1958 const char *str, 706 const char *str,
1959 int unset __maybe_unused) 707 int unset __maybe_unused)
1960{ 708{
1961 return metricgroup__parse_groups(opt, str, &metric_events); 709 return metricgroup__parse_groups(opt, str, &stat_config.metric_events);
1962} 710}
1963 711
1964static const struct option stat_options[] = { 712static const struct option stat_options[] = {
@@ -1969,7 +717,7 @@ static const struct option stat_options[] = {
1969 parse_events_option), 717 parse_events_option),
1970 OPT_CALLBACK(0, "filter", &evsel_list, "filter", 718 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1971 "event filter", parse_filter), 719 "event filter", parse_filter),
1972 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 720 OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit,
1973 "child tasks do not inherit counters"), 721 "child tasks do not inherit counters"),
1974 OPT_STRING('p', "pid", &target.pid, "pid", 722 OPT_STRING('p', "pid", &target.pid, "pid",
1975 "stat events on existing process id"), 723 "stat events on existing process id"),
@@ -1982,11 +730,11 @@ static const struct option stat_options[] = {
1982 OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"), 730 OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"),
1983 OPT_INCR('v', "verbose", &verbose, 731 OPT_INCR('v', "verbose", &verbose,
1984 "be more verbose (show counter open errors, etc)"), 732 "be more verbose (show counter open errors, etc)"),
1985 OPT_INTEGER('r', "repeat", &run_count, 733 OPT_INTEGER('r', "repeat", &stat_config.run_count,
1986 "repeat command and print average + stddev (max: 100, forever: 0)"), 734 "repeat command and print average + stddev (max: 100, forever: 0)"),
1987 OPT_BOOLEAN(0, "table", &walltime_run_table, 735 OPT_BOOLEAN(0, "table", &stat_config.walltime_run_table,
1988 "display details about each run (only with -r option)"), 736 "display details about each run (only with -r option)"),
1989 OPT_BOOLEAN('n', "null", &null_run, 737 OPT_BOOLEAN('n', "null", &stat_config.null_run,
1990 "null run - dont start any counters"), 738 "null run - dont start any counters"),
1991 OPT_INCR('d', "detailed", &detailed_run, 739 OPT_INCR('d', "detailed", &detailed_run,
1992 "detailed run - start a lot of events"), 740 "detailed run - start a lot of events"),
@@ -1999,8 +747,8 @@ static const struct option stat_options[] = {
1999 "list of cpus to monitor in system-wide"), 747 "list of cpus to monitor in system-wide"),
2000 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode, 748 OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
2001 "disable CPU count aggregation", AGGR_NONE), 749 "disable CPU count aggregation", AGGR_NONE),
2002 OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"), 750 OPT_BOOLEAN(0, "no-merge", &stat_config.no_merge, "Do not merge identical named events"),
2003 OPT_STRING('x', "field-separator", &csv_sep, "separator", 751 OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",
2004 "print counts with custom separator"), 752 "print counts with custom separator"),
2005 OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 753 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
2006 "monitor event in cgroup name only", parse_cgroups), 754 "monitor event in cgroup name only", parse_cgroups),
@@ -2017,7 +765,7 @@ static const struct option stat_options[] = {
2017 "(overhead is possible for values <= 100ms)"), 765 "(overhead is possible for values <= 100ms)"),
2018 OPT_INTEGER(0, "interval-count", &stat_config.times, 766 OPT_INTEGER(0, "interval-count", &stat_config.times,
2019 "print counts for fixed number of times"), 767 "print counts for fixed number of times"),
2020 OPT_BOOLEAN(0, "interval-clear", &interval_clear, 768 OPT_BOOLEAN(0, "interval-clear", &stat_config.interval_clear,
2021 "clear screen in between new interval"), 769 "clear screen in between new interval"),
2022 OPT_UINTEGER(0, "timeout", &stat_config.timeout, 770 OPT_UINTEGER(0, "timeout", &stat_config.timeout,
2023 "stop workload and print counts after a timeout period in ms (>= 10ms)"), 771 "stop workload and print counts after a timeout period in ms (>= 10ms)"),
@@ -2027,9 +775,9 @@ static const struct option stat_options[] = {
2027 "aggregate counts per physical processor core", AGGR_CORE), 775 "aggregate counts per physical processor core", AGGR_CORE),
2028 OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode, 776 OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode,
2029 "aggregate counts per thread", AGGR_THREAD), 777 "aggregate counts per thread", AGGR_THREAD),
2030 OPT_UINTEGER('D', "delay", &initial_delay, 778 OPT_UINTEGER('D', "delay", &stat_config.initial_delay,
2031 "ms to wait before starting measurement after program start"), 779 "ms to wait before starting measurement after program start"),
2032 OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL, 780 OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL,
2033 "Only print computed metrics. No raw values", enable_metric_only), 781 "Only print computed metrics. No raw values", enable_metric_only),
2034 OPT_BOOLEAN(0, "topdown", &topdown_run, 782 OPT_BOOLEAN(0, "topdown", &topdown_run,
2035 "measure topdown level 1 statistics"), 783 "measure topdown level 1 statistics"),
@@ -2041,12 +789,14 @@ static const struct option stat_options[] = {
2041 OPT_END() 789 OPT_END()
2042}; 790};
2043 791
2044static int perf_stat__get_socket(struct cpu_map *map, int cpu) 792static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
793 struct cpu_map *map, int cpu)
2045{ 794{
2046 return cpu_map__get_socket(map, cpu, NULL); 795 return cpu_map__get_socket(map, cpu, NULL);
2047} 796}
2048 797
2049static int perf_stat__get_core(struct cpu_map *map, int cpu) 798static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused,
799 struct cpu_map *map, int cpu)
2050{ 800{
2051 return cpu_map__get_core(map, cpu, NULL); 801 return cpu_map__get_core(map, cpu, NULL);
2052} 802}
@@ -2063,9 +813,8 @@ static int cpu_map__get_max(struct cpu_map *map)
2063 return max; 813 return max;
2064} 814}
2065 815
2066static struct cpu_map *cpus_aggr_map; 816static int perf_stat__get_aggr(struct perf_stat_config *config,
2067 817 aggr_get_id_t get_id, struct cpu_map *map, int idx)
2068static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx)
2069{ 818{
2070 int cpu; 819 int cpu;
2071 820
@@ -2074,20 +823,22 @@ static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int id
2074 823
2075 cpu = map->map[idx]; 824 cpu = map->map[idx];
2076 825
2077 if (cpus_aggr_map->map[cpu] == -1) 826 if (config->cpus_aggr_map->map[cpu] == -1)
2078 cpus_aggr_map->map[cpu] = get_id(map, idx); 827 config->cpus_aggr_map->map[cpu] = get_id(config, map, idx);
2079 828
2080 return cpus_aggr_map->map[cpu]; 829 return config->cpus_aggr_map->map[cpu];
2081} 830}
2082 831
2083static int perf_stat__get_socket_cached(struct cpu_map *map, int idx) 832static int perf_stat__get_socket_cached(struct perf_stat_config *config,
833 struct cpu_map *map, int idx)
2084{ 834{
2085 return perf_stat__get_aggr(perf_stat__get_socket, map, idx); 835 return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx);
2086} 836}
2087 837
2088static int perf_stat__get_core_cached(struct cpu_map *map, int idx) 838static int perf_stat__get_core_cached(struct perf_stat_config *config,
839 struct cpu_map *map, int idx)
2089{ 840{
2090 return perf_stat__get_aggr(perf_stat__get_core, map, idx); 841 return perf_stat__get_aggr(config, perf_stat__get_core, map, idx);
2091} 842}
2092 843
2093static int perf_stat_init_aggr_mode(void) 844static int perf_stat_init_aggr_mode(void)
@@ -2096,18 +847,18 @@ static int perf_stat_init_aggr_mode(void)
2096 847
2097 switch (stat_config.aggr_mode) { 848 switch (stat_config.aggr_mode) {
2098 case AGGR_SOCKET: 849 case AGGR_SOCKET:
2099 if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { 850 if (cpu_map__build_socket_map(evsel_list->cpus, &stat_config.aggr_map)) {
2100 perror("cannot build socket map"); 851 perror("cannot build socket map");
2101 return -1; 852 return -1;
2102 } 853 }
2103 aggr_get_id = perf_stat__get_socket_cached; 854 stat_config.aggr_get_id = perf_stat__get_socket_cached;
2104 break; 855 break;
2105 case AGGR_CORE: 856 case AGGR_CORE:
2106 if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { 857 if (cpu_map__build_core_map(evsel_list->cpus, &stat_config.aggr_map)) {
2107 perror("cannot build core map"); 858 perror("cannot build core map");
2108 return -1; 859 return -1;
2109 } 860 }
2110 aggr_get_id = perf_stat__get_core_cached; 861 stat_config.aggr_get_id = perf_stat__get_core_cached;
2111 break; 862 break;
2112 case AGGR_NONE: 863 case AGGR_NONE:
2113 case AGGR_GLOBAL: 864 case AGGR_GLOBAL:
@@ -2123,16 +874,16 @@ static int perf_stat_init_aggr_mode(void)
2123 * the aggregation translate cpumap. 874 * the aggregation translate cpumap.
2124 */ 875 */
2125 nr = cpu_map__get_max(evsel_list->cpus); 876 nr = cpu_map__get_max(evsel_list->cpus);
2126 cpus_aggr_map = cpu_map__empty_new(nr + 1); 877 stat_config.cpus_aggr_map = cpu_map__empty_new(nr + 1);
2127 return cpus_aggr_map ? 0 : -ENOMEM; 878 return stat_config.cpus_aggr_map ? 0 : -ENOMEM;
2128} 879}
2129 880
2130static void perf_stat__exit_aggr_mode(void) 881static void perf_stat__exit_aggr_mode(void)
2131{ 882{
2132 cpu_map__put(aggr_map); 883 cpu_map__put(stat_config.aggr_map);
2133 cpu_map__put(cpus_aggr_map); 884 cpu_map__put(stat_config.cpus_aggr_map);
2134 aggr_map = NULL; 885 stat_config.aggr_map = NULL;
2135 cpus_aggr_map = NULL; 886 stat_config.cpus_aggr_map = NULL;
2136} 887}
2137 888
2138static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx) 889static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx)
@@ -2190,12 +941,14 @@ static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus,
2190 return cpu_map__build_map(cpus, corep, perf_env__get_core, env); 941 return cpu_map__build_map(cpus, corep, perf_env__get_core, env);
2191} 942}
2192 943
2193static int perf_stat__get_socket_file(struct cpu_map *map, int idx) 944static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
945 struct cpu_map *map, int idx)
2194{ 946{
2195 return perf_env__get_socket(map, idx, &perf_stat.session->header.env); 947 return perf_env__get_socket(map, idx, &perf_stat.session->header.env);
2196} 948}
2197 949
2198static int perf_stat__get_core_file(struct cpu_map *map, int idx) 950static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,
951 struct cpu_map *map, int idx)
2199{ 952{
2200 return perf_env__get_core(map, idx, &perf_stat.session->header.env); 953 return perf_env__get_core(map, idx, &perf_stat.session->header.env);
2201} 954}
@@ -2206,18 +959,18 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
2206 959
2207 switch (stat_config.aggr_mode) { 960 switch (stat_config.aggr_mode) {
2208 case AGGR_SOCKET: 961 case AGGR_SOCKET:
2209 if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) { 962 if (perf_env__build_socket_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
2210 perror("cannot build socket map"); 963 perror("cannot build socket map");
2211 return -1; 964 return -1;
2212 } 965 }
2213 aggr_get_id = perf_stat__get_socket_file; 966 stat_config.aggr_get_id = perf_stat__get_socket_file;
2214 break; 967 break;
2215 case AGGR_CORE: 968 case AGGR_CORE:
2216 if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) { 969 if (perf_env__build_core_map(env, evsel_list->cpus, &stat_config.aggr_map)) {
2217 perror("cannot build core map"); 970 perror("cannot build core map");
2218 return -1; 971 return -1;
2219 } 972 }
2220 aggr_get_id = perf_stat__get_core_file; 973 stat_config.aggr_get_id = perf_stat__get_core_file;
2221 break; 974 break;
2222 case AGGR_NONE: 975 case AGGR_NONE:
2223 case AGGR_GLOBAL: 976 case AGGR_GLOBAL:
@@ -2401,7 +1154,7 @@ static int add_default_attributes(void)
2401 struct parse_events_error errinfo; 1154 struct parse_events_error errinfo;
2402 1155
2403 /* Set attrs if no event is selected and !null_run: */ 1156 /* Set attrs if no event is selected and !null_run: */
2404 if (null_run) 1157 if (stat_config.null_run)
2405 return 0; 1158 return 0;
2406 1159
2407 if (transaction_run) { 1160 if (transaction_run) {
@@ -2414,7 +1167,7 @@ static int add_default_attributes(void)
2414 struct option opt = { .value = &evsel_list }; 1167 struct option opt = { .value = &evsel_list };
2415 1168
2416 return metricgroup__parse_groups(&opt, "transaction", 1169 return metricgroup__parse_groups(&opt, "transaction",
2417 &metric_events); 1170 &stat_config.metric_events);
2418 } 1171 }
2419 1172
2420 if (pmu_have_event("cpu", "cycles-ct") && 1173 if (pmu_have_event("cpu", "cycles-ct") &&
@@ -2452,7 +1205,7 @@ static int add_default_attributes(void)
2452 if (pmu_have_event("msr", "aperf") && 1205 if (pmu_have_event("msr", "aperf") &&
2453 pmu_have_event("msr", "smi")) { 1206 pmu_have_event("msr", "smi")) {
2454 if (!force_metric_only) 1207 if (!force_metric_only)
2455 metric_only = true; 1208 stat_config.metric_only = true;
2456 err = parse_events(evsel_list, smi_cost_attrs, &errinfo); 1209 err = parse_events(evsel_list, smi_cost_attrs, &errinfo);
2457 } else { 1210 } else {
2458 fprintf(stderr, "To measure SMI cost, it needs " 1211 fprintf(stderr, "To measure SMI cost, it needs "
@@ -2483,7 +1236,7 @@ static int add_default_attributes(void)
2483 } 1236 }
2484 1237
2485 if (!force_metric_only) 1238 if (!force_metric_only)
2486 metric_only = true; 1239 stat_config.metric_only = true;
2487 if (topdown_filter_events(topdown_attrs, &str, 1240 if (topdown_filter_events(topdown_attrs, &str,
2488 arch_topdown_check_group(&warn)) < 0) { 1241 arch_topdown_check_group(&warn)) < 0) {
2489 pr_err("Out of memory\n"); 1242 pr_err("Out of memory\n");
@@ -2580,7 +1333,7 @@ static int __cmd_record(int argc, const char **argv)
2580 if (output_name) 1333 if (output_name)
2581 data->file.path = output_name; 1334 data->file.path = output_name;
2582 1335
2583 if (run_count != 1 || forever) { 1336 if (stat_config.run_count != 1 || forever) {
2584 pr_err("Cannot use -r option with perf stat record.\n"); 1337 pr_err("Cannot use -r option with perf stat record.\n");
2585 return -1; 1338 return -1;
2586 } 1339 }
@@ -2599,9 +1352,8 @@ static int __cmd_record(int argc, const char **argv)
2599 return argc; 1352 return argc;
2600} 1353}
2601 1354
2602static int process_stat_round_event(struct perf_tool *tool __maybe_unused, 1355static int process_stat_round_event(struct perf_session *session,
2603 union perf_event *event, 1356 union perf_event *event)
2604 struct perf_session *session)
2605{ 1357{
2606 struct stat_round_event *stat_round = &event->stat_round; 1358 struct stat_round_event *stat_round = &event->stat_round;
2607 struct perf_evsel *counter; 1359 struct perf_evsel *counter;
@@ -2626,10 +1378,10 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2626} 1378}
2627 1379
2628static 1380static
2629int process_stat_config_event(struct perf_tool *tool, 1381int process_stat_config_event(struct perf_session *session,
2630 union perf_event *event, 1382 union perf_event *event)
2631 struct perf_session *session __maybe_unused)
2632{ 1383{
1384 struct perf_tool *tool = session->tool;
2633 struct perf_stat *st = container_of(tool, struct perf_stat, tool); 1385 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2634 1386
2635 perf_event__read_stat_config(&stat_config, &event->stat_config); 1387 perf_event__read_stat_config(&stat_config, &event->stat_config);
@@ -2669,10 +1421,10 @@ static int set_maps(struct perf_stat *st)
2669} 1421}
2670 1422
2671static 1423static
2672int process_thread_map_event(struct perf_tool *tool, 1424int process_thread_map_event(struct perf_session *session,
2673 union perf_event *event, 1425 union perf_event *event)
2674 struct perf_session *session __maybe_unused)
2675{ 1426{
1427 struct perf_tool *tool = session->tool;
2676 struct perf_stat *st = container_of(tool, struct perf_stat, tool); 1428 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2677 1429
2678 if (st->threads) { 1430 if (st->threads) {
@@ -2688,10 +1440,10 @@ int process_thread_map_event(struct perf_tool *tool,
2688} 1440}
2689 1441
2690static 1442static
2691int process_cpu_map_event(struct perf_tool *tool, 1443int process_cpu_map_event(struct perf_session *session,
2692 union perf_event *event, 1444 union perf_event *event)
2693 struct perf_session *session __maybe_unused)
2694{ 1445{
1446 struct perf_tool *tool = session->tool;
2695 struct perf_stat *st = container_of(tool, struct perf_stat, tool); 1447 struct perf_stat *st = container_of(tool, struct perf_stat, tool);
2696 struct cpu_map *cpus; 1448 struct cpu_map *cpus;
2697 1449
@@ -2853,12 +1605,12 @@ int cmd_stat(int argc, const char **argv)
2853 perf_stat__collect_metric_expr(evsel_list); 1605 perf_stat__collect_metric_expr(evsel_list);
2854 perf_stat__init_shadow_stats(); 1606 perf_stat__init_shadow_stats();
2855 1607
2856 if (csv_sep) { 1608 if (stat_config.csv_sep) {
2857 csv_output = true; 1609 stat_config.csv_output = true;
2858 if (!strcmp(csv_sep, "\\t")) 1610 if (!strcmp(stat_config.csv_sep, "\\t"))
2859 csv_sep = "\t"; 1611 stat_config.csv_sep = "\t";
2860 } else 1612 } else
2861 csv_sep = DEFAULT_SEPARATOR; 1613 stat_config.csv_sep = DEFAULT_SEPARATOR;
2862 1614
2863 if (argc && !strncmp(argv[0], "rec", 3)) { 1615 if (argc && !strncmp(argv[0], "rec", 3)) {
2864 argc = __cmd_record(argc, argv); 1616 argc = __cmd_record(argc, argv);
@@ -2883,17 +1635,17 @@ int cmd_stat(int argc, const char **argv)
2883 goto out; 1635 goto out;
2884 } 1636 }
2885 1637
2886 if (metric_only && stat_config.aggr_mode == AGGR_THREAD) { 1638 if (stat_config.metric_only && stat_config.aggr_mode == AGGR_THREAD) {
2887 fprintf(stderr, "--metric-only is not supported with --per-thread\n"); 1639 fprintf(stderr, "--metric-only is not supported with --per-thread\n");
2888 goto out; 1640 goto out;
2889 } 1641 }
2890 1642
2891 if (metric_only && run_count > 1) { 1643 if (stat_config.metric_only && stat_config.run_count > 1) {
2892 fprintf(stderr, "--metric-only is not supported with -r\n"); 1644 fprintf(stderr, "--metric-only is not supported with -r\n");
2893 goto out; 1645 goto out;
2894 } 1646 }
2895 1647
2896 if (walltime_run_table && run_count <= 1) { 1648 if (stat_config.walltime_run_table && stat_config.run_count <= 1) {
2897 fprintf(stderr, "--table is only supported with -r\n"); 1649 fprintf(stderr, "--table is only supported with -r\n");
2898 parse_options_usage(stat_usage, stat_options, "r", 1); 1650 parse_options_usage(stat_usage, stat_options, "r", 1);
2899 parse_options_usage(NULL, stat_options, "table", 0); 1651 parse_options_usage(NULL, stat_options, "table", 0);
@@ -2931,7 +1683,7 @@ int cmd_stat(int argc, const char **argv)
2931 /* 1683 /*
2932 * let the spreadsheet do the pretty-printing 1684 * let the spreadsheet do the pretty-printing
2933 */ 1685 */
2934 if (csv_output) { 1686 if (stat_config.csv_output) {
2935 /* User explicitly passed -B? */ 1687 /* User explicitly passed -B? */
2936 if (big_num_opt == 1) { 1688 if (big_num_opt == 1) {
2937 fprintf(stderr, "-B option not supported with -x\n"); 1689 fprintf(stderr, "-B option not supported with -x\n");
@@ -2939,9 +1691,9 @@ int cmd_stat(int argc, const char **argv)
2939 parse_options_usage(NULL, stat_options, "x", 1); 1691 parse_options_usage(NULL, stat_options, "x", 1);
2940 goto out; 1692 goto out;
2941 } else /* Nope, so disable big number formatting */ 1693 } else /* Nope, so disable big number formatting */
2942 big_num = false; 1694 stat_config.big_num = false;
2943 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1695 } else if (big_num_opt == 0) /* User passed --no-big-num */
2944 big_num = false; 1696 stat_config.big_num = false;
2945 1697
2946 setup_system_wide(argc); 1698 setup_system_wide(argc);
2947 1699
@@ -2949,21 +1701,21 @@ int cmd_stat(int argc, const char **argv)
2949 * Display user/system times only for single 1701 * Display user/system times only for single
2950 * run and when there's specified tracee. 1702 * run and when there's specified tracee.
2951 */ 1703 */
2952 if ((run_count == 1) && target__none(&target)) 1704 if ((stat_config.run_count == 1) && target__none(&target))
2953 ru_display = true; 1705 stat_config.ru_display = true;
2954 1706
2955 if (run_count < 0) { 1707 if (stat_config.run_count < 0) {
2956 pr_err("Run count must be a positive number\n"); 1708 pr_err("Run count must be a positive number\n");
2957 parse_options_usage(stat_usage, stat_options, "r", 1); 1709 parse_options_usage(stat_usage, stat_options, "r", 1);
2958 goto out; 1710 goto out;
2959 } else if (run_count == 0) { 1711 } else if (stat_config.run_count == 0) {
2960 forever = true; 1712 forever = true;
2961 run_count = 1; 1713 stat_config.run_count = 1;
2962 } 1714 }
2963 1715
2964 if (walltime_run_table) { 1716 if (stat_config.walltime_run_table) {
2965 walltime_run = zalloc(run_count * sizeof(walltime_run[0])); 1717 stat_config.walltime_run = zalloc(stat_config.run_count * sizeof(stat_config.walltime_run[0]));
2966 if (!walltime_run) { 1718 if (!stat_config.walltime_run) {
2967 pr_err("failed to setup -r option"); 1719 pr_err("failed to setup -r option");
2968 goto out; 1720 goto out;
2969 } 1721 }
@@ -3066,6 +1818,17 @@ int cmd_stat(int argc, const char **argv)
3066 goto out; 1818 goto out;
3067 1819
3068 /* 1820 /*
1821 * Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
1822 * while avoiding that older tools show confusing messages.
1823 *
1824 * However for pipe sessions we need to keep it zero,
1825 * because script's perf_evsel__check_attr is triggered
1826 * by attr->sample_type != 0, and we can't run it on
1827 * stat sessions.
1828 */
1829 stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe);
1830
1831 /*
3069 * We dont want to block the signals - that would cause 1832 * We dont want to block the signals - that would cause
3070 * child tasks to inherit that and Ctrl-C would not work. 1833 * child tasks to inherit that and Ctrl-C would not work.
3071 * What we want is for Ctrl-C to work in the exec()-ed 1834 * What we want is for Ctrl-C to work in the exec()-ed
@@ -3079,8 +1842,8 @@ int cmd_stat(int argc, const char **argv)
3079 signal(SIGABRT, skip_signal); 1842 signal(SIGABRT, skip_signal);
3080 1843
3081 status = 0; 1844 status = 0;
3082 for (run_idx = 0; forever || run_idx < run_count; run_idx++) { 1845 for (run_idx = 0; forever || run_idx < stat_config.run_count; run_idx++) {
3083 if (run_count != 1 && verbose > 0) 1846 if (stat_config.run_count != 1 && verbose > 0)
3084 fprintf(output, "[ perf stat: executing run #%d ... ]\n", 1847 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
3085 run_idx + 1); 1848 run_idx + 1);
3086 1849
@@ -3132,7 +1895,7 @@ int cmd_stat(int argc, const char **argv)
3132 perf_stat__exit_aggr_mode(); 1895 perf_stat__exit_aggr_mode();
3133 perf_evlist__free_stats(evsel_list); 1896 perf_evlist__free_stats(evsel_list);
3134out: 1897out:
3135 free(walltime_run); 1898 free(stat_config.walltime_run);
3136 1899
3137 if (smi_cost && smi_reset) 1900 if (smi_cost && smi_reset)
3138 sysfs__write_int(FREEZE_ON_SMI_PATH, 0); 1901 sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index d21d8751e749..aa0c73e57924 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1134,11 +1134,6 @@ static int __cmd_top(struct perf_top *top)
1134 if (!target__none(&opts->target)) 1134 if (!target__none(&opts->target))
1135 perf_evlist__enable(top->evlist); 1135 perf_evlist__enable(top->evlist);
1136 1136
1137 /* Wait for a minimal set of events before starting the snapshot */
1138 perf_evlist__poll(top->evlist, 100);
1139
1140 perf_top__mmap_read(top);
1141
1142 ret = -1; 1137 ret = -1;
1143 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : 1138 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
1144 display_thread), top)) { 1139 display_thread), top)) {
@@ -1156,6 +1151,11 @@ static int __cmd_top(struct perf_top *top)
1156 } 1151 }
1157 } 1152 }
1158 1153
1154 /* Wait for a minimal set of events before starting the snapshot */
1155 perf_evlist__poll(top->evlist, 100);
1156
1157 perf_top__mmap_read(top);
1158
1159 while (!done) { 1159 while (!done) {
1160 u64 hits = top->samples; 1160 u64 hits = top->samples;
1161 1161
@@ -1257,7 +1257,14 @@ int cmd_top(int argc, const char **argv)
1257 .uses_mmap = true, 1257 .uses_mmap = true,
1258 }, 1258 },
1259 .proc_map_timeout = 500, 1259 .proc_map_timeout = 500,
1260 .overwrite = 1, 1260 /*
1261 * FIXME: This will lose PERF_RECORD_MMAP and other metadata
1262 * when we pause, fix that and reenable. Probably using a
1263 * separate evlist with a dummy event, i.e. a non-overwrite
1264 * ring buffer just for metadata events, while PERF_RECORD_SAMPLE
1265 * stays in overwrite mode. -acme
1266 * */
1267 .overwrite = 0,
1261 }, 1268 },
1262 .max_stack = sysctl__max_stack(), 1269 .max_stack = sysctl__max_stack(),
1263 .annotation_opts = annotation__default_options, 1270 .annotation_opts = annotation__default_options,
@@ -1372,6 +1379,8 @@ int cmd_top(int argc, const char **argv)
1372 "Show raw trace event output (do not use print fmt or plugins)"), 1379 "Show raw trace event output (do not use print fmt or plugins)"),
1373 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, 1380 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
1374 "Show entries in a hierarchy"), 1381 "Show entries in a hierarchy"),
1382 OPT_BOOLEAN(0, "overwrite", &top.record_opts.overwrite,
1383 "Use a backward ring buffer, default: no"),
1375 OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"), 1384 OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
1376 OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize, 1385 OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize,
1377 "number of thread to run event synthesize"), 1386 "number of thread to run event synthesize"),
@@ -1420,6 +1429,9 @@ int cmd_top(int argc, const char **argv)
1420 } 1429 }
1421 } 1430 }
1422 1431
1432 if (opts->branch_stack && callchain_param.enabled)
1433 symbol_conf.show_branchflag_count = true;
1434
1423 sort__mode = SORT_MODE__TOP; 1435 sort__mode = SORT_MODE__TOP;
1424 /* display thread wants entries to be collapsed in a different tree */ 1436 /* display thread wants entries to be collapsed in a different tree */
1425 perf_hpp_list.need_collapse = 1; 1437 perf_hpp_list.need_collapse = 1;
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 22ab8e67c760..835619476370 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -89,6 +89,8 @@ struct trace {
89 u64 base_time; 89 u64 base_time;
90 FILE *output; 90 FILE *output;
91 unsigned long nr_events; 91 unsigned long nr_events;
92 unsigned long nr_events_printed;
93 unsigned long max_events;
92 struct strlist *ev_qualifier; 94 struct strlist *ev_qualifier;
93 struct { 95 struct {
94 size_t nr; 96 size_t nr;
@@ -106,6 +108,7 @@ struct trace {
106 } stats; 108 } stats;
107 unsigned int max_stack; 109 unsigned int max_stack;
108 unsigned int min_stack; 110 unsigned int min_stack;
111 bool raw_augmented_syscalls;
109 bool not_ev_qualifier; 112 bool not_ev_qualifier;
110 bool live; 113 bool live;
111 bool full_time; 114 bool full_time;
@@ -181,7 +184,7 @@ static int __tp_field__init_uint(struct tp_field *field, int size, int offset, b
181 return 0; 184 return 0;
182} 185}
183 186
184static int tp_field__init_uint(struct tp_field *field, struct format_field *format_field, bool needs_swap) 187static int tp_field__init_uint(struct tp_field *field, struct tep_format_field *format_field, bool needs_swap)
185{ 188{
186 return __tp_field__init_uint(field, format_field->size, format_field->offset, needs_swap); 189 return __tp_field__init_uint(field, format_field->size, format_field->offset, needs_swap);
187} 190}
@@ -198,7 +201,7 @@ static int __tp_field__init_ptr(struct tp_field *field, int offset)
198 return 0; 201 return 0;
199} 202}
200 203
201static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field) 204static int tp_field__init_ptr(struct tp_field *field, struct tep_format_field *format_field)
202{ 205{
203 return __tp_field__init_ptr(field, format_field->offset); 206 return __tp_field__init_ptr(field, format_field->offset);
204} 207}
@@ -214,7 +217,7 @@ static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
214 struct tp_field *field, 217 struct tp_field *field,
215 const char *name) 218 const char *name)
216{ 219{
217 struct format_field *format_field = perf_evsel__field(evsel, name); 220 struct tep_format_field *format_field = perf_evsel__field(evsel, name);
218 221
219 if (format_field == NULL) 222 if (format_field == NULL)
220 return -1; 223 return -1;
@@ -230,7 +233,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
230 struct tp_field *field, 233 struct tp_field *field,
231 const char *name) 234 const char *name)
232{ 235{
233 struct format_field *format_field = perf_evsel__field(evsel, name); 236 struct tep_format_field *format_field = perf_evsel__field(evsel, name);
234 237
235 if (format_field == NULL) 238 if (format_field == NULL)
236 return -1; 239 return -1;
@@ -288,6 +291,13 @@ static int perf_evsel__init_augmented_syscall_tp_args(struct perf_evsel *evsel)
288 return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64)); 291 return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64));
289} 292}
290 293
294static int perf_evsel__init_augmented_syscall_tp_ret(struct perf_evsel *evsel)
295{
296 struct syscall_tp *sc = evsel->priv;
297
298 return __tp_field__init_uint(&sc->ret, sizeof(u64), sc->id.offset + sizeof(u64), evsel->needs_swap);
299}
300
291static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler) 301static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler)
292{ 302{
293 evsel->priv = malloc(sizeof(struct syscall_tp)); 303 evsel->priv = malloc(sizeof(struct syscall_tp));
@@ -498,16 +508,6 @@ static const char *clockid[] = {
498}; 508};
499static DEFINE_STRARRAY(clockid); 509static DEFINE_STRARRAY(clockid);
500 510
501static const char *socket_families[] = {
502 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
503 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
504 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
505 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
506 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
507 "ALG", "NFC", "VSOCK",
508};
509static DEFINE_STRARRAY(socket_families);
510
511static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size, 511static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
512 struct syscall_arg *arg) 512 struct syscall_arg *arg)
513{ 513{
@@ -615,6 +615,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
615 615
616struct syscall_arg_fmt { 616struct syscall_arg_fmt {
617 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg); 617 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
618 unsigned long (*mask_val)(struct syscall_arg *arg, unsigned long val);
618 void *parm; 619 void *parm;
619 const char *name; 620 const char *name;
620 bool show_zero; 621 bool show_zero;
@@ -631,6 +632,8 @@ static struct syscall_fmt {
631} syscall_fmts[] = { 632} syscall_fmts[] = {
632 { .name = "access", 633 { .name = "access",
633 .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, 634 .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
635 { .name = "bind",
636 .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* umyaddr */ }, }, },
634 { .name = "bpf", 637 { .name = "bpf",
635 .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, 638 .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
636 { .name = "brk", .hexret = true, 639 { .name = "brk", .hexret = true,
@@ -645,6 +648,8 @@ static struct syscall_fmt {
645 [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, }, 648 [4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, },
646 { .name = "close", 649 { .name = "close",
647 .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, }, 650 .arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
651 { .name = "connect",
652 .arg = { [1] = { .scnprintf = SCA_SOCKADDR, /* servaddr */ }, }, },
648 { .name = "epoll_ctl", 653 { .name = "epoll_ctl",
649 .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, }, 654 .arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
650 { .name = "eventfd2", 655 { .name = "eventfd2",
@@ -722,6 +727,10 @@ static struct syscall_fmt {
722 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, 727 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
723 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, 728 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
724 [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, }, 729 [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
730 { .name = "mount",
731 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* dev_name */ },
732 [3] = { .scnprintf = SCA_MOUNT_FLAGS, /* flags */
733 .mask_val = SCAMV_MOUNT_FLAGS, /* flags */ }, }, },
725 { .name = "mprotect", 734 { .name = "mprotect",
726 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ }, 735 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
727 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, }, 736 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
@@ -801,7 +810,8 @@ static struct syscall_fmt {
801 { .name = "sendmsg", 810 { .name = "sendmsg",
802 .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, 811 .arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
803 { .name = "sendto", 812 { .name = "sendto",
804 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, }, 813 .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ },
814 [4] = { .scnprintf = SCA_SOCKADDR, /* addr */ }, }, },
805 { .name = "set_tid_address", .errpid = true, }, 815 { .name = "set_tid_address", .errpid = true, },
806 { .name = "setitimer", 816 { .name = "setitimer",
807 .arg = { [0] = STRARRAY(which, itimers), }, }, 817 .arg = { [0] = STRARRAY(which, itimers), }, },
@@ -830,6 +840,8 @@ static struct syscall_fmt {
830 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, 840 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
831 { .name = "tkill", 841 { .name = "tkill",
832 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, 842 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
843 { .name = "umount2", .alias = "umount",
844 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* name */ }, }, },
833 { .name = "uname", .alias = "newuname", }, 845 { .name = "uname", .alias = "newuname", },
834 { .name = "unlinkat", 846 { .name = "unlinkat",
835 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, 847 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
@@ -853,16 +865,30 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
853 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp); 865 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
854} 866}
855 867
868static struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
869{
870 int i, nmemb = ARRAY_SIZE(syscall_fmts);
871
872 for (i = 0; i < nmemb; ++i) {
873 if (syscall_fmts[i].alias && strcmp(syscall_fmts[i].alias, alias) == 0)
874 return &syscall_fmts[i];
875 }
876
877 return NULL;
878}
879
856/* 880/*
857 * is_exit: is this "exit" or "exit_group"? 881 * is_exit: is this "exit" or "exit_group"?
858 * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter. 882 * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
883 * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
859 */ 884 */
860struct syscall { 885struct syscall {
861 struct event_format *tp_format; 886 struct tep_event_format *tp_format;
862 int nr_args; 887 int nr_args;
888 int args_size;
863 bool is_exit; 889 bool is_exit;
864 bool is_open; 890 bool is_open;
865 struct format_field *args; 891 struct tep_format_field *args;
866 const char *name; 892 const char *name;
867 struct syscall_fmt *fmt; 893 struct syscall_fmt *fmt;
868 struct syscall_arg_fmt *arg_fmt; 894 struct syscall_arg_fmt *arg_fmt;
@@ -1095,11 +1121,21 @@ static void thread__set_filename_pos(struct thread *thread, const char *bf,
1095 ttrace->filename.entry_str_pos = bf - ttrace->entry_str; 1121 ttrace->filename.entry_str_pos = bf - ttrace->entry_str;
1096} 1122}
1097 1123
1124static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, char *bf, size_t size)
1125{
1126 struct augmented_arg *augmented_arg = arg->augmented.args;
1127
1128 return scnprintf(bf, size, "%.*s", augmented_arg->size, augmented_arg->value);
1129}
1130
1098static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, 1131static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
1099 struct syscall_arg *arg) 1132 struct syscall_arg *arg)
1100{ 1133{
1101 unsigned long ptr = arg->val; 1134 unsigned long ptr = arg->val;
1102 1135
1136 if (arg->augmented.args)
1137 return syscall_arg__scnprintf_augmented_string(arg, bf, size);
1138
1103 if (!arg->trace->vfs_getname) 1139 if (!arg->trace->vfs_getname)
1104 return scnprintf(bf, size, "%#x", ptr); 1140 return scnprintf(bf, size, "%#x", ptr);
1105 1141
@@ -1142,11 +1178,9 @@ static void sig_handler(int sig)
1142 interrupted = sig == SIGINT; 1178 interrupted = sig == SIGINT;
1143} 1179}
1144 1180
1145static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, 1181static size_t trace__fprintf_comm_tid(struct trace *trace, struct thread *thread, FILE *fp)
1146 u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
1147{ 1182{
1148 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); 1183 size_t printed = 0;
1149 printed += fprintf_duration(duration, duration_calculated, fp);
1150 1184
1151 if (trace->multiple_threads) { 1185 if (trace->multiple_threads) {
1152 if (trace->show_comm) 1186 if (trace->show_comm)
@@ -1157,6 +1191,14 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
1157 return printed; 1191 return printed;
1158} 1192}
1159 1193
1194static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
1195 u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
1196{
1197 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
1198 printed += fprintf_duration(duration, duration_calculated, fp);
1199 return printed + trace__fprintf_comm_tid(trace, thread, fp);
1200}
1201
1160static int trace__process_event(struct trace *trace, struct machine *machine, 1202static int trace__process_event(struct trace *trace, struct machine *machine,
1161 union perf_event *event, struct perf_sample *sample) 1203 union perf_event *event, struct perf_sample *sample)
1162{ 1204{
@@ -1258,10 +1300,12 @@ static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args)
1258 1300
1259static int syscall__set_arg_fmts(struct syscall *sc) 1301static int syscall__set_arg_fmts(struct syscall *sc)
1260{ 1302{
1261 struct format_field *field; 1303 struct tep_format_field *field, *last_field = NULL;
1262 int idx = 0, len; 1304 int idx = 0, len;
1263 1305
1264 for (field = sc->args; field; field = field->next, ++idx) { 1306 for (field = sc->args; field; field = field->next, ++idx) {
1307 last_field = field;
1308
1265 if (sc->fmt && sc->fmt->arg[idx].scnprintf) 1309 if (sc->fmt && sc->fmt->arg[idx].scnprintf)
1266 continue; 1310 continue;
1267 1311
@@ -1270,7 +1314,7 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1270 strcmp(field->name, "path") == 0 || 1314 strcmp(field->name, "path") == 0 ||
1271 strcmp(field->name, "pathname") == 0)) 1315 strcmp(field->name, "pathname") == 0))
1272 sc->arg_fmt[idx].scnprintf = SCA_FILENAME; 1316 sc->arg_fmt[idx].scnprintf = SCA_FILENAME;
1273 else if (field->flags & FIELD_IS_POINTER) 1317 else if (field->flags & TEP_FIELD_IS_POINTER)
1274 sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex; 1318 sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex;
1275 else if (strcmp(field->type, "pid_t") == 0) 1319 else if (strcmp(field->type, "pid_t") == 0)
1276 sc->arg_fmt[idx].scnprintf = SCA_PID; 1320 sc->arg_fmt[idx].scnprintf = SCA_PID;
@@ -1292,6 +1336,9 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1292 } 1336 }
1293 } 1337 }
1294 1338
1339 if (last_field)
1340 sc->args_size = last_field->offset + last_field->size;
1341
1295 return 0; 1342 return 0;
1296} 1343}
1297 1344
@@ -1459,6 +1506,19 @@ static size_t syscall__scnprintf_name(struct syscall *sc, char *bf, size_t size,
1459 return scnprintf(bf, size, "arg%d: ", arg->idx); 1506 return scnprintf(bf, size, "arg%d: ", arg->idx);
1460} 1507}
1461 1508
1509/*
1510 * Check if the value is in fact zero, i.e. mask whatever needs masking, such
1511 * as mount 'flags' argument that needs ignoring some magic flag, see comment
1512 * in tools/perf/trace/beauty/mount_flags.c
1513 */
1514static unsigned long syscall__mask_val(struct syscall *sc, struct syscall_arg *arg, unsigned long val)
1515{
1516 if (sc->arg_fmt && sc->arg_fmt[arg->idx].mask_val)
1517 return sc->arg_fmt[arg->idx].mask_val(arg, val);
1518
1519 return val;
1520}
1521
1462static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size, 1522static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
1463 struct syscall_arg *arg, unsigned long val) 1523 struct syscall_arg *arg, unsigned long val)
1464{ 1524{
@@ -1472,14 +1532,18 @@ static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
1472} 1532}
1473 1533
1474static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1534static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1475 unsigned char *args, struct trace *trace, 1535 unsigned char *args, void *augmented_args, int augmented_args_size,
1476 struct thread *thread) 1536 struct trace *trace, struct thread *thread)
1477{ 1537{
1478 size_t printed = 0; 1538 size_t printed = 0;
1479 unsigned long val; 1539 unsigned long val;
1480 u8 bit = 1; 1540 u8 bit = 1;
1481 struct syscall_arg arg = { 1541 struct syscall_arg arg = {
1482 .args = args, 1542 .args = args,
1543 .augmented = {
1544 .size = augmented_args_size,
1545 .args = augmented_args,
1546 },
1483 .idx = 0, 1547 .idx = 0,
1484 .mask = 0, 1548 .mask = 0,
1485 .trace = trace, 1549 .trace = trace,
@@ -1495,7 +1559,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1495 ttrace->ret_scnprintf = NULL; 1559 ttrace->ret_scnprintf = NULL;
1496 1560
1497 if (sc->args != NULL) { 1561 if (sc->args != NULL) {
1498 struct format_field *field; 1562 struct tep_format_field *field;
1499 1563
1500 for (field = sc->args; field; 1564 for (field = sc->args; field;
1501 field = field->next, ++arg.idx, bit <<= 1) { 1565 field = field->next, ++arg.idx, bit <<= 1) {
@@ -1503,6 +1567,11 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1503 continue; 1567 continue;
1504 1568
1505 val = syscall_arg__val(&arg, arg.idx); 1569 val = syscall_arg__val(&arg, arg.idx);
1570 /*
1571 * Some syscall args need some mask, most don't and
1572 * return val untouched.
1573 */
1574 val = syscall__mask_val(sc, &arg, val);
1506 1575
1507 /* 1576 /*
1508 * Suppress this argument if its value is zero and 1577 * Suppress this argument if its value is zero and
@@ -1634,6 +1703,8 @@ static int trace__printf_interrupted_entry(struct trace *trace)
1634 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str); 1703 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1635 ttrace->entry_pending = false; 1704 ttrace->entry_pending = false;
1636 1705
1706 ++trace->nr_events_printed;
1707
1637 return printed; 1708 return printed;
1638} 1709}
1639 1710
@@ -1654,6 +1725,32 @@ static int trace__fprintf_sample(struct trace *trace, struct perf_evsel *evsel,
1654 return printed; 1725 return printed;
1655} 1726}
1656 1727
1728static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sample, int *augmented_args_size, bool raw_augmented)
1729{
1730 void *augmented_args = NULL;
1731 /*
1732 * For now with BPF raw_augmented we hook into raw_syscalls:sys_enter
1733 * and there we get all 6 syscall args plus the tracepoint common
1734 * fields (sizeof(long)) and the syscall_nr (another long). So we check
1735 * if that is the case and if so don't look after the sc->args_size,
1736 * but always after the full raw_syscalls:sys_enter payload, which is
1737 * fixed.
1738 *
1739 * We'll revisit this later to pass s->args_size to the BPF augmenter
1740 * (now tools/perf/examples/bpf/augmented_raw_syscalls.c, so that it
1741 * copies only what we need for each syscall, like what happens when we
1742 * use syscalls:sys_enter_NAME, so that we reduce the kernel/userspace
1743 * traffic to just what is needed for each syscall.
1744 */
1745 int args_size = raw_augmented ? (8 * (int)sizeof(long)) : sc->args_size;
1746
1747 *augmented_args_size = sample->raw_size - args_size;
1748 if (*augmented_args_size > 0)
1749 augmented_args = sample->raw_data + args_size;
1750
1751 return augmented_args;
1752}
1753
1657static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1754static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1658 union perf_event *event __maybe_unused, 1755 union perf_event *event __maybe_unused,
1659 struct perf_sample *sample) 1756 struct perf_sample *sample)
@@ -1663,6 +1760,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1663 size_t printed = 0; 1760 size_t printed = 0;
1664 struct thread *thread; 1761 struct thread *thread;
1665 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; 1762 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
1763 int augmented_args_size = 0;
1764 void *augmented_args = NULL;
1666 struct syscall *sc = trace__syscall_info(trace, evsel, id); 1765 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1667 struct thread_trace *ttrace; 1766 struct thread_trace *ttrace;
1668 1767
@@ -1686,13 +1785,24 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1686 1785
1687 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) 1786 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
1688 trace__printf_interrupted_entry(trace); 1787 trace__printf_interrupted_entry(trace);
1689 1788 /*
1789 * If this is raw_syscalls.sys_enter, then it always comes with the 6 possible
1790 * arguments, even if the syscall being handled, say "openat", uses only 4 arguments
1791 * this breaks syscall__augmented_args() check for augmented args, as we calculate
1792 * syscall->args_size using each syscalls:sys_enter_NAME tracefs format file,
1793 * so when handling, say the openat syscall, we end up getting 6 args for the
1794 * raw_syscalls:sys_enter event, when we expected just 4, we end up mistakenly
1795 * thinking that the extra 2 u64 args are the augmented filename, so just check
1796 * here and avoid using augmented syscalls when the evsel is the raw_syscalls one.
1797 */
1798 if (evsel != trace->syscalls.events.sys_enter)
1799 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls);
1690 ttrace->entry_time = sample->time; 1800 ttrace->entry_time = sample->time;
1691 msg = ttrace->entry_str; 1801 msg = ttrace->entry_str;
1692 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name); 1802 printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
1693 1803
1694 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed, 1804 printed += syscall__scnprintf_args(sc, msg + printed, trace__entry_str_size - printed,
1695 args, trace, thread); 1805 args, augmented_args, augmented_args_size, trace, thread);
1696 1806
1697 if (sc->is_exit) { 1807 if (sc->is_exit) {
1698 if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { 1808 if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) {
@@ -1723,7 +1833,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse
1723 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; 1833 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
1724 struct syscall *sc = trace__syscall_info(trace, evsel, id); 1834 struct syscall *sc = trace__syscall_info(trace, evsel, id);
1725 char msg[1024]; 1835 char msg[1024];
1726 void *args; 1836 void *args, *augmented_args = NULL;
1837 int augmented_args_size;
1727 1838
1728 if (sc == NULL) 1839 if (sc == NULL)
1729 return -1; 1840 return -1;
@@ -1738,7 +1849,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evse
1738 goto out_put; 1849 goto out_put;
1739 1850
1740 args = perf_evsel__sc_tp_ptr(evsel, args, sample); 1851 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
1741 syscall__scnprintf_args(sc, msg, sizeof(msg), args, trace, thread); 1852 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls);
1853 syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread);
1742 fprintf(trace->output, "%s", msg); 1854 fprintf(trace->output, "%s", msg);
1743 err = 0; 1855 err = 0;
1744out_put: 1856out_put:
@@ -1754,12 +1866,14 @@ static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evse
1754 int max_stack = evsel->attr.sample_max_stack ? 1866 int max_stack = evsel->attr.sample_max_stack ?
1755 evsel->attr.sample_max_stack : 1867 evsel->attr.sample_max_stack :
1756 trace->max_stack; 1868 trace->max_stack;
1869 int err;
1757 1870
1758 if (machine__resolve(trace->host, &al, sample) < 0 || 1871 if (machine__resolve(trace->host, &al, sample) < 0)
1759 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack))
1760 return -1; 1872 return -1;
1761 1873
1762 return 0; 1874 err = thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack);
1875 addr_location__put(&al);
1876 return err;
1763} 1877}
1764 1878
1765static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample) 1879static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
@@ -1884,6 +1998,13 @@ errno_print: {
1884 1998
1885 fputc('\n', trace->output); 1999 fputc('\n', trace->output);
1886 2000
2001 /*
2002 * We only consider an 'event' for the sake of --max-events a non-filtered
2003 * sys_enter + sys_exit and other tracepoint events.
2004 */
2005 if (++trace->nr_events_printed == trace->max_events && trace->max_events != ULONG_MAX)
2006 interrupted = true;
2007
1887 if (callchain_ret > 0) 2008 if (callchain_ret > 0)
1888 trace__fprintf_callchain(trace, sample); 2009 trace__fprintf_callchain(trace, sample);
1889 else if (callchain_ret < 0) 2010 else if (callchain_ret < 0)
@@ -2016,13 +2137,25 @@ static void bpf_output__fprintf(struct trace *trace,
2016{ 2137{
2017 binary__fprintf(sample->raw_data, sample->raw_size, 8, 2138 binary__fprintf(sample->raw_data, sample->raw_size, 8,
2018 bpf_output__printer, NULL, trace->output); 2139 bpf_output__printer, NULL, trace->output);
2140 ++trace->nr_events_printed;
2019} 2141}
2020 2142
2021static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, 2143static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2022 union perf_event *event __maybe_unused, 2144 union perf_event *event __maybe_unused,
2023 struct perf_sample *sample) 2145 struct perf_sample *sample)
2024{ 2146{
2147 struct thread *thread;
2025 int callchain_ret = 0; 2148 int callchain_ret = 0;
2149 /*
2150 * Check if we called perf_evsel__disable(evsel) due to, for instance,
2151 * this event's max_events having been hit and this is an entry coming
2152 * from the ring buffer that we should discard, since the max events
2153 * have already been considered/printed.
2154 */
2155 if (evsel->disabled)
2156 return 0;
2157
2158 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2026 2159
2027 if (sample->callchain) { 2160 if (sample->callchain) {
2028 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor); 2161 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
@@ -2039,22 +2172,47 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2039 if (trace->trace_syscalls) 2172 if (trace->trace_syscalls)
2040 fprintf(trace->output, "( ): "); 2173 fprintf(trace->output, "( ): ");
2041 2174
2175 if (thread)
2176 trace__fprintf_comm_tid(trace, thread, trace->output);
2177
2178 if (evsel == trace->syscalls.events.augmented) {
2179 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
2180 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2181
2182 if (sc) {
2183 fprintf(trace->output, "%s(", sc->name);
2184 trace__fprintf_sys_enter(trace, evsel, sample);
2185 fputc(')', trace->output);
2186 goto newline;
2187 }
2188
2189 /*
2190 * XXX: Not having the associated syscall info or not finding/adding
2191 * the thread should never happen, but if it does...
2192 * fall thru and print it as a bpf_output event.
2193 */
2194 }
2195
2042 fprintf(trace->output, "%s:", evsel->name); 2196 fprintf(trace->output, "%s:", evsel->name);
2043 2197
2044 if (perf_evsel__is_bpf_output(evsel)) { 2198 if (perf_evsel__is_bpf_output(evsel)) {
2045 if (evsel == trace->syscalls.events.augmented) 2199 bpf_output__fprintf(trace, sample);
2046 trace__fprintf_sys_enter(trace, evsel, sample);
2047 else
2048 bpf_output__fprintf(trace, sample);
2049 } else if (evsel->tp_format) { 2200 } else if (evsel->tp_format) {
2050 if (strncmp(evsel->tp_format->name, "sys_enter_", 10) || 2201 if (strncmp(evsel->tp_format->name, "sys_enter_", 10) ||
2051 trace__fprintf_sys_enter(trace, evsel, sample)) { 2202 trace__fprintf_sys_enter(trace, evsel, sample)) {
2052 event_format__fprintf(evsel->tp_format, sample->cpu, 2203 event_format__fprintf(evsel->tp_format, sample->cpu,
2053 sample->raw_data, sample->raw_size, 2204 sample->raw_data, sample->raw_size,
2054 trace->output); 2205 trace->output);
2206 ++trace->nr_events_printed;
2207
2208 if (evsel->max_events != ULONG_MAX && ++evsel->nr_events_printed == evsel->max_events) {
2209 perf_evsel__disable(evsel);
2210 perf_evsel__close(evsel);
2211 }
2055 } 2212 }
2056 } 2213 }
2057 2214
2215newline:
2058 fprintf(trace->output, "\n"); 2216 fprintf(trace->output, "\n");
2059 2217
2060 if (callchain_ret > 0) 2218 if (callchain_ret > 0)
@@ -2062,6 +2220,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2062 else if (callchain_ret < 0) 2220 else if (callchain_ret < 0)
2063 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); 2221 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2064out: 2222out:
2223 thread__put(thread);
2065 return 0; 2224 return 0;
2066} 2225}
2067 2226
@@ -2148,6 +2307,8 @@ static int trace__pgfault(struct trace *trace,
2148 trace__fprintf_callchain(trace, sample); 2307 trace__fprintf_callchain(trace, sample);
2149 else if (callchain_ret < 0) 2308 else if (callchain_ret < 0)
2150 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); 2309 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2310
2311 ++trace->nr_events_printed;
2151out: 2312out:
2152 err = 0; 2313 err = 0;
2153out_put: 2314out_put:
@@ -2325,6 +2486,9 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2325 tracepoint_handler handler = evsel->handler; 2486 tracepoint_handler handler = evsel->handler;
2326 handler(trace, evsel, event, sample); 2487 handler(trace, evsel, event, sample);
2327 } 2488 }
2489
2490 if (trace->nr_events_printed >= trace->max_events && trace->max_events != ULONG_MAX)
2491 interrupted = true;
2328} 2492}
2329 2493
2330static int trace__add_syscall_newtp(struct trace *trace) 2494static int trace__add_syscall_newtp(struct trace *trace)
@@ -2629,7 +2793,7 @@ next_event:
2629 int timeout = done ? 100 : -1; 2793 int timeout = done ? 100 : -1;
2630 2794
2631 if (!draining && perf_evlist__poll(evlist, timeout) > 0) { 2795 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2632 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0) 2796 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP | POLLNVAL) == 0)
2633 draining = true; 2797 draining = true;
2634 2798
2635 goto again; 2799 goto again;
@@ -3061,6 +3225,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
3061 int len = strlen(str) + 1, err = -1, list, idx; 3225 int len = strlen(str) + 1, err = -1, list, idx;
3062 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR); 3226 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
3063 char group_name[PATH_MAX]; 3227 char group_name[PATH_MAX];
3228 struct syscall_fmt *fmt;
3064 3229
3065 if (strace_groups_dir == NULL) 3230 if (strace_groups_dir == NULL)
3066 return -1; 3231 return -1;
@@ -3078,12 +3243,19 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
3078 if (syscalltbl__id(trace->sctbl, s) >= 0 || 3243 if (syscalltbl__id(trace->sctbl, s) >= 0 ||
3079 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) { 3244 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
3080 list = 1; 3245 list = 1;
3246 goto do_concat;
3247 }
3248
3249 fmt = syscall_fmt__find_by_alias(s);
3250 if (fmt != NULL) {
3251 list = 1;
3252 s = fmt->name;
3081 } else { 3253 } else {
3082 path__join(group_name, sizeof(group_name), strace_groups_dir, s); 3254 path__join(group_name, sizeof(group_name), strace_groups_dir, s);
3083 if (access(group_name, R_OK) == 0) 3255 if (access(group_name, R_OK) == 0)
3084 list = 1; 3256 list = 1;
3085 } 3257 }
3086 3258do_concat:
3087 if (lists[list]) { 3259 if (lists[list]) {
3088 sprintf(lists[list] + strlen(lists[list]), ",%s", s); 3260 sprintf(lists[list] + strlen(lists[list]), ",%s", s);
3089 } else { 3261 } else {
@@ -3172,6 +3344,7 @@ int cmd_trace(int argc, const char **argv)
3172 .trace_syscalls = false, 3344 .trace_syscalls = false,
3173 .kernel_syscallchains = false, 3345 .kernel_syscallchains = false,
3174 .max_stack = UINT_MAX, 3346 .max_stack = UINT_MAX,
3347 .max_events = ULONG_MAX,
3175 }; 3348 };
3176 const char *output_name = NULL; 3349 const char *output_name = NULL;
3177 const struct option trace_options[] = { 3350 const struct option trace_options[] = {
@@ -3224,6 +3397,8 @@ int cmd_trace(int argc, const char **argv)
3224 &record_parse_callchain_opt), 3397 &record_parse_callchain_opt),
3225 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains, 3398 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3226 "Show the kernel callchains on the syscall exit path"), 3399 "Show the kernel callchains on the syscall exit path"),
3400 OPT_ULONG(0, "max-events", &trace.max_events,
3401 "Set the maximum number of events to print, exit after that is reached. "),
3227 OPT_UINTEGER(0, "min-stack", &trace.min_stack, 3402 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
3228 "Set the minimum stack depth when parsing the callchain, " 3403 "Set the minimum stack depth when parsing the callchain, "
3229 "anything below the specified depth will be ignored."), 3404 "anything below the specified depth will be ignored."),
@@ -3276,12 +3451,8 @@ int cmd_trace(int argc, const char **argv)
3276 goto out; 3451 goto out;
3277 } 3452 }
3278 3453
3279 if (evsel) { 3454 if (evsel)
3280 if (perf_evsel__init_augmented_syscall_tp(evsel) ||
3281 perf_evsel__init_augmented_syscall_tp_args(evsel))
3282 goto out;
3283 trace.syscalls.events.augmented = evsel; 3455 trace.syscalls.events.augmented = evsel;
3284 }
3285 3456
3286 err = bpf__setup_stdout(trace.evlist); 3457 err = bpf__setup_stdout(trace.evlist);
3287 if (err) { 3458 if (err) {
@@ -3326,6 +3497,42 @@ int cmd_trace(int argc, const char **argv)
3326 } 3497 }
3327 } 3498 }
3328 3499
3500 /*
3501 * If we are augmenting syscalls, then combine what we put in the
3502 * __augmented_syscalls__ BPF map with what is in the
3503 * syscalls:sys_exit_FOO tracepoints, i.e. just like we do without BPF,
3504 * combining raw_syscalls:sys_enter with raw_syscalls:sys_exit.
3505 *
3506 * We'll switch to look at two BPF maps, one for sys_enter and the
3507 * other for sys_exit when we start augmenting the sys_exit paths with
3508 * buffers that are being copied from kernel to userspace, think 'read'
3509 * syscall.
3510 */
3511 if (trace.syscalls.events.augmented) {
3512 evsel = trace.syscalls.events.augmented;
3513
3514 if (perf_evsel__init_augmented_syscall_tp(evsel) ||
3515 perf_evsel__init_augmented_syscall_tp_args(evsel))
3516 goto out;
3517 evsel->handler = trace__sys_enter;
3518
3519 evlist__for_each_entry(trace.evlist, evsel) {
3520 bool raw_syscalls_sys_exit = strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_exit") == 0;
3521
3522 if (raw_syscalls_sys_exit) {
3523 trace.raw_augmented_syscalls = true;
3524 goto init_augmented_syscall_tp;
3525 }
3526
3527 if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) {
3528init_augmented_syscall_tp:
3529 perf_evsel__init_augmented_syscall_tp(evsel);
3530 perf_evsel__init_augmented_syscall_tp_ret(evsel);
3531 evsel->handler = trace__sys_exit;
3532 }
3533 }
3534 }
3535
3329 if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) 3536 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
3330 return trace__record(&trace, argc-1, &argv[1]); 3537 return trace__record(&trace, argc-1, &argv[1]);
3331 3538
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 466540ee8ea7..9531f7bd7d9b 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -5,6 +5,7 @@ HEADERS='
5include/uapi/drm/drm.h 5include/uapi/drm/drm.h
6include/uapi/drm/i915_drm.h 6include/uapi/drm/i915_drm.h
7include/uapi/linux/fcntl.h 7include/uapi/linux/fcntl.h
8include/uapi/linux/fs.h
8include/uapi/linux/kcmp.h 9include/uapi/linux/kcmp.h
9include/uapi/linux/kvm.h 10include/uapi/linux/kvm.h
10include/uapi/linux/in.h 11include/uapi/linux/in.h
@@ -14,6 +15,7 @@ include/uapi/linux/sched.h
14include/uapi/linux/stat.h 15include/uapi/linux/stat.h
15include/uapi/linux/vhost.h 16include/uapi/linux/vhost.h
16include/uapi/sound/asound.h 17include/uapi/sound/asound.h
18include/linux/bits.h
17include/linux/hash.h 19include/linux/hash.h
18include/uapi/linux/hw_breakpoint.h 20include/uapi/linux/hw_breakpoint.h
19arch/x86/include/asm/disabled-features.h 21arch/x86/include/asm/disabled-features.h
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 2d0caf20ff3a..bc6c585f74fc 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -30,3 +30,4 @@ perf-test mainporcelain common
30perf-timechart mainporcelain common 30perf-timechart mainporcelain common
31perf-top mainporcelain common 31perf-top mainporcelain common
32perf-trace mainporcelain audit 32perf-trace mainporcelain audit
33perf-version mainporcelain common
diff --git a/tools/perf/examples/bpf/augmented_raw_syscalls.c b/tools/perf/examples/bpf/augmented_raw_syscalls.c
new file mode 100644
index 000000000000..90a19336310b
--- /dev/null
+++ b/tools/perf/examples/bpf/augmented_raw_syscalls.c
@@ -0,0 +1,131 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Augment the raw_syscalls tracepoints with the contents of the pointer arguments.
4 *
5 * Test it with:
6 *
7 * perf trace -e tools/perf/examples/bpf/augmented_raw_syscalls.c cat /etc/passwd > /dev/null
8 *
9 * This exactly matches what is marshalled into the raw_syscall:sys_enter
10 * payload expected by the 'perf trace' beautifiers.
11 *
12 * For now it just uses the existing tracepoint augmentation code in 'perf
13 * trace', in the next csets we'll hook up these with the sys_enter/sys_exit
14 * code that will combine entry/exit in a strace like way.
15 */
16
17#include <stdio.h>
18#include <linux/socket.h>
19
20/* bpf-output associated map */
21struct bpf_map SEC("maps") __augmented_syscalls__ = {
22 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
23 .key_size = sizeof(int),
24 .value_size = sizeof(u32),
25 .max_entries = __NR_CPUS__,
26};
27
28struct syscall_enter_args {
29 unsigned long long common_tp_fields;
30 long syscall_nr;
31 unsigned long args[6];
32};
33
34struct syscall_exit_args {
35 unsigned long long common_tp_fields;
36 long syscall_nr;
37 long ret;
38};
39
40struct augmented_filename {
41 unsigned int size;
42 int reserved;
43 char value[256];
44};
45
46#define SYS_OPEN 2
47#define SYS_OPENAT 257
48
49SEC("raw_syscalls:sys_enter")
50int sys_enter(struct syscall_enter_args *args)
51{
52 struct {
53 struct syscall_enter_args args;
54 struct augmented_filename filename;
55 } augmented_args;
56 unsigned int len = sizeof(augmented_args);
57 const void *filename_arg = NULL;
58
59 probe_read(&augmented_args.args, sizeof(augmented_args.args), args);
60 /*
61 * Yonghong and Edward Cree sayz:
62 *
63 * https://www.spinics.net/lists/netdev/msg531645.html
64 *
65 * >> R0=inv(id=0) R1=inv2 R6=ctx(id=0,off=0,imm=0) R7=inv64 R10=fp0,call_-1
66 * >> 10: (bf) r1 = r6
67 * >> 11: (07) r1 += 16
68 * >> 12: (05) goto pc+2
69 * >> 15: (79) r3 = *(u64 *)(r1 +0)
70 * >> dereference of modified ctx ptr R1 off=16 disallowed
71 * > Aha, we at least got a different error message this time.
72 * > And indeed llvm has done that optimisation, rather than the more obvious
73 * > 11: r3 = *(u64 *)(r1 +16)
74 * > because it wants to have lots of reads share a single insn. You may be able
75 * > to defeat that optimisation by adding compiler barriers, idk. Maybe someone
76 * > with llvm knowledge can figure out how to stop it (ideally, llvm would know
77 * > when it's generating for bpf backend and not do that). -O0? ¯\_(ツ)_/¯
78 *
79 * The optimization mostly likes below:
80 *
81 * br1:
82 * ...
83 * r1 += 16
84 * goto merge
85 * br2:
86 * ...
87 * r1 += 20
88 * goto merge
89 * merge:
90 * *(u64 *)(r1 + 0)
91 *
92 * The compiler tries to merge common loads. There is no easy way to
93 * stop this compiler optimization without turning off a lot of other
94 * optimizations. The easiest way is to add barriers:
95 *
96 * __asm__ __volatile__("": : :"memory")
97 *
98 * after the ctx memory access to prevent their down stream merging.
99 */
100 switch (augmented_args.args.syscall_nr) {
101 case SYS_OPEN: filename_arg = (const void *)args->args[0];
102 __asm__ __volatile__("": : :"memory");
103 break;
104 case SYS_OPENAT: filename_arg = (const void *)args->args[1];
105 break;
106 }
107
108 if (filename_arg != NULL) {
109 augmented_args.filename.reserved = 0;
110 augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
111 sizeof(augmented_args.filename.value),
112 filename_arg);
113 if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) {
114 len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size;
115 len &= sizeof(augmented_args.filename.value) - 1;
116 }
117 } else {
118 len = sizeof(augmented_args.args);
119 }
120
121 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, len);
122 return 0;
123}
124
125SEC("raw_syscalls:sys_exit")
126int sys_exit(struct syscall_exit_args *args)
127{
128 return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */
129}
130
131license(GPL);
diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c
index 69a31386d8cd..2ae44813ef2d 100644
--- a/tools/perf/examples/bpf/augmented_syscalls.c
+++ b/tools/perf/examples/bpf/augmented_syscalls.c
@@ -1,6 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2/* 2/*
3 * Augment the openat syscall with the contents of the filename pointer argument. 3 * Augment syscalls with the contents of the pointer arguments.
4 * 4 *
5 * Test it with: 5 * Test it with:
6 * 6 *
@@ -10,15 +10,14 @@
10 * the last one should be the one for '/etc/passwd'. 10 * the last one should be the one for '/etc/passwd'.
11 * 11 *
12 * This matches what is marshalled into the raw_syscall:sys_enter payload 12 * This matches what is marshalled into the raw_syscall:sys_enter payload
13 * expected by the 'perf trace' beautifiers, and can be used by them unmodified, 13 * expected by the 'perf trace' beautifiers, and can be used by them, that will
14 * which will be done as that feature is implemented in the next csets, for now 14 * check if perf_sample->raw_data is more than what is expected for each
15 * it will appear in a dump done by the default tracepoint handler in 'perf trace', 15 * syscalls:sys_{enter,exit}_SYSCALL tracepoint, uing the extra data as the
16 * that uses bpf_output__fprintf() to just dump those contents, as done with 16 * contents of pointer arguments.
17 * the bpf-output event associated with the __bpf_output__ map declared in
18 * tools/perf/include/bpf/stdio.h.
19 */ 17 */
20 18
21#include <stdio.h> 19#include <stdio.h>
20#include <linux/socket.h>
22 21
23struct bpf_map SEC("maps") __augmented_syscalls__ = { 22struct bpf_map SEC("maps") __augmented_syscalls__ = {
24 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, 23 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
@@ -27,6 +26,44 @@ struct bpf_map SEC("maps") __augmented_syscalls__ = {
27 .max_entries = __NR_CPUS__, 26 .max_entries = __NR_CPUS__,
28}; 27};
29 28
29struct syscall_exit_args {
30 unsigned long long common_tp_fields;
31 long syscall_nr;
32 long ret;
33};
34
35struct augmented_filename {
36 unsigned int size;
37 int reserved;
38 char value[256];
39};
40
41#define augmented_filename_syscall(syscall) \
42struct augmented_enter_##syscall##_args { \
43 struct syscall_enter_##syscall##_args args; \
44 struct augmented_filename filename; \
45}; \
46int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
47{ \
48 struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \
49 unsigned int len = sizeof(augmented_args); \
50 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
51 augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \
52 sizeof(augmented_args.filename.value), \
53 args->filename_ptr); \
54 if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) { \
55 len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size; \
56 len &= sizeof(augmented_args.filename.value) - 1; \
57 } \
58 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
59 &augmented_args, len); \
60 return 0; \
61} \
62int syscall_exit(syscall)(struct syscall_exit_args *args) \
63{ \
64 return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \
65}
66
30struct syscall_enter_openat_args { 67struct syscall_enter_openat_args {
31 unsigned long long common_tp_fields; 68 unsigned long long common_tp_fields;
32 long syscall_nr; 69 long syscall_nr;
@@ -36,20 +73,101 @@ struct syscall_enter_openat_args {
36 long mode; 73 long mode;
37}; 74};
38 75
39struct augmented_enter_openat_args { 76augmented_filename_syscall(openat);
40 struct syscall_enter_openat_args args; 77
41 char filename[64]; 78struct syscall_enter_open_args {
79 unsigned long long common_tp_fields;
80 long syscall_nr;
81 char *filename_ptr;
82 long flags;
83 long mode;
84};
85
86augmented_filename_syscall(open);
87
88struct syscall_enter_inotify_add_watch_args {
89 unsigned long long common_tp_fields;
90 long syscall_nr;
91 long fd;
92 char *filename_ptr;
93 long mask;
94};
95
96augmented_filename_syscall(inotify_add_watch);
97
98struct statbuf;
99
100struct syscall_enter_newstat_args {
101 unsigned long long common_tp_fields;
102 long syscall_nr;
103 char *filename_ptr;
104 struct stat *statbuf;
42}; 105};
43 106
44int syscall_enter(openat)(struct syscall_enter_openat_args *args) 107augmented_filename_syscall(newstat);
45{ 108
46 struct augmented_enter_openat_args augmented_args; 109#ifndef _K_SS_MAXSIZE
110#define _K_SS_MAXSIZE 128
111#endif
47 112
48 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); 113#define augmented_sockaddr_syscall(syscall) \
49 probe_read_str(&augmented_args.filename, sizeof(augmented_args.filename), args->filename_ptr); 114struct augmented_enter_##syscall##_args { \
50 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, 115 struct syscall_enter_##syscall##_args args; \
51 &augmented_args, sizeof(augmented_args)); 116 struct sockaddr_storage addr; \
52 return 1; 117}; \
118int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
119{ \
120 struct augmented_enter_##syscall##_args augmented_args; \
121 unsigned long addrlen = sizeof(augmented_args.addr); \
122 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
123/* FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK */ \
124/* if (addrlen > augmented_args.args.addrlen) */ \
125/* addrlen = augmented_args.args.addrlen; */ \
126/* */ \
127 probe_read(&augmented_args.addr, addrlen, args->addr_ptr); \
128 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
129 &augmented_args, \
130 sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen); \
131 return 0; \
132} \
133int syscall_exit(syscall)(struct syscall_exit_args *args) \
134{ \
135 return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \
53} 136}
54 137
138struct sockaddr;
139
140struct syscall_enter_bind_args {
141 unsigned long long common_tp_fields;
142 long syscall_nr;
143 long fd;
144 struct sockaddr *addr_ptr;
145 unsigned long addrlen;
146};
147
148augmented_sockaddr_syscall(bind);
149
150struct syscall_enter_connect_args {
151 unsigned long long common_tp_fields;
152 long syscall_nr;
153 long fd;
154 struct sockaddr *addr_ptr;
155 unsigned long addrlen;
156};
157
158augmented_sockaddr_syscall(connect);
159
160struct syscall_enter_sendto_args {
161 unsigned long long common_tp_fields;
162 long syscall_nr;
163 long fd;
164 void *buff;
165 long len;
166 unsigned long flags;
167 struct sockaddr *addr_ptr;
168 long addr_len;
169};
170
171augmented_sockaddr_syscall(sendto);
172
55license(GPL); 173license(GPL);
diff --git a/tools/perf/examples/bpf/etcsnoop.c b/tools/perf/examples/bpf/etcsnoop.c
new file mode 100644
index 000000000000..b59e8812ee8c
--- /dev/null
+++ b/tools/perf/examples/bpf/etcsnoop.c
@@ -0,0 +1,80 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Augment the filename syscalls with the contents of the filename pointer argument
4 * filtering only those that do not start with /etc/.
5 *
6 * Test it with:
7 *
8 * perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null
9 *
10 * It'll catch some openat syscalls related to the dynamic linked and
11 * the last one should be the one for '/etc/passwd'.
12 *
13 * This matches what is marshalled into the raw_syscall:sys_enter payload
14 * expected by the 'perf trace' beautifiers, and can be used by them unmodified,
15 * which will be done as that feature is implemented in the next csets, for now
16 * it will appear in a dump done by the default tracepoint handler in 'perf trace',
17 * that uses bpf_output__fprintf() to just dump those contents, as done with
18 * the bpf-output event associated with the __bpf_output__ map declared in
19 * tools/perf/include/bpf/stdio.h.
20 */
21
22#include <stdio.h>
23
24struct bpf_map SEC("maps") __augmented_syscalls__ = {
25 .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
26 .key_size = sizeof(int),
27 .value_size = sizeof(u32),
28 .max_entries = __NR_CPUS__,
29};
30
31struct augmented_filename {
32 int size;
33 int reserved;
34 char value[64];
35};
36
37#define augmented_filename_syscall_enter(syscall) \
38struct augmented_enter_##syscall##_args { \
39 struct syscall_enter_##syscall##_args args; \
40 struct augmented_filename filename; \
41}; \
42int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \
43{ \
44 char etc[6] = "/etc/"; \
45 struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \
46 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \
47 augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \
48 sizeof(augmented_args.filename.value), \
49 args->filename_ptr); \
50 if (__builtin_memcmp(augmented_args.filename.value, etc, 4) != 0) \
51 return 0; \
52 perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \
53 &augmented_args, \
54 (sizeof(augmented_args) - sizeof(augmented_args.filename.value) + \
55 augmented_args.filename.size)); \
56 return 0; \
57}
58
59struct syscall_enter_openat_args {
60 unsigned long long common_tp_fields;
61 long syscall_nr;
62 long dfd;
63 char *filename_ptr;
64 long flags;
65 long mode;
66};
67
68augmented_filename_syscall_enter(openat);
69
70struct syscall_enter_open_args {
71 unsigned long long common_tp_fields;
72 long syscall_nr;
73 char *filename_ptr;
74 long flags;
75 long mode;
76};
77
78augmented_filename_syscall_enter(open);
79
80license(GPL);
diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h
index 47897d65e799..52b6d87fe822 100644
--- a/tools/perf/include/bpf/bpf.h
+++ b/tools/perf/include/bpf/bpf.h
@@ -26,6 +26,9 @@ struct bpf_map {
26#define syscall_enter(name) \ 26#define syscall_enter(name) \
27 SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name 27 SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name
28 28
29#define syscall_exit(name) \
30 SEC("syscalls:sys_exit_" #name) syscall_exit_ ## name
31
29#define license(name) \ 32#define license(name) \
30char _license[] SEC("license") = #name; \ 33char _license[] SEC("license") = #name; \
31int _version SEC("version") = LINUX_VERSION_CODE; 34int _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/tools/perf/include/bpf/linux/socket.h b/tools/perf/include/bpf/linux/socket.h
new file mode 100644
index 000000000000..7f844568dab8
--- /dev/null
+++ b/tools/perf/include/bpf/linux/socket.h
@@ -0,0 +1,24 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2#ifndef _UAPI_LINUX_SOCKET_H
3#define _UAPI_LINUX_SOCKET_H
4
5/*
6 * Desired design of maximum size and alignment (see RFC2553)
7 */
8#define _K_SS_MAXSIZE 128 /* Implementation specific max size */
9#define _K_SS_ALIGNSIZE (__alignof__ (struct sockaddr *))
10 /* Implementation specific desired alignment */
11
12typedef unsigned short __kernel_sa_family_t;
13
14struct __kernel_sockaddr_storage {
15 __kernel_sa_family_t ss_family; /* address family */
16 /* Following field(s) are implementation specific */
17 char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
18 /* space to achieve desired size, */
19 /* _SS_MAXSIZE value minus size of ss_family */
20} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */
21
22#define sockaddr_storage __kernel_sockaddr_storage
23
24#endif /* _UAPI_LINUX_SOCKET_H */
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
index ac1bcdc17dae..f7eb63cbbc65 100644
--- a/tools/perf/jvmti/jvmti_agent.c
+++ b/tools/perf/jvmti/jvmti_agent.c
@@ -125,7 +125,7 @@ perf_get_timestamp(void)
125} 125}
126 126
127static int 127static int
128debug_cache_init(void) 128create_jit_cache_dir(void)
129{ 129{
130 char str[32]; 130 char str[32];
131 char *base, *p; 131 char *base, *p;
@@ -144,8 +144,13 @@ debug_cache_init(void)
144 144
145 strftime(str, sizeof(str), JIT_LANG"-jit-%Y%m%d", &tm); 145 strftime(str, sizeof(str), JIT_LANG"-jit-%Y%m%d", &tm);
146 146
147 snprintf(jit_path, PATH_MAX - 1, "%s/.debug/", base); 147 ret = snprintf(jit_path, PATH_MAX, "%s/.debug/", base);
148 148 if (ret >= PATH_MAX) {
149 warnx("jvmti: cannot generate jit cache dir because %s/.debug/"
150 " is too long, please check the cwd, JITDUMPDIR, and"
151 " HOME variables", base);
152 return -1;
153 }
149 ret = mkdir(jit_path, 0755); 154 ret = mkdir(jit_path, 0755);
150 if (ret == -1) { 155 if (ret == -1) {
151 if (errno != EEXIST) { 156 if (errno != EEXIST) {
@@ -154,20 +159,32 @@ debug_cache_init(void)
154 } 159 }
155 } 160 }
156 161
157 snprintf(jit_path, PATH_MAX - 1, "%s/.debug/jit", base); 162 ret = snprintf(jit_path, PATH_MAX, "%s/.debug/jit", base);
163 if (ret >= PATH_MAX) {
164 warnx("jvmti: cannot generate jit cache dir because"
165 " %s/.debug/jit is too long, please check the cwd,"
166 " JITDUMPDIR, and HOME variables", base);
167 return -1;
168 }
158 ret = mkdir(jit_path, 0755); 169 ret = mkdir(jit_path, 0755);
159 if (ret == -1) { 170 if (ret == -1) {
160 if (errno != EEXIST) { 171 if (errno != EEXIST) {
161 warn("cannot create jit cache dir %s", jit_path); 172 warn("jvmti: cannot create jit cache dir %s", jit_path);
162 return -1; 173 return -1;
163 } 174 }
164 } 175 }
165 176
166 snprintf(jit_path, PATH_MAX - 1, "%s/.debug/jit/%s.XXXXXXXX", base, str); 177 ret = snprintf(jit_path, PATH_MAX, "%s/.debug/jit/%s.XXXXXXXX", base, str);
167 178 if (ret >= PATH_MAX) {
179 warnx("jvmti: cannot generate jit cache dir because"
180 " %s/.debug/jit/%s.XXXXXXXX is too long, please check"
181 " the cwd, JITDUMPDIR, and HOME variables",
182 base, str);
183 return -1;
184 }
168 p = mkdtemp(jit_path); 185 p = mkdtemp(jit_path);
169 if (p != jit_path) { 186 if (p != jit_path) {
170 warn("cannot create jit cache dir %s", jit_path); 187 warn("jvmti: cannot create jit cache dir %s", jit_path);
171 return -1; 188 return -1;
172 } 189 }
173 190
@@ -228,7 +245,7 @@ void *jvmti_open(void)
228{ 245{
229 char dump_path[PATH_MAX]; 246 char dump_path[PATH_MAX];
230 struct jitheader header; 247 struct jitheader header;
231 int fd; 248 int fd, ret;
232 FILE *fp; 249 FILE *fp;
233 250
234 init_arch_timestamp(); 251 init_arch_timestamp();
@@ -245,12 +262,22 @@ void *jvmti_open(void)
245 262
246 memset(&header, 0, sizeof(header)); 263 memset(&header, 0, sizeof(header));
247 264
248 debug_cache_init(); 265 /*
266 * jitdump file dir
267 */
268 if (create_jit_cache_dir() < 0)
269 return NULL;
249 270
250 /* 271 /*
251 * jitdump file name 272 * jitdump file name
252 */ 273 */
253 scnprintf(dump_path, PATH_MAX, "%s/jit-%i.dump", jit_path, getpid()); 274 ret = snprintf(dump_path, PATH_MAX, "%s/jit-%i.dump", jit_path, getpid());
275 if (ret >= PATH_MAX) {
276 warnx("jvmti: cannot generate jitdump file full path because"
277 " %s/jit-%i.dump is too long, please check the cwd,"
278 " JITDUMPDIR, and HOME variables", jit_path, getpid());
279 return NULL;
280 }
254 281
255 fd = open(dump_path, O_CREAT|O_TRUNC|O_RDWR, 0666); 282 fd = open(dump_path, O_CREAT|O_TRUNC|O_RDWR, 0666);
256 if (fd == -1) 283 if (fd == -1)
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 21bf7f5a3cf5..0ed4a34c74c4 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -81,6 +81,7 @@ struct record_opts {
81 unsigned initial_delay; 81 unsigned initial_delay;
82 bool use_clockid; 82 bool use_clockid;
83 clockid_t clockid; 83 clockid_t clockid;
84 u64 clockid_res_ns;
84 unsigned int proc_map_timeout; 85 unsigned int proc_map_timeout;
85}; 86};
86 87
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json
new file mode 100644
index 000000000000..abc98b018446
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/branch.json
@@ -0,0 +1,23 @@
1[
2 {
3 "ArchStdEvent": "BR_IMMED_SPEC",
4 },
5 {
6 "ArchStdEvent": "BR_RETURN_SPEC",
7 },
8 {
9 "ArchStdEvent": "BR_INDIRECT_SPEC",
10 },
11 {
12 "PublicDescription": "Mispredicted or not predicted branch speculatively executed",
13 "EventCode": "0x10",
14 "EventName": "BR_MIS_PRED",
15 "BriefDescription": "Branch mispredicted"
16 },
17 {
18 "PublicDescription": "Predictable branch speculatively executed",
19 "EventCode": "0x12",
20 "EventName": "BR_PRED",
21 "BriefDescription": "Predictable branch"
22 },
23]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json
new file mode 100644
index 000000000000..687b2629e1d1
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/bus.json
@@ -0,0 +1,26 @@
1[
2 {
3 "ArchStdEvent": "BUS_ACCESS_RD",
4 },
5 {
6 "ArchStdEvent": "BUS_ACCESS_WR",
7 },
8 {
9 "ArchStdEvent": "BUS_ACCESS_SHARED",
10 },
11 {
12 "ArchStdEvent": "BUS_ACCESS_NOT_SHARED",
13 },
14 {
15 "ArchStdEvent": "BUS_ACCESS_NORMAL",
16 },
17 {
18 "ArchStdEvent": "BUS_ACCESS_PERIPH",
19 },
20 {
21 "PublicDescription": "Bus access",
22 "EventCode": "0x19",
23 "EventName": "BUS_ACCESS",
24 "BriefDescription": "Bus access"
25 },
26]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json
new file mode 100644
index 000000000000..df9201434cb6
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/cache.json
@@ -0,0 +1,191 @@
1[
2 {
3 "ArchStdEvent": "L1D_CACHE_RD",
4 },
5 {
6 "ArchStdEvent": "L1D_CACHE_WR",
7 },
8 {
9 "ArchStdEvent": "L1D_CACHE_REFILL_RD",
10 },
11 {
12 "ArchStdEvent": "L1D_CACHE_INVAL",
13 },
14 {
15 "ArchStdEvent": "L1D_TLB_REFILL_RD",
16 },
17 {
18 "ArchStdEvent": "L1D_TLB_REFILL_WR",
19 },
20 {
21 "ArchStdEvent": "L2D_CACHE_RD",
22 },
23 {
24 "ArchStdEvent": "L2D_CACHE_WR",
25 },
26 {
27 "ArchStdEvent": "L2D_CACHE_REFILL_RD",
28 },
29 {
30 "ArchStdEvent": "L2D_CACHE_REFILL_WR",
31 },
32 {
33 "ArchStdEvent": "L2D_CACHE_WB_VICTIM",
34 },
35 {
36 "ArchStdEvent": "L2D_CACHE_WB_CLEAN",
37 },
38 {
39 "ArchStdEvent": "L2D_CACHE_INVAL",
40 },
41 {
42 "PublicDescription": "Level 1 instruction cache refill",
43 "EventCode": "0x01",
44 "EventName": "L1I_CACHE_REFILL",
45 "BriefDescription": "L1I cache refill"
46 },
47 {
48 "PublicDescription": "Level 1 instruction TLB refill",
49 "EventCode": "0x02",
50 "EventName": "L1I_TLB_REFILL",
51 "BriefDescription": "L1I TLB refill"
52 },
53 {
54 "PublicDescription": "Level 1 data cache refill",
55 "EventCode": "0x03",
56 "EventName": "L1D_CACHE_REFILL",
57 "BriefDescription": "L1D cache refill"
58 },
59 {
60 "PublicDescription": "Level 1 data cache access",
61 "EventCode": "0x04",
62 "EventName": "L1D_CACHE_ACCESS",
63 "BriefDescription": "L1D cache access"
64 },
65 {
66 "PublicDescription": "Level 1 data TLB refill",
67 "EventCode": "0x05",
68 "EventName": "L1D_TLB_REFILL",
69 "BriefDescription": "L1D TLB refill"
70 },
71 {
72 "PublicDescription": "Level 1 instruction cache access",
73 "EventCode": "0x14",
74 "EventName": "L1I_CACHE_ACCESS",
75 "BriefDescription": "L1I cache access"
76 },
77 {
78 "PublicDescription": "Level 2 data cache access",
79 "EventCode": "0x16",
80 "EventName": "L2D_CACHE_ACCESS",
81 "BriefDescription": "L2D cache access"
82 },
83 {
84 "PublicDescription": "Level 2 data refill",
85 "EventCode": "0x17",
86 "EventName": "L2D_CACHE_REFILL",
87 "BriefDescription": "L2D cache refill"
88 },
89 {
90 "PublicDescription": "Level 2 data cache, Write-Back",
91 "EventCode": "0x18",
92 "EventName": "L2D_CACHE_WB",
93 "BriefDescription": "L2D cache Write-Back"
94 },
95 {
96 "PublicDescription": "Level 1 data TLB access. This event counts any load or store operation which accesses the data L1 TLB",
97 "EventCode": "0x25",
98 "EventName": "L1D_TLB_ACCESS",
99 "BriefDescription": "L1D TLB access"
100 },
101 {
102 "PublicDescription": "Level 1 instruction TLB access. This event counts any instruction fetch which accesses the instruction L1 TLB",
103 "EventCode": "0x26",
104 "EventName": "L1I_TLB_ACCESS",
105 "BriefDescription": "L1I TLB access"
106 },
107 {
108 "PublicDescription": "Level 2 access to data TLB that caused a page table walk. This event counts on any data access which causes L2D_TLB_REFILL to count",
109 "EventCode": "0x34",
110 "EventName": "L2D_TLB_ACCESS",
111 "BriefDescription": "L2D TLB access"
112 },
113 {
114 "PublicDescription": "Level 2 access to instruciton TLB that caused a page table walk. This event counts on any instruciton access which causes L2I_TLB_REFILL to count",
115 "EventCode": "0x35",
116 "EventName": "L2I_TLB_ACCESS",
117 "BriefDescription": "L2D TLB access"
118 },
119 {
120 "PublicDescription": "Branch target buffer misprediction",
121 "EventCode": "0x102",
122 "EventName": "BTB_MIS_PRED",
123 "BriefDescription": "BTB misprediction"
124 },
125 {
126 "PublicDescription": "ITB miss",
127 "EventCode": "0x103",
128 "EventName": "ITB_MISS",
129 "BriefDescription": "ITB miss"
130 },
131 {
132 "PublicDescription": "DTB miss",
133 "EventCode": "0x104",
134 "EventName": "DTB_MISS",
135 "BriefDescription": "DTB miss"
136 },
137 {
138 "PublicDescription": "Level 1 data cache late miss",
139 "EventCode": "0x105",
140 "EventName": "L1D_CACHE_LATE_MISS",
141 "BriefDescription": "L1D cache late miss"
142 },
143 {
144 "PublicDescription": "Level 1 data cache prefetch request",
145 "EventCode": "0x106",
146 "EventName": "L1D_CACHE_PREFETCH",
147 "BriefDescription": "L1D cache prefetch"
148 },
149 {
150 "PublicDescription": "Level 2 data cache prefetch request",
151 "EventCode": "0x107",
152 "EventName": "L2D_CACHE_PREFETCH",
153 "BriefDescription": "L2D cache prefetch"
154 },
155 {
156 "PublicDescription": "Level 1 stage 2 TLB refill",
157 "EventCode": "0x111",
158 "EventName": "L1_STAGE2_TLB_REFILL",
159 "BriefDescription": "L1 stage 2 TLB refill"
160 },
161 {
162 "PublicDescription": "Page walk cache level-0 stage-1 hit",
163 "EventCode": "0x112",
164 "EventName": "PAGE_WALK_L0_STAGE1_HIT",
165 "BriefDescription": "Page walk, L0 stage-1 hit"
166 },
167 {
168 "PublicDescription": "Page walk cache level-1 stage-1 hit",
169 "EventCode": "0x113",
170 "EventName": "PAGE_WALK_L1_STAGE1_HIT",
171 "BriefDescription": "Page walk, L1 stage-1 hit"
172 },
173 {
174 "PublicDescription": "Page walk cache level-2 stage-1 hit",
175 "EventCode": "0x114",
176 "EventName": "PAGE_WALK_L2_STAGE1_HIT",
177 "BriefDescription": "Page walk, L2 stage-1 hit"
178 },
179 {
180 "PublicDescription": "Page walk cache level-1 stage-2 hit",
181 "EventCode": "0x115",
182 "EventName": "PAGE_WALK_L1_STAGE2_HIT",
183 "BriefDescription": "Page walk, L1 stage-2 hit"
184 },
185 {
186 "PublicDescription": "Page walk cache level-2 stage-2 hit",
187 "EventCode": "0x116",
188 "EventName": "PAGE_WALK_L2_STAGE2_HIT",
189 "BriefDescription": "Page walk, L2 stage-2 hit"
190 },
191]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json
new file mode 100644
index 000000000000..38cd1f1a70dc
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/clock.json
@@ -0,0 +1,20 @@
1[
2 {
3 "PublicDescription": "The number of core clock cycles",
4 "EventCode": "0x11",
5 "EventName": "CPU_CYCLES",
6 "BriefDescription": "Clock cycles"
7 },
8 {
9 "PublicDescription": "FSU clocking gated off cycle",
10 "EventCode": "0x101",
11 "EventName": "FSU_CLOCK_OFF_CYCLES",
12 "BriefDescription": "FSU clocking gated off cycle"
13 },
14 {
15 "PublicDescription": "Wait state cycle",
16 "EventCode": "0x110",
17 "EventName": "Wait_CYCLES",
18 "BriefDescription": "Wait state cycle"
19 },
20]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json
deleted file mode 100644
index bc03c06c3918..000000000000
--- a/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json
+++ /dev/null
@@ -1,32 +0,0 @@
1[
2 {
3 "ArchStdEvent": "L1D_CACHE_RD",
4 },
5 {
6 "ArchStdEvent": "L1D_CACHE_WR",
7 },
8 {
9 "ArchStdEvent": "L1D_CACHE_REFILL_RD",
10 },
11 {
12 "ArchStdEvent": "L1D_CACHE_REFILL_WR",
13 },
14 {
15 "ArchStdEvent": "L1D_TLB_REFILL_RD",
16 },
17 {
18 "ArchStdEvent": "L1D_TLB_REFILL_WR",
19 },
20 {
21 "ArchStdEvent": "L1D_TLB_RD",
22 },
23 {
24 "ArchStdEvent": "L1D_TLB_WR",
25 },
26 {
27 "ArchStdEvent": "BUS_ACCESS_RD",
28 },
29 {
30 "ArchStdEvent": "BUS_ACCESS_WR",
31 }
32]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json
new file mode 100644
index 000000000000..3720dc28a15f
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/exception.json
@@ -0,0 +1,50 @@
1[
2 {
3 "ArchStdEvent": "EXC_UNDEF",
4 },
5 {
6 "ArchStdEvent": "EXC_SVC",
7 },
8 {
9 "ArchStdEvent": "EXC_PABORT",
10 },
11 {
12 "ArchStdEvent": "EXC_DABORT",
13 },
14 {
15 "ArchStdEvent": "EXC_IRQ",
16 },
17 {
18 "ArchStdEvent": "EXC_FIQ",
19 },
20 {
21 "ArchStdEvent": "EXC_HVC",
22 },
23 {
24 "ArchStdEvent": "EXC_TRAP_PABORT",
25 },
26 {
27 "ArchStdEvent": "EXC_TRAP_DABORT",
28 },
29 {
30 "ArchStdEvent": "EXC_TRAP_OTHER",
31 },
32 {
33 "ArchStdEvent": "EXC_TRAP_IRQ",
34 },
35 {
36 "ArchStdEvent": "EXC_TRAP_FIQ",
37 },
38 {
39 "PublicDescription": "Exception taken",
40 "EventCode": "0x09",
41 "EventName": "EXC_TAKEN",
42 "BriefDescription": "Exception taken"
43 },
44 {
45 "PublicDescription": "Instruction architecturally executed, condition check pass, exception return",
46 "EventCode": "0x0a",
47 "EventName": "EXC_RETURN",
48 "BriefDescription": "Exception return"
49 },
50]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json
new file mode 100644
index 000000000000..82cf753e6472
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/instruction.json
@@ -0,0 +1,89 @@
1[
2 {
3 "ArchStdEvent": "LD_SPEC",
4 },
5 {
6 "ArchStdEvent": "ST_SPEC",
7 },
8 {
9 "ArchStdEvent": "LDST_SPEC",
10 },
11 {
12 "ArchStdEvent": "DP_SPEC",
13 },
14 {
15 "ArchStdEvent": "ASE_SPEC",
16 },
17 {
18 "ArchStdEvent": "VFP_SPEC",
19 },
20 {
21 "ArchStdEvent": "PC_WRITE_SPEC",
22 },
23 {
24 "ArchStdEvent": "CRYPTO_SPEC",
25 },
26 {
27 "ArchStdEvent": "ISB_SPEC",
28 },
29 {
30 "ArchStdEvent": "DSB_SPEC",
31 },
32 {
33 "ArchStdEvent": "DMB_SPEC",
34 },
35 {
36 "ArchStdEvent": "RC_LD_SPEC",
37 },
38 {
39 "ArchStdEvent": "RC_ST_SPEC",
40 },
41 {
42 "PublicDescription": "Instruction architecturally executed, software increment",
43 "EventCode": "0x00",
44 "EventName": "SW_INCR",
45 "BriefDescription": "Software increment"
46 },
47 {
48 "PublicDescription": "Instruction architecturally executed",
49 "EventCode": "0x08",
50 "EventName": "INST_RETIRED",
51 "BriefDescription": "Instruction retired"
52 },
53 {
54 "PublicDescription": "Instruction architecturally executed, condition code check pass, write to CONTEXTIDR",
55 "EventCode": "0x0b",
56 "EventName": "CID_WRITE_RETIRED",
57 "BriefDescription": "Write to CONTEXTIDR"
58 },
59 {
60 "PublicDescription": "Operation speculatively executed",
61 "EventCode": "0x1b",
62 "EventName": "INST_SPEC",
63 "BriefDescription": "Speculatively executed"
64 },
65 {
66 "PublicDescription": "Instruction architecturally executed (condition check pass), write to TTBR",
67 "EventCode": "0x1c",
68 "EventName": "TTBR_WRITE_RETIRED",
69 "BriefDescription": "Instruction executed, TTBR write"
70 },
71 {
72 "PublicDescription": "Instruction architecturally executed, branch. This event counts all branches, taken or not. This excludes exception entries, debug entries and CCFAIL branches",
73 "EventCode": "0x21",
74 "EventName": "BR_RETIRED",
75 "BriefDescription": "Branch retired"
76 },
77 {
78 "PublicDescription": "Instruction architecturally executed, mispredicted branch. This event counts any branch counted by BR_RETIRED which is not correctly predicted and causes a pipeline flush",
79 "EventCode": "0x22",
80 "EventName": "BR_MISPRED_RETIRED",
81 "BriefDescription": "Mispredicted branch retired"
82 },
83 {
84 "PublicDescription": "Operation speculatively executed, NOP",
85 "EventCode": "0x100",
86 "EventName": "NOP_SPEC",
87 "BriefDescription": "Speculatively executed, NOP"
88 },
89]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json
new file mode 100644
index 000000000000..2aecc5c2347d
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/intrinsic.json
@@ -0,0 +1,14 @@
1[
2 {
3 "ArchStdEvent": "LDREX_SPEC",
4 },
5 {
6 "ArchStdEvent": "STREX_PASS_SPEC",
7 },
8 {
9 "ArchStdEvent": "STREX_FAIL_SPEC",
10 },
11 {
12 "ArchStdEvent": "STREX_SPEC",
13 },
14]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json
new file mode 100644
index 000000000000..08508697b318
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/memory.json
@@ -0,0 +1,29 @@
1[
2 {
3 "ArchStdEvent": "MEM_ACCESS_RD",
4 },
5 {
6 "ArchStdEvent": "MEM_ACCESS_WR",
7 },
8 {
9 "ArchStdEvent": "UNALIGNED_LD_SPEC",
10 },
11 {
12 "ArchStdEvent": "UNALIGNED_ST_SPEC",
13 },
14 {
15 "ArchStdEvent": "UNALIGNED_LDST_SPEC",
16 },
17 {
18 "PublicDescription": "Data memory access",
19 "EventCode": "0x13",
20 "EventName": "MEM_ACCESS",
21 "BriefDescription": "Memory access"
22 },
23 {
24 "PublicDescription": "Local memory error. This event counts any correctable or uncorrectable memory error (ECC or parity) in the protected core RAMs",
25 "EventCode": "0x1a",
26 "EventName": "MEM_ERROR",
27 "BriefDescription": "Memory error"
28 },
29]
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json
new file mode 100644
index 000000000000..e2087de586bf
--- /dev/null
+++ b/tools/perf/pmu-events/arch/arm64/ampere/emag/pipeline.json
@@ -0,0 +1,50 @@
1[
2 {
3 "PublicDescription": "Decode starved for instruction cycle",
4 "EventCode": "0x108",
5 "EventName": "DECODE_STALL",
6 "BriefDescription": "Decode starved"
7 },
8 {
9 "PublicDescription": "Op dispatch stalled cycle",
10 "EventCode": "0x109",
11 "EventName": "DISPATCH_STALL",
12 "BriefDescription": "Dispatch stalled"
13 },
14 {
15 "PublicDescription": "IXA Op non-issue",
16 "EventCode": "0x10a",
17 "EventName": "IXA_STALL",
18 "BriefDescription": "IXA stalled"
19 },
20 {
21 "PublicDescription": "IXB Op non-issue",
22 "EventCode": "0x10b",
23 "EventName": "IXB_STALL",
24 "BriefDescription": "IXB stalled"
25 },
26 {
27 "PublicDescription": "BX Op non-issue",
28 "EventCode": "0x10c",
29 "EventName": "BX_STALL",
30 "BriefDescription": "BX stalled"
31 },
32 {
33 "PublicDescription": "LX Op non-issue",
34 "EventCode": "0x10d",
35 "EventName": "LX_STALL",
36 "BriefDescription": "LX stalled"
37 },
38 {
39 "PublicDescription": "SX Op non-issue",
40 "EventCode": "0x10e",
41 "EventName": "SX_STALL",
42 "BriefDescription": "SX stalled"
43 },
44 {
45 "PublicDescription": "FX Op non-issue",
46 "EventCode": "0x10f",
47 "EventName": "FX_STALL",
48 "BriefDescription": "FX stalled"
49 },
50]
diff --git a/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json b/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
index d40498f2cb1e..635c09fda1d9 100644
--- a/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
@@ -188,7 +188,7 @@
188 "Counter": "0,1,2,3", 188 "Counter": "0,1,2,3",
189 "EventCode": "0xb", 189 "EventCode": "0xb",
190 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES", 190 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
191 "Filter": "filter_band0=1200", 191 "Filter": "filter_band0=12",
192 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 192 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
193 "MetricName": "freq_ge_1200mhz_cycles %", 193 "MetricName": "freq_ge_1200mhz_cycles %",
194 "PerPkg": "1", 194 "PerPkg": "1",
@@ -199,7 +199,7 @@
199 "Counter": "0,1,2,3", 199 "Counter": "0,1,2,3",
200 "EventCode": "0xc", 200 "EventCode": "0xc",
201 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES", 201 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
202 "Filter": "filter_band1=2000", 202 "Filter": "filter_band1=20",
203 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 203 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
204 "MetricName": "freq_ge_2000mhz_cycles %", 204 "MetricName": "freq_ge_2000mhz_cycles %",
205 "PerPkg": "1", 205 "PerPkg": "1",
@@ -210,7 +210,7 @@
210 "Counter": "0,1,2,3", 210 "Counter": "0,1,2,3",
211 "EventCode": "0xd", 211 "EventCode": "0xd",
212 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES", 212 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
213 "Filter": "filter_band2=3000", 213 "Filter": "filter_band2=30",
214 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 214 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
215 "MetricName": "freq_ge_3000mhz_cycles %", 215 "MetricName": "freq_ge_3000mhz_cycles %",
216 "PerPkg": "1", 216 "PerPkg": "1",
@@ -221,7 +221,7 @@
221 "Counter": "0,1,2,3", 221 "Counter": "0,1,2,3",
222 "EventCode": "0xe", 222 "EventCode": "0xe",
223 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES", 223 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
224 "Filter": "filter_band3=4000", 224 "Filter": "filter_band3=40",
225 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 225 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
226 "MetricName": "freq_ge_4000mhz_cycles %", 226 "MetricName": "freq_ge_4000mhz_cycles %",
227 "PerPkg": "1", 227 "PerPkg": "1",
@@ -232,7 +232,7 @@
232 "Counter": "0,1,2,3", 232 "Counter": "0,1,2,3",
233 "EventCode": "0xb", 233 "EventCode": "0xb",
234 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS", 234 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
235 "Filter": "edge=1,filter_band0=1200", 235 "Filter": "edge=1,filter_band0=12",
236 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 236 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
237 "MetricName": "freq_ge_1200mhz_cycles %", 237 "MetricName": "freq_ge_1200mhz_cycles %",
238 "PerPkg": "1", 238 "PerPkg": "1",
@@ -243,7 +243,7 @@
243 "Counter": "0,1,2,3", 243 "Counter": "0,1,2,3",
244 "EventCode": "0xc", 244 "EventCode": "0xc",
245 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS", 245 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
246 "Filter": "edge=1,filter_band1=2000", 246 "Filter": "edge=1,filter_band1=20",
247 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 247 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
248 "MetricName": "freq_ge_2000mhz_cycles %", 248 "MetricName": "freq_ge_2000mhz_cycles %",
249 "PerPkg": "1", 249 "PerPkg": "1",
@@ -254,7 +254,7 @@
254 "Counter": "0,1,2,3", 254 "Counter": "0,1,2,3",
255 "EventCode": "0xd", 255 "EventCode": "0xd",
256 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS", 256 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
257 "Filter": "edge=1,filter_band2=4000", 257 "Filter": "edge=1,filter_band2=30",
258 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 258 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
259 "MetricName": "freq_ge_3000mhz_cycles %", 259 "MetricName": "freq_ge_3000mhz_cycles %",
260 "PerPkg": "1", 260 "PerPkg": "1",
@@ -265,7 +265,7 @@
265 "Counter": "0,1,2,3", 265 "Counter": "0,1,2,3",
266 "EventCode": "0xe", 266 "EventCode": "0xe",
267 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS", 267 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
268 "Filter": "edge=1,filter_band3=4000", 268 "Filter": "edge=1,filter_band3=40",
269 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 269 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
270 "MetricName": "freq_ge_4000mhz_cycles %", 270 "MetricName": "freq_ge_4000mhz_cycles %",
271 "PerPkg": "1", 271 "PerPkg": "1",
diff --git a/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json b/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
index 16034bfd06dd..8755693d86c6 100644
--- a/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
+++ b/tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
@@ -187,7 +187,7 @@
187 "Counter": "0,1,2,3", 187 "Counter": "0,1,2,3",
188 "EventCode": "0xb", 188 "EventCode": "0xb",
189 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES", 189 "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
190 "Filter": "filter_band0=1200", 190 "Filter": "filter_band0=12",
191 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 191 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
192 "MetricName": "freq_ge_1200mhz_cycles %", 192 "MetricName": "freq_ge_1200mhz_cycles %",
193 "PerPkg": "1", 193 "PerPkg": "1",
@@ -198,7 +198,7 @@
198 "Counter": "0,1,2,3", 198 "Counter": "0,1,2,3",
199 "EventCode": "0xc", 199 "EventCode": "0xc",
200 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES", 200 "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
201 "Filter": "filter_band1=2000", 201 "Filter": "filter_band1=20",
202 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 202 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
203 "MetricName": "freq_ge_2000mhz_cycles %", 203 "MetricName": "freq_ge_2000mhz_cycles %",
204 "PerPkg": "1", 204 "PerPkg": "1",
@@ -209,7 +209,7 @@
209 "Counter": "0,1,2,3", 209 "Counter": "0,1,2,3",
210 "EventCode": "0xd", 210 "EventCode": "0xd",
211 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES", 211 "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
212 "Filter": "filter_band2=3000", 212 "Filter": "filter_band2=30",
213 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 213 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
214 "MetricName": "freq_ge_3000mhz_cycles %", 214 "MetricName": "freq_ge_3000mhz_cycles %",
215 "PerPkg": "1", 215 "PerPkg": "1",
@@ -220,7 +220,7 @@
220 "Counter": "0,1,2,3", 220 "Counter": "0,1,2,3",
221 "EventCode": "0xe", 221 "EventCode": "0xe",
222 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES", 222 "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
223 "Filter": "filter_band3=4000", 223 "Filter": "filter_band3=40",
224 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 224 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
225 "MetricName": "freq_ge_4000mhz_cycles %", 225 "MetricName": "freq_ge_4000mhz_cycles %",
226 "PerPkg": "1", 226 "PerPkg": "1",
@@ -231,7 +231,7 @@
231 "Counter": "0,1,2,3", 231 "Counter": "0,1,2,3",
232 "EventCode": "0xb", 232 "EventCode": "0xb",
233 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS", 233 "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
234 "Filter": "edge=1,filter_band0=1200", 234 "Filter": "edge=1,filter_band0=12",
235 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 235 "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
236 "MetricName": "freq_ge_1200mhz_cycles %", 236 "MetricName": "freq_ge_1200mhz_cycles %",
237 "PerPkg": "1", 237 "PerPkg": "1",
@@ -242,7 +242,7 @@
242 "Counter": "0,1,2,3", 242 "Counter": "0,1,2,3",
243 "EventCode": "0xc", 243 "EventCode": "0xc",
244 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS", 244 "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
245 "Filter": "edge=1,filter_band1=2000", 245 "Filter": "edge=1,filter_band1=20",
246 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 246 "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
247 "MetricName": "freq_ge_2000mhz_cycles %", 247 "MetricName": "freq_ge_2000mhz_cycles %",
248 "PerPkg": "1", 248 "PerPkg": "1",
@@ -253,7 +253,7 @@
253 "Counter": "0,1,2,3", 253 "Counter": "0,1,2,3",
254 "EventCode": "0xd", 254 "EventCode": "0xd",
255 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS", 255 "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
256 "Filter": "edge=1,filter_band2=4000", 256 "Filter": "edge=1,filter_band2=30",
257 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 257 "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
258 "MetricName": "freq_ge_3000mhz_cycles %", 258 "MetricName": "freq_ge_3000mhz_cycles %",
259 "PerPkg": "1", 259 "PerPkg": "1",
@@ -264,7 +264,7 @@
264 "Counter": "0,1,2,3", 264 "Counter": "0,1,2,3",
265 "EventCode": "0xe", 265 "EventCode": "0xe",
266 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS", 266 "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
267 "Filter": "edge=1,filter_band3=4000", 267 "Filter": "edge=1,filter_band3=40",
268 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.", 268 "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
269 "MetricName": "freq_ge_4000mhz_cycles %", 269 "MetricName": "freq_ge_4000mhz_cycles %",
270 "PerPkg": "1", 270 "PerPkg": "1",
diff --git a/tools/perf/scripts/python/call-graph-from-sql.py b/tools/perf/scripts/python/call-graph-from-sql.py
deleted file mode 100644
index b494a67a1c67..000000000000
--- a/tools/perf/scripts/python/call-graph-from-sql.py
+++ /dev/null
@@ -1,339 +0,0 @@
1#!/usr/bin/python2
2# call-graph-from-sql.py: create call-graph from sql database
3# Copyright (c) 2014-2017, Intel Corporation.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms and conditions of the GNU General Public License,
7# version 2, as published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13
14# To use this script you will need to have exported data using either the
15# export-to-sqlite.py or the export-to-postgresql.py script. Refer to those
16# scripts for details.
17#
18# Following on from the example in the export scripts, a
19# call-graph can be displayed for the pt_example database like this:
20#
21# python tools/perf/scripts/python/call-graph-from-sql.py pt_example
22#
23# Note that for PostgreSQL, this script supports connecting to remote databases
24# by setting hostname, port, username, password, and dbname e.g.
25#
26# python tools/perf/scripts/python/call-graph-from-sql.py "hostname=myhost username=myuser password=mypassword dbname=pt_example"
27#
28# The result is a GUI window with a tree representing a context-sensitive
29# call-graph. Expanding a couple of levels of the tree and adjusting column
30# widths to suit will display something like:
31#
32# Call Graph: pt_example
33# Call Path Object Count Time(ns) Time(%) Branch Count Branch Count(%)
34# v- ls
35# v- 2638:2638
36# v- _start ld-2.19.so 1 10074071 100.0 211135 100.0
37# |- unknown unknown 1 13198 0.1 1 0.0
38# >- _dl_start ld-2.19.so 1 1400980 13.9 19637 9.3
39# >- _d_linit_internal ld-2.19.so 1 448152 4.4 11094 5.3
40# v-__libc_start_main@plt ls 1 8211741 81.5 180397 85.4
41# >- _dl_fixup ld-2.19.so 1 7607 0.1 108 0.1
42# >- __cxa_atexit libc-2.19.so 1 11737 0.1 10 0.0
43# >- __libc_csu_init ls 1 10354 0.1 10 0.0
44# |- _setjmp libc-2.19.so 1 0 0.0 4 0.0
45# v- main ls 1 8182043 99.6 180254 99.9
46#
47# Points to note:
48# The top level is a command name (comm)
49# The next level is a thread (pid:tid)
50# Subsequent levels are functions
51# 'Count' is the number of calls
52# 'Time' is the elapsed time until the function returns
53# Percentages are relative to the level above
54# 'Branch Count' is the total number of branches for that function and all
55# functions that it calls
56
57import sys
58from PySide.QtCore import *
59from PySide.QtGui import *
60from PySide.QtSql import *
61from decimal import *
62
63class TreeItem():
64
65 def __init__(self, db, row, parent_item):
66 self.db = db
67 self.row = row
68 self.parent_item = parent_item
69 self.query_done = False;
70 self.child_count = 0
71 self.child_items = []
72 self.data = ["", "", "", "", "", "", ""]
73 self.comm_id = 0
74 self.thread_id = 0
75 self.call_path_id = 1
76 self.branch_count = 0
77 self.time = 0
78 if not parent_item:
79 self.setUpRoot()
80
81 def setUpRoot(self):
82 self.query_done = True
83 query = QSqlQuery(self.db)
84 ret = query.exec_('SELECT id, comm FROM comms')
85 if not ret:
86 raise Exception("Query failed: " + query.lastError().text())
87 while query.next():
88 if not query.value(0):
89 continue
90 child_item = TreeItem(self.db, self.child_count, self)
91 self.child_items.append(child_item)
92 self.child_count += 1
93 child_item.setUpLevel1(query.value(0), query.value(1))
94
95 def setUpLevel1(self, comm_id, comm):
96 self.query_done = True;
97 self.comm_id = comm_id
98 self.data[0] = comm
99 self.child_items = []
100 self.child_count = 0
101 query = QSqlQuery(self.db)
102 ret = query.exec_('SELECT thread_id, ( SELECT pid FROM threads WHERE id = thread_id ), ( SELECT tid FROM threads WHERE id = thread_id ) FROM comm_threads WHERE comm_id = ' + str(comm_id))
103 if not ret:
104 raise Exception("Query failed: " + query.lastError().text())
105 while query.next():
106 child_item = TreeItem(self.db, self.child_count, self)
107 self.child_items.append(child_item)
108 self.child_count += 1
109 child_item.setUpLevel2(comm_id, query.value(0), query.value(1), query.value(2))
110
111 def setUpLevel2(self, comm_id, thread_id, pid, tid):
112 self.comm_id = comm_id
113 self.thread_id = thread_id
114 self.data[0] = str(pid) + ":" + str(tid)
115
116 def getChildItem(self, row):
117 return self.child_items[row]
118
119 def getParentItem(self):
120 return self.parent_item
121
122 def getRow(self):
123 return self.row
124
125 def timePercent(self, b):
126 if not self.time:
127 return "0.0"
128 x = (b * Decimal(100)) / self.time
129 return str(x.quantize(Decimal('.1'), rounding=ROUND_HALF_UP))
130
131 def branchPercent(self, b):
132 if not self.branch_count:
133 return "0.0"
134 x = (b * Decimal(100)) / self.branch_count
135 return str(x.quantize(Decimal('.1'), rounding=ROUND_HALF_UP))
136
137 def addChild(self, call_path_id, name, dso, count, time, branch_count):
138 child_item = TreeItem(self.db, self.child_count, self)
139 child_item.comm_id = self.comm_id
140 child_item.thread_id = self.thread_id
141 child_item.call_path_id = call_path_id
142 child_item.branch_count = branch_count
143 child_item.time = time
144 child_item.data[0] = name
145 if dso == "[kernel.kallsyms]":
146 dso = "[kernel]"
147 child_item.data[1] = dso
148 child_item.data[2] = str(count)
149 child_item.data[3] = str(time)
150 child_item.data[4] = self.timePercent(time)
151 child_item.data[5] = str(branch_count)
152 child_item.data[6] = self.branchPercent(branch_count)
153 self.child_items.append(child_item)
154 self.child_count += 1
155
156 def selectCalls(self):
157 self.query_done = True;
158 query = QSqlQuery(self.db)
159 ret = query.exec_('SELECT id, call_path_id, branch_count, call_time, return_time, '
160 '( SELECT name FROM symbols WHERE id = ( SELECT symbol_id FROM call_paths WHERE id = call_path_id ) ), '
161 '( SELECT short_name FROM dsos WHERE id = ( SELECT dso_id FROM symbols WHERE id = ( SELECT symbol_id FROM call_paths WHERE id = call_path_id ) ) ), '
162 '( SELECT ip FROM call_paths where id = call_path_id ) '
163 'FROM calls WHERE parent_call_path_id = ' + str(self.call_path_id) + ' AND comm_id = ' + str(self.comm_id) + ' AND thread_id = ' + str(self.thread_id) +
164 ' ORDER BY call_path_id')
165 if not ret:
166 raise Exception("Query failed: " + query.lastError().text())
167 last_call_path_id = 0
168 name = ""
169 dso = ""
170 count = 0
171 branch_count = 0
172 total_branch_count = 0
173 time = 0
174 total_time = 0
175 while query.next():
176 if query.value(1) == last_call_path_id:
177 count += 1
178 branch_count += query.value(2)
179 time += query.value(4) - query.value(3)
180 else:
181 if count:
182 self.addChild(last_call_path_id, name, dso, count, time, branch_count)
183 last_call_path_id = query.value(1)
184 name = query.value(5)
185 dso = query.value(6)
186 count = 1
187 total_branch_count += branch_count
188 total_time += time
189 branch_count = query.value(2)
190 time = query.value(4) - query.value(3)
191 if count:
192 self.addChild(last_call_path_id, name, dso, count, time, branch_count)
193 total_branch_count += branch_count
194 total_time += time
195 # Top level does not have time or branch count, so fix that here
196 if total_branch_count > self.branch_count:
197 self.branch_count = total_branch_count
198 if self.branch_count:
199 for child_item in self.child_items:
200 child_item.data[6] = self.branchPercent(child_item.branch_count)
201 if total_time > self.time:
202 self.time = total_time
203 if self.time:
204 for child_item in self.child_items:
205 child_item.data[4] = self.timePercent(child_item.time)
206
207 def childCount(self):
208 if not self.query_done:
209 self.selectCalls()
210 return self.child_count
211
212 def columnCount(self):
213 return 7
214
215 def columnHeader(self, column):
216 headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
217 return headers[column]
218
219 def getData(self, column):
220 return self.data[column]
221
222class TreeModel(QAbstractItemModel):
223
224 def __init__(self, db, parent=None):
225 super(TreeModel, self).__init__(parent)
226 self.db = db
227 self.root = TreeItem(db, 0, None)
228
229 def columnCount(self, parent):
230 return self.root.columnCount()
231
232 def rowCount(self, parent):
233 if parent.isValid():
234 parent_item = parent.internalPointer()
235 else:
236 parent_item = self.root
237 return parent_item.childCount()
238
239 def headerData(self, section, orientation, role):
240 if role == Qt.TextAlignmentRole:
241 if section > 1:
242 return Qt.AlignRight
243 if role != Qt.DisplayRole:
244 return None
245 if orientation != Qt.Horizontal:
246 return None
247 return self.root.columnHeader(section)
248
249 def parent(self, child):
250 child_item = child.internalPointer()
251 if child_item is self.root:
252 return QModelIndex()
253 parent_item = child_item.getParentItem()
254 return self.createIndex(parent_item.getRow(), 0, parent_item)
255
256 def index(self, row, column, parent):
257 if parent.isValid():
258 parent_item = parent.internalPointer()
259 else:
260 parent_item = self.root
261 child_item = parent_item.getChildItem(row)
262 return self.createIndex(row, column, child_item)
263
264 def data(self, index, role):
265 if role == Qt.TextAlignmentRole:
266 if index.column() > 1:
267 return Qt.AlignRight
268 if role != Qt.DisplayRole:
269 return None
270 index_item = index.internalPointer()
271 return index_item.getData(index.column())
272
273class MainWindow(QMainWindow):
274
275 def __init__(self, db, dbname, parent=None):
276 super(MainWindow, self).__init__(parent)
277
278 self.setObjectName("MainWindow")
279 self.setWindowTitle("Call Graph: " + dbname)
280 self.move(100, 100)
281 self.resize(800, 600)
282 style = self.style()
283 icon = style.standardIcon(QStyle.SP_MessageBoxInformation)
284 self.setWindowIcon(icon);
285
286 self.model = TreeModel(db)
287
288 self.view = QTreeView()
289 self.view.setModel(self.model)
290
291 self.setCentralWidget(self.view)
292
293if __name__ == '__main__':
294 if (len(sys.argv) < 2):
295 print >> sys.stderr, "Usage is: call-graph-from-sql.py <database name>"
296 raise Exception("Too few arguments")
297
298 dbname = sys.argv[1]
299
300 is_sqlite3 = False
301 try:
302 f = open(dbname)
303 if f.read(15) == "SQLite format 3":
304 is_sqlite3 = True
305 f.close()
306 except:
307 pass
308
309 if is_sqlite3:
310 db = QSqlDatabase.addDatabase('QSQLITE')
311 else:
312 db = QSqlDatabase.addDatabase('QPSQL')
313 opts = dbname.split()
314 for opt in opts:
315 if '=' in opt:
316 opt = opt.split('=')
317 if opt[0] == 'hostname':
318 db.setHostName(opt[1])
319 elif opt[0] == 'port':
320 db.setPort(int(opt[1]))
321 elif opt[0] == 'username':
322 db.setUserName(opt[1])
323 elif opt[0] == 'password':
324 db.setPassword(opt[1])
325 elif opt[0] == 'dbname':
326 dbname = opt[1]
327 else:
328 dbname = opt
329
330 db.setDatabaseName(dbname)
331 if not db.open():
332 raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
333
334 app = QApplication(sys.argv)
335 window = MainWindow(db, dbname)
336 window.show()
337 err = app.exec_()
338 db.close()
339 sys.exit(err)
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index efcaf6cac2eb..0564dd7377f2 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -59,7 +59,7 @@ import datetime
59# pt_example=# \q 59# pt_example=# \q
60# 60#
61# An example of using the database is provided by the script 61# An example of using the database is provided by the script
62# call-graph-from-sql.py. Refer to that script for details. 62# exported-sql-viewer.py. Refer to that script for details.
63# 63#
64# Tables: 64# Tables:
65# 65#
@@ -204,14 +204,23 @@ from ctypes import *
204libpq = CDLL("libpq.so.5") 204libpq = CDLL("libpq.so.5")
205PQconnectdb = libpq.PQconnectdb 205PQconnectdb = libpq.PQconnectdb
206PQconnectdb.restype = c_void_p 206PQconnectdb.restype = c_void_p
207PQconnectdb.argtypes = [ c_char_p ]
207PQfinish = libpq.PQfinish 208PQfinish = libpq.PQfinish
209PQfinish.argtypes = [ c_void_p ]
208PQstatus = libpq.PQstatus 210PQstatus = libpq.PQstatus
211PQstatus.restype = c_int
212PQstatus.argtypes = [ c_void_p ]
209PQexec = libpq.PQexec 213PQexec = libpq.PQexec
210PQexec.restype = c_void_p 214PQexec.restype = c_void_p
215PQexec.argtypes = [ c_void_p, c_char_p ]
211PQresultStatus = libpq.PQresultStatus 216PQresultStatus = libpq.PQresultStatus
217PQresultStatus.restype = c_int
218PQresultStatus.argtypes = [ c_void_p ]
212PQputCopyData = libpq.PQputCopyData 219PQputCopyData = libpq.PQputCopyData
220PQputCopyData.restype = c_int
213PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ] 221PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ]
214PQputCopyEnd = libpq.PQputCopyEnd 222PQputCopyEnd = libpq.PQputCopyEnd
223PQputCopyEnd.restype = c_int
215PQputCopyEnd.argtypes = [ c_void_p, c_void_p ] 224PQputCopyEnd.argtypes = [ c_void_p, c_void_p ]
216 225
217sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 226sys.path.append(os.environ['PERF_EXEC_PATH'] + \
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py
index f827bf77e9d2..245caf2643ed 100644
--- a/tools/perf/scripts/python/export-to-sqlite.py
+++ b/tools/perf/scripts/python/export-to-sqlite.py
@@ -40,7 +40,7 @@ import datetime
40# sqlite> .quit 40# sqlite> .quit
41# 41#
42# An example of using the database is provided by the script 42# An example of using the database is provided by the script
43# call-graph-from-sql.py. Refer to that script for details. 43# exported-sql-viewer.py. Refer to that script for details.
44# 44#
45# The database structure is practically the same as created by the script 45# The database structure is practically the same as created by the script
46# export-to-postgresql.py. Refer to that script for details. A notable 46# export-to-postgresql.py. Refer to that script for details. A notable
@@ -440,7 +440,11 @@ def branch_type_table(*x):
440 440
441def sample_table(*x): 441def sample_table(*x):
442 if branches: 442 if branches:
443 bind_exec(sample_query, 18, x) 443 for xx in x[0:15]:
444 sample_query.addBindValue(str(xx))
445 for xx in x[19:22]:
446 sample_query.addBindValue(str(xx))
447 do_query_(sample_query)
444 else: 448 else:
445 bind_exec(sample_query, 22, x) 449 bind_exec(sample_query, 22, x)
446 450
diff --git a/tools/perf/scripts/python/exported-sql-viewer.py b/tools/perf/scripts/python/exported-sql-viewer.py
new file mode 100755
index 000000000000..f278ce5ebab7
--- /dev/null
+++ b/tools/perf/scripts/python/exported-sql-viewer.py
@@ -0,0 +1,2615 @@
1#!/usr/bin/python2
2# SPDX-License-Identifier: GPL-2.0
3# exported-sql-viewer.py: view data from sql database
4# Copyright (c) 2014-2018, Intel Corporation.
5
6# To use this script you will need to have exported data using either the
7# export-to-sqlite.py or the export-to-postgresql.py script. Refer to those
8# scripts for details.
9#
10# Following on from the example in the export scripts, a
11# call-graph can be displayed for the pt_example database like this:
12#
13# python tools/perf/scripts/python/exported-sql-viewer.py pt_example
14#
15# Note that for PostgreSQL, this script supports connecting to remote databases
16# by setting hostname, port, username, password, and dbname e.g.
17#
18# python tools/perf/scripts/python/exported-sql-viewer.py "hostname=myhost username=myuser password=mypassword dbname=pt_example"
19#
20# The result is a GUI window with a tree representing a context-sensitive
21# call-graph. Expanding a couple of levels of the tree and adjusting column
22# widths to suit will display something like:
23#
24# Call Graph: pt_example
25# Call Path Object Count Time(ns) Time(%) Branch Count Branch Count(%)
26# v- ls
27# v- 2638:2638
28# v- _start ld-2.19.so 1 10074071 100.0 211135 100.0
29# |- unknown unknown 1 13198 0.1 1 0.0
30# >- _dl_start ld-2.19.so 1 1400980 13.9 19637 9.3
31# >- _d_linit_internal ld-2.19.so 1 448152 4.4 11094 5.3
32# v-__libc_start_main@plt ls 1 8211741 81.5 180397 85.4
33# >- _dl_fixup ld-2.19.so 1 7607 0.1 108 0.1
34# >- __cxa_atexit libc-2.19.so 1 11737 0.1 10 0.0
35# >- __libc_csu_init ls 1 10354 0.1 10 0.0
36# |- _setjmp libc-2.19.so 1 0 0.0 4 0.0
37# v- main ls 1 8182043 99.6 180254 99.9
38#
39# Points to note:
40# The top level is a command name (comm)
41# The next level is a thread (pid:tid)
42# Subsequent levels are functions
43# 'Count' is the number of calls
44# 'Time' is the elapsed time until the function returns
45# Percentages are relative to the level above
46# 'Branch Count' is the total number of branches for that function and all
47# functions that it calls
48
49# There is also a "All branches" report, which displays branches and
50# possibly disassembly. However, presently, the only supported disassembler is
51# Intel XED, and additionally the object code must be present in perf build ID
52# cache. To use Intel XED, libxed.so must be present. To build and install
53# libxed.so:
54# git clone https://github.com/intelxed/mbuild.git mbuild
55# git clone https://github.com/intelxed/xed
56# cd xed
57# ./mfile.py --share
58# sudo ./mfile.py --prefix=/usr/local install
59# sudo ldconfig
60#
61# Example report:
62#
63# Time CPU Command PID TID Branch Type In Tx Branch
64# 8107675239590 2 ls 22011 22011 return from interrupt No ffffffff86a00a67 native_irq_return_iret ([kernel]) -> 7fab593ea260 _start (ld-2.19.so)
65# 7fab593ea260 48 89 e7 mov %rsp, %rdi
66# 8107675239899 2 ls 22011 22011 hardware interrupt No 7fab593ea260 _start (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel])
67# 8107675241900 2 ls 22011 22011 return from interrupt No ffffffff86a00a67 native_irq_return_iret ([kernel]) -> 7fab593ea260 _start (ld-2.19.so)
68# 7fab593ea260 48 89 e7 mov %rsp, %rdi
69# 7fab593ea263 e8 c8 06 00 00 callq 0x7fab593ea930
70# 8107675241900 2 ls 22011 22011 call No 7fab593ea263 _start+0x3 (ld-2.19.so) -> 7fab593ea930 _dl_start (ld-2.19.so)
71# 7fab593ea930 55 pushq %rbp
72# 7fab593ea931 48 89 e5 mov %rsp, %rbp
73# 7fab593ea934 41 57 pushq %r15
74# 7fab593ea936 41 56 pushq %r14
75# 7fab593ea938 41 55 pushq %r13
76# 7fab593ea93a 41 54 pushq %r12
77# 7fab593ea93c 53 pushq %rbx
78# 7fab593ea93d 48 89 fb mov %rdi, %rbx
79# 7fab593ea940 48 83 ec 68 sub $0x68, %rsp
80# 7fab593ea944 0f 31 rdtsc
81# 7fab593ea946 48 c1 e2 20 shl $0x20, %rdx
82# 7fab593ea94a 89 c0 mov %eax, %eax
83# 7fab593ea94c 48 09 c2 or %rax, %rdx
84# 7fab593ea94f 48 8b 05 1a 15 22 00 movq 0x22151a(%rip), %rax
85# 8107675242232 2 ls 22011 22011 hardware interrupt No 7fab593ea94f _dl_start+0x1f (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel])
86# 8107675242900 2 ls 22011 22011 return from interrupt No ffffffff86a00a67 native_irq_return_iret ([kernel]) -> 7fab593ea94f _dl_start+0x1f (ld-2.19.so)
87# 7fab593ea94f 48 8b 05 1a 15 22 00 movq 0x22151a(%rip), %rax
88# 7fab593ea956 48 89 15 3b 13 22 00 movq %rdx, 0x22133b(%rip)
89# 8107675243232 2 ls 22011 22011 hardware interrupt No 7fab593ea956 _dl_start+0x26 (ld-2.19.so) -> ffffffff86a012e0 page_fault ([kernel])
90
91import sys
92import weakref
93import threading
94import string
95import cPickle
96import re
97import os
98from PySide.QtCore import *
99from PySide.QtGui import *
100from PySide.QtSql import *
101from decimal import *
102from ctypes import *
103from multiprocessing import Process, Array, Value, Event
104
105# Data formatting helpers
106
107def tohex(ip):
108 if ip < 0:
109 ip += 1 << 64
110 return "%x" % ip
111
112def offstr(offset):
113 if offset:
114 return "+0x%x" % offset
115 return ""
116
117def dsoname(name):
118 if name == "[kernel.kallsyms]":
119 return "[kernel]"
120 return name
121
122def findnth(s, sub, n, offs=0):
123 pos = s.find(sub)
124 if pos < 0:
125 return pos
126 if n <= 1:
127 return offs + pos
128 return findnth(s[pos + 1:], sub, n - 1, offs + pos + 1)
129
130# Percent to one decimal place
131
132def PercentToOneDP(n, d):
133 if not d:
134 return "0.0"
135 x = (n * Decimal(100)) / d
136 return str(x.quantize(Decimal(".1"), rounding=ROUND_HALF_UP))
137
138# Helper for queries that must not fail
139
140def QueryExec(query, stmt):
141 ret = query.exec_(stmt)
142 if not ret:
143 raise Exception("Query failed: " + query.lastError().text())
144
145# Background thread
146
147class Thread(QThread):
148
149 done = Signal(object)
150
151 def __init__(self, task, param=None, parent=None):
152 super(Thread, self).__init__(parent)
153 self.task = task
154 self.param = param
155
156 def run(self):
157 while True:
158 if self.param is None:
159 done, result = self.task()
160 else:
161 done, result = self.task(self.param)
162 self.done.emit(result)
163 if done:
164 break
165
166# Tree data model
167
168class TreeModel(QAbstractItemModel):
169
170 def __init__(self, root, parent=None):
171 super(TreeModel, self).__init__(parent)
172 self.root = root
173 self.last_row_read = 0
174
175 def Item(self, parent):
176 if parent.isValid():
177 return parent.internalPointer()
178 else:
179 return self.root
180
181 def rowCount(self, parent):
182 result = self.Item(parent).childCount()
183 if result < 0:
184 result = 0
185 self.dataChanged.emit(parent, parent)
186 return result
187
188 def hasChildren(self, parent):
189 return self.Item(parent).hasChildren()
190
191 def headerData(self, section, orientation, role):
192 if role == Qt.TextAlignmentRole:
193 return self.columnAlignment(section)
194 if role != Qt.DisplayRole:
195 return None
196 if orientation != Qt.Horizontal:
197 return None
198 return self.columnHeader(section)
199
200 def parent(self, child):
201 child_item = child.internalPointer()
202 if child_item is self.root:
203 return QModelIndex()
204 parent_item = child_item.getParentItem()
205 return self.createIndex(parent_item.getRow(), 0, parent_item)
206
207 def index(self, row, column, parent):
208 child_item = self.Item(parent).getChildItem(row)
209 return self.createIndex(row, column, child_item)
210
211 def DisplayData(self, item, index):
212 return item.getData(index.column())
213
214 def FetchIfNeeded(self, row):
215 if row > self.last_row_read:
216 self.last_row_read = row
217 if row + 10 >= self.root.child_count:
218 self.fetcher.Fetch(glb_chunk_sz)
219
220 def columnAlignment(self, column):
221 return Qt.AlignLeft
222
223 def columnFont(self, column):
224 return None
225
226 def data(self, index, role):
227 if role == Qt.TextAlignmentRole:
228 return self.columnAlignment(index.column())
229 if role == Qt.FontRole:
230 return self.columnFont(index.column())
231 if role != Qt.DisplayRole:
232 return None
233 item = index.internalPointer()
234 return self.DisplayData(item, index)
235
236# Table data model
237
238class TableModel(QAbstractTableModel):
239
240 def __init__(self, parent=None):
241 super(TableModel, self).__init__(parent)
242 self.child_count = 0
243 self.child_items = []
244 self.last_row_read = 0
245
246 def Item(self, parent):
247 if parent.isValid():
248 return parent.internalPointer()
249 else:
250 return self
251
252 def rowCount(self, parent):
253 return self.child_count
254
255 def headerData(self, section, orientation, role):
256 if role == Qt.TextAlignmentRole:
257 return self.columnAlignment(section)
258 if role != Qt.DisplayRole:
259 return None
260 if orientation != Qt.Horizontal:
261 return None
262 return self.columnHeader(section)
263
264 def index(self, row, column, parent):
265 return self.createIndex(row, column, self.child_items[row])
266
267 def DisplayData(self, item, index):
268 return item.getData(index.column())
269
270 def FetchIfNeeded(self, row):
271 if row > self.last_row_read:
272 self.last_row_read = row
273 if row + 10 >= self.child_count:
274 self.fetcher.Fetch(glb_chunk_sz)
275
276 def columnAlignment(self, column):
277 return Qt.AlignLeft
278
279 def columnFont(self, column):
280 return None
281
282 def data(self, index, role):
283 if role == Qt.TextAlignmentRole:
284 return self.columnAlignment(index.column())
285 if role == Qt.FontRole:
286 return self.columnFont(index.column())
287 if role != Qt.DisplayRole:
288 return None
289 item = index.internalPointer()
290 return self.DisplayData(item, index)
291
292# Model cache
293
294model_cache = weakref.WeakValueDictionary()
295model_cache_lock = threading.Lock()
296
297def LookupCreateModel(model_name, create_fn):
298 model_cache_lock.acquire()
299 try:
300 model = model_cache[model_name]
301 except:
302 model = None
303 if model is None:
304 model = create_fn()
305 model_cache[model_name] = model
306 model_cache_lock.release()
307 return model
308
309# Find bar
310
311class FindBar():
312
313 def __init__(self, parent, finder, is_reg_expr=False):
314 self.finder = finder
315 self.context = []
316 self.last_value = None
317 self.last_pattern = None
318
319 label = QLabel("Find:")
320 label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
321
322 self.textbox = QComboBox()
323 self.textbox.setEditable(True)
324 self.textbox.currentIndexChanged.connect(self.ValueChanged)
325
326 self.progress = QProgressBar()
327 self.progress.setRange(0, 0)
328 self.progress.hide()
329
330 if is_reg_expr:
331 self.pattern = QCheckBox("Regular Expression")
332 else:
333 self.pattern = QCheckBox("Pattern")
334 self.pattern.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
335
336 self.next_button = QToolButton()
337 self.next_button.setIcon(parent.style().standardIcon(QStyle.SP_ArrowDown))
338 self.next_button.released.connect(lambda: self.NextPrev(1))
339
340 self.prev_button = QToolButton()
341 self.prev_button.setIcon(parent.style().standardIcon(QStyle.SP_ArrowUp))
342 self.prev_button.released.connect(lambda: self.NextPrev(-1))
343
344 self.close_button = QToolButton()
345 self.close_button.setIcon(parent.style().standardIcon(QStyle.SP_DockWidgetCloseButton))
346 self.close_button.released.connect(self.Deactivate)
347
348 self.hbox = QHBoxLayout()
349 self.hbox.setContentsMargins(0, 0, 0, 0)
350
351 self.hbox.addWidget(label)
352 self.hbox.addWidget(self.textbox)
353 self.hbox.addWidget(self.progress)
354 self.hbox.addWidget(self.pattern)
355 self.hbox.addWidget(self.next_button)
356 self.hbox.addWidget(self.prev_button)
357 self.hbox.addWidget(self.close_button)
358
359 self.bar = QWidget()
360 self.bar.setLayout(self.hbox);
361 self.bar.hide()
362
363 def Widget(self):
364 return self.bar
365
366 def Activate(self):
367 self.bar.show()
368 self.textbox.setFocus()
369
370 def Deactivate(self):
371 self.bar.hide()
372
373 def Busy(self):
374 self.textbox.setEnabled(False)
375 self.pattern.hide()
376 self.next_button.hide()
377 self.prev_button.hide()
378 self.progress.show()
379
380 def Idle(self):
381 self.textbox.setEnabled(True)
382 self.progress.hide()
383 self.pattern.show()
384 self.next_button.show()
385 self.prev_button.show()
386
387 def Find(self, direction):
388 value = self.textbox.currentText()
389 pattern = self.pattern.isChecked()
390 self.last_value = value
391 self.last_pattern = pattern
392 self.finder.Find(value, direction, pattern, self.context)
393
394 def ValueChanged(self):
395 value = self.textbox.currentText()
396 pattern = self.pattern.isChecked()
397 index = self.textbox.currentIndex()
398 data = self.textbox.itemData(index)
399 # Store the pattern in the combo box to keep it with the text value
400 if data == None:
401 self.textbox.setItemData(index, pattern)
402 else:
403 self.pattern.setChecked(data)
404 self.Find(0)
405
406 def NextPrev(self, direction):
407 value = self.textbox.currentText()
408 pattern = self.pattern.isChecked()
409 if value != self.last_value:
410 index = self.textbox.findText(value)
411 # Allow for a button press before the value has been added to the combo box
412 if index < 0:
413 index = self.textbox.count()
414 self.textbox.addItem(value, pattern)
415 self.textbox.setCurrentIndex(index)
416 return
417 else:
418 self.textbox.setItemData(index, pattern)
419 elif pattern != self.last_pattern:
420 # Keep the pattern recorded in the combo box up to date
421 index = self.textbox.currentIndex()
422 self.textbox.setItemData(index, pattern)
423 self.Find(direction)
424
425 def NotFound(self):
426 QMessageBox.information(self.bar, "Find", "'" + self.textbox.currentText() + "' not found")
427
428# Context-sensitive call graph data model item base
429
430class CallGraphLevelItemBase(object):
431
432 def __init__(self, glb, row, parent_item):
433 self.glb = glb
434 self.row = row
435 self.parent_item = parent_item
436 self.query_done = False;
437 self.child_count = 0
438 self.child_items = []
439
440 def getChildItem(self, row):
441 return self.child_items[row]
442
443 def getParentItem(self):
444 return self.parent_item
445
446 def getRow(self):
447 return self.row
448
449 def childCount(self):
450 if not self.query_done:
451 self.Select()
452 if not self.child_count:
453 return -1
454 return self.child_count
455
456 def hasChildren(self):
457 if not self.query_done:
458 return True
459 return self.child_count > 0
460
461 def getData(self, column):
462 return self.data[column]
463
464# Context-sensitive call graph data model level 2+ item base
465
466class CallGraphLevelTwoPlusItemBase(CallGraphLevelItemBase):
467
468 def __init__(self, glb, row, comm_id, thread_id, call_path_id, time, branch_count, parent_item):
469 super(CallGraphLevelTwoPlusItemBase, self).__init__(glb, row, parent_item)
470 self.comm_id = comm_id
471 self.thread_id = thread_id
472 self.call_path_id = call_path_id
473 self.branch_count = branch_count
474 self.time = time
475
476 def Select(self):
477 self.query_done = True;
478 query = QSqlQuery(self.glb.db)
479 QueryExec(query, "SELECT call_path_id, name, short_name, COUNT(calls.id), SUM(return_time - call_time), SUM(branch_count)"
480 " FROM calls"
481 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
482 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
483 " INNER JOIN dsos ON symbols.dso_id = dsos.id"
484 " WHERE parent_call_path_id = " + str(self.call_path_id) +
485 " AND comm_id = " + str(self.comm_id) +
486 " AND thread_id = " + str(self.thread_id) +
487 " GROUP BY call_path_id, name, short_name"
488 " ORDER BY call_path_id")
489 while query.next():
490 child_item = CallGraphLevelThreeItem(self.glb, self.child_count, self.comm_id, self.thread_id, query.value(0), query.value(1), query.value(2), query.value(3), int(query.value(4)), int(query.value(5)), self)
491 self.child_items.append(child_item)
492 self.child_count += 1
493
494# Context-sensitive call graph data model level three item
495
496class CallGraphLevelThreeItem(CallGraphLevelTwoPlusItemBase):
497
498 def __init__(self, glb, row, comm_id, thread_id, call_path_id, name, dso, count, time, branch_count, parent_item):
499 super(CallGraphLevelThreeItem, self).__init__(glb, row, comm_id, thread_id, call_path_id, time, branch_count, parent_item)
500 dso = dsoname(dso)
501 self.data = [ name, dso, str(count), str(time), PercentToOneDP(time, parent_item.time), str(branch_count), PercentToOneDP(branch_count, parent_item.branch_count) ]
502 self.dbid = call_path_id
503
504# Context-sensitive call graph data model level two item
505
506class CallGraphLevelTwoItem(CallGraphLevelTwoPlusItemBase):
507
508 def __init__(self, glb, row, comm_id, thread_id, pid, tid, parent_item):
509 super(CallGraphLevelTwoItem, self).__init__(glb, row, comm_id, thread_id, 1, 0, 0, parent_item)
510 self.data = [str(pid) + ":" + str(tid), "", "", "", "", "", ""]
511 self.dbid = thread_id
512
513 def Select(self):
514 super(CallGraphLevelTwoItem, self).Select()
515 for child_item in self.child_items:
516 self.time += child_item.time
517 self.branch_count += child_item.branch_count
518 for child_item in self.child_items:
519 child_item.data[4] = PercentToOneDP(child_item.time, self.time)
520 child_item.data[6] = PercentToOneDP(child_item.branch_count, self.branch_count)
521
522# Context-sensitive call graph data model level one item
523
524class CallGraphLevelOneItem(CallGraphLevelItemBase):
525
526 def __init__(self, glb, row, comm_id, comm, parent_item):
527 super(CallGraphLevelOneItem, self).__init__(glb, row, parent_item)
528 self.data = [comm, "", "", "", "", "", ""]
529 self.dbid = comm_id
530
531 def Select(self):
532 self.query_done = True;
533 query = QSqlQuery(self.glb.db)
534 QueryExec(query, "SELECT thread_id, pid, tid"
535 " FROM comm_threads"
536 " INNER JOIN threads ON thread_id = threads.id"
537 " WHERE comm_id = " + str(self.dbid))
538 while query.next():
539 child_item = CallGraphLevelTwoItem(self.glb, self.child_count, self.dbid, query.value(0), query.value(1), query.value(2), self)
540 self.child_items.append(child_item)
541 self.child_count += 1
542
543# Context-sensitive call graph data model root item
544
545class CallGraphRootItem(CallGraphLevelItemBase):
546
547 def __init__(self, glb):
548 super(CallGraphRootItem, self).__init__(glb, 0, None)
549 self.dbid = 0
550 self.query_done = True;
551 query = QSqlQuery(glb.db)
552 QueryExec(query, "SELECT id, comm FROM comms")
553 while query.next():
554 if not query.value(0):
555 continue
556 child_item = CallGraphLevelOneItem(glb, self.child_count, query.value(0), query.value(1), self)
557 self.child_items.append(child_item)
558 self.child_count += 1
559
560# Context-sensitive call graph data model
561
562class CallGraphModel(TreeModel):
563
564 def __init__(self, glb, parent=None):
565 super(CallGraphModel, self).__init__(CallGraphRootItem(glb), parent)
566 self.glb = glb
567
568 def columnCount(self, parent=None):
569 return 7
570
571 def columnHeader(self, column):
572 headers = ["Call Path", "Object", "Count ", "Time (ns) ", "Time (%) ", "Branch Count ", "Branch Count (%) "]
573 return headers[column]
574
575 def columnAlignment(self, column):
576 alignment = [ Qt.AlignLeft, Qt.AlignLeft, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight, Qt.AlignRight ]
577 return alignment[column]
578
579 def FindSelect(self, value, pattern, query):
580 if pattern:
581 # postgresql and sqlite pattern patching differences:
582 # postgresql LIKE is case sensitive but sqlite LIKE is not
583 # postgresql LIKE allows % and _ to be escaped with \ but sqlite LIKE does not
584 # postgresql supports ILIKE which is case insensitive
585 # sqlite supports GLOB (text only) which uses * and ? and is case sensitive
586 if not self.glb.dbref.is_sqlite3:
587 # Escape % and _
588 s = value.replace("%", "\%")
589 s = s.replace("_", "\_")
590 # Translate * and ? into SQL LIKE pattern characters % and _
591 trans = string.maketrans("*?", "%_")
592 match = " LIKE '" + str(s).translate(trans) + "'"
593 else:
594 match = " GLOB '" + str(value) + "'"
595 else:
596 match = " = '" + str(value) + "'"
597 QueryExec(query, "SELECT call_path_id, comm_id, thread_id"
598 " FROM calls"
599 " INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
600 " INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
601 " WHERE symbols.name" + match +
602 " GROUP BY comm_id, thread_id, call_path_id"
603 " ORDER BY comm_id, thread_id, call_path_id")
604
605 def FindPath(self, query):
606 # Turn the query result into a list of ids that the tree view can walk
607 # to open the tree at the right place.
608 ids = []
609 parent_id = query.value(0)
610 while parent_id:
611 ids.insert(0, parent_id)
612 q2 = QSqlQuery(self.glb.db)
613 QueryExec(q2, "SELECT parent_id"
614 " FROM call_paths"
615 " WHERE id = " + str(parent_id))
616 if not q2.next():
617 break
618 parent_id = q2.value(0)
619 # The call path root is not used
620 if ids[0] == 1:
621 del ids[0]
622 ids.insert(0, query.value(2))
623 ids.insert(0, query.value(1))
624 return ids
625
626 def Found(self, query, found):
627 if found:
628 return self.FindPath(query)
629 return []
630
631 def FindValue(self, value, pattern, query, last_value, last_pattern):
632 if last_value == value and pattern == last_pattern:
633 found = query.first()
634 else:
635 self.FindSelect(value, pattern, query)
636 found = query.next()
637 return self.Found(query, found)
638
639 def FindNext(self, query):
640 found = query.next()
641 if not found:
642 found = query.first()
643 return self.Found(query, found)
644
645 def FindPrev(self, query):
646 found = query.previous()
647 if not found:
648 found = query.last()
649 return self.Found(query, found)
650
651 def FindThread(self, c):
652 if c.direction == 0 or c.value != c.last_value or c.pattern != c.last_pattern:
653 ids = self.FindValue(c.value, c.pattern, c.query, c.last_value, c.last_pattern)
654 elif c.direction > 0:
655 ids = self.FindNext(c.query)
656 else:
657 ids = self.FindPrev(c.query)
658 return (True, ids)
659
660 def Find(self, value, direction, pattern, context, callback):
661 class Context():
662 def __init__(self, *x):
663 self.value, self.direction, self.pattern, self.query, self.last_value, self.last_pattern = x
664 def Update(self, *x):
665 self.value, self.direction, self.pattern, self.last_value, self.last_pattern = x + (self.value, self.pattern)
666 if len(context):
667 context[0].Update(value, direction, pattern)
668 else:
669 context.append(Context(value, direction, pattern, QSqlQuery(self.glb.db), None, None))
670 # Use a thread so the UI is not blocked during the SELECT
671 thread = Thread(self.FindThread, context[0])
672 thread.done.connect(lambda ids, t=thread, c=callback: self.FindDone(t, c, ids), Qt.QueuedConnection)
673 thread.start()
674
675 def FindDone(self, thread, callback, ids):
676 callback(ids)
677
678# Vertical widget layout
679
680class VBox():
681
682 def __init__(self, w1, w2, w3=None):
683 self.vbox = QWidget()
684 self.vbox.setLayout(QVBoxLayout());
685
686 self.vbox.layout().setContentsMargins(0, 0, 0, 0)
687
688 self.vbox.layout().addWidget(w1)
689 self.vbox.layout().addWidget(w2)
690 if w3:
691 self.vbox.layout().addWidget(w3)
692
693 def Widget(self):
694 return self.vbox
695
696# Context-sensitive call graph window
697
698class CallGraphWindow(QMdiSubWindow):
699
700 def __init__(self, glb, parent=None):
701 super(CallGraphWindow, self).__init__(parent)
702
703 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x))
704
705 self.view = QTreeView()
706 self.view.setModel(self.model)
707
708 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)):
709 self.view.setColumnWidth(c, w)
710
711 self.find_bar = FindBar(self, self)
712
713 self.vbox = VBox(self.view, self.find_bar.Widget())
714
715 self.setWidget(self.vbox.Widget())
716
717 AddSubWindow(glb.mainwindow.mdi_area, self, "Context-Sensitive Call Graph")
718
719 def DisplayFound(self, ids):
720 if not len(ids):
721 return False
722 parent = QModelIndex()
723 for dbid in ids:
724 found = False
725 n = self.model.rowCount(parent)
726 for row in xrange(n):
727 child = self.model.index(row, 0, parent)
728 if child.internalPointer().dbid == dbid:
729 found = True
730 self.view.setCurrentIndex(child)
731 parent = child
732 break
733 if not found:
734 break
735 return found
736
737 def Find(self, value, direction, pattern, context):
738 self.view.setFocus()
739 self.find_bar.Busy()
740 self.model.Find(value, direction, pattern, context, self.FindDone)
741
742 def FindDone(self, ids):
743 found = True
744 if not self.DisplayFound(ids):
745 found = False
746 self.find_bar.Idle()
747 if not found:
748 self.find_bar.NotFound()
749
750# Child data item finder
751
752class ChildDataItemFinder():
753
754 def __init__(self, root):
755 self.root = root
756 self.value, self.direction, self.pattern, self.last_value, self.last_pattern = (None,) * 5
757 self.rows = []
758 self.pos = 0
759
760 def FindSelect(self):
761 self.rows = []
762 if self.pattern:
763 pattern = re.compile(self.value)
764 for child in self.root.child_items:
765 for column_data in child.data:
766 if re.search(pattern, str(column_data)) is not None:
767 self.rows.append(child.row)
768 break
769 else:
770 for child in self.root.child_items:
771 for column_data in child.data:
772 if self.value in str(column_data):
773 self.rows.append(child.row)
774 break
775
776 def FindValue(self):
777 self.pos = 0
778 if self.last_value != self.value or self.pattern != self.last_pattern:
779 self.FindSelect()
780 if not len(self.rows):
781 return -1
782 return self.rows[self.pos]
783
784 def FindThread(self):
785 if self.direction == 0 or self.value != self.last_value or self.pattern != self.last_pattern:
786 row = self.FindValue()
787 elif len(self.rows):
788 if self.direction > 0:
789 self.pos += 1
790 if self.pos >= len(self.rows):
791 self.pos = 0
792 else:
793 self.pos -= 1
794 if self.pos < 0:
795 self.pos = len(self.rows) - 1
796 row = self.rows[self.pos]
797 else:
798 row = -1
799 return (True, row)
800
801 def Find(self, value, direction, pattern, context, callback):
802 self.value, self.direction, self.pattern, self.last_value, self.last_pattern = (value, direction,pattern, self.value, self.pattern)
803 # Use a thread so the UI is not blocked
804 thread = Thread(self.FindThread)
805 thread.done.connect(lambda row, t=thread, c=callback: self.FindDone(t, c, row), Qt.QueuedConnection)
806 thread.start()
807
808 def FindDone(self, thread, callback, row):
809 callback(row)
810
811# Number of database records to fetch in one go
812
813glb_chunk_sz = 10000
814
815# size of pickled integer big enough for record size
816
817glb_nsz = 8
818
819# Background process for SQL data fetcher
820
821class SQLFetcherProcess():
822
823 def __init__(self, dbref, sql, buffer, head, tail, fetch_count, fetching_done, process_target, wait_event, fetched_event, prep):
824 # Need a unique connection name
825 conn_name = "SQLFetcher" + str(os.getpid())
826 self.db, dbname = dbref.Open(conn_name)
827 self.sql = sql
828 self.buffer = buffer
829 self.head = head
830 self.tail = tail
831 self.fetch_count = fetch_count
832 self.fetching_done = fetching_done
833 self.process_target = process_target
834 self.wait_event = wait_event
835 self.fetched_event = fetched_event
836 self.prep = prep
837 self.query = QSqlQuery(self.db)
838 self.query_limit = 0 if "$$last_id$$" in sql else 2
839 self.last_id = -1
840 self.fetched = 0
841 self.more = True
842 self.local_head = self.head.value
843 self.local_tail = self.tail.value
844
845 def Select(self):
846 if self.query_limit:
847 if self.query_limit == 1:
848 return
849 self.query_limit -= 1
850 stmt = self.sql.replace("$$last_id$$", str(self.last_id))
851 QueryExec(self.query, stmt)
852
853 def Next(self):
854 if not self.query.next():
855 self.Select()
856 if not self.query.next():
857 return None
858 self.last_id = self.query.value(0)
859 return self.prep(self.query)
860
861 def WaitForTarget(self):
862 while True:
863 self.wait_event.clear()
864 target = self.process_target.value
865 if target > self.fetched or target < 0:
866 break
867 self.wait_event.wait()
868 return target
869
870 def HasSpace(self, sz):
871 if self.local_tail <= self.local_head:
872 space = len(self.buffer) - self.local_head
873 if space > sz:
874 return True
875 if space >= glb_nsz:
876 # Use 0 (or space < glb_nsz) to mean there is no more at the top of the buffer
877 nd = cPickle.dumps(0, cPickle.HIGHEST_PROTOCOL)
878 self.buffer[self.local_head : self.local_head + len(nd)] = nd
879 self.local_head = 0
880 if self.local_tail - self.local_head > sz:
881 return True
882 return False
883
884 def WaitForSpace(self, sz):
885 if self.HasSpace(sz):
886 return
887 while True:
888 self.wait_event.clear()
889 self.local_tail = self.tail.value
890 if self.HasSpace(sz):
891 return
892 self.wait_event.wait()
893
894 def AddToBuffer(self, obj):
895 d = cPickle.dumps(obj, cPickle.HIGHEST_PROTOCOL)
896 n = len(d)
897 nd = cPickle.dumps(n, cPickle.HIGHEST_PROTOCOL)
898 sz = n + glb_nsz
899 self.WaitForSpace(sz)
900 pos = self.local_head
901 self.buffer[pos : pos + len(nd)] = nd
902 self.buffer[pos + glb_nsz : pos + sz] = d
903 self.local_head += sz
904
905 def FetchBatch(self, batch_size):
906 fetched = 0
907 while batch_size > fetched:
908 obj = self.Next()
909 if obj is None:
910 self.more = False
911 break
912 self.AddToBuffer(obj)
913 fetched += 1
914 if fetched:
915 self.fetched += fetched
916 with self.fetch_count.get_lock():
917 self.fetch_count.value += fetched
918 self.head.value = self.local_head
919 self.fetched_event.set()
920
921 def Run(self):
922 while self.more:
923 target = self.WaitForTarget()
924 if target < 0:
925 break
926 batch_size = min(glb_chunk_sz, target - self.fetched)
927 self.FetchBatch(batch_size)
928 self.fetching_done.value = True
929 self.fetched_event.set()
930
931def SQLFetcherFn(*x):
932 process = SQLFetcherProcess(*x)
933 process.Run()
934
935# SQL data fetcher
936
937class SQLFetcher(QObject):
938
939 done = Signal(object)
940
941 def __init__(self, glb, sql, prep, process_data, parent=None):
942 super(SQLFetcher, self).__init__(parent)
943 self.process_data = process_data
944 self.more = True
945 self.target = 0
946 self.last_target = 0
947 self.fetched = 0
948 self.buffer_size = 16 * 1024 * 1024
949 self.buffer = Array(c_char, self.buffer_size, lock=False)
950 self.head = Value(c_longlong)
951 self.tail = Value(c_longlong)
952 self.local_tail = 0
953 self.fetch_count = Value(c_longlong)
954 self.fetching_done = Value(c_bool)
955 self.last_count = 0
956 self.process_target = Value(c_longlong)
957 self.wait_event = Event()
958 self.fetched_event = Event()
959 glb.AddInstanceToShutdownOnExit(self)
960 self.process = Process(target=SQLFetcherFn, args=(glb.dbref, sql, self.buffer, self.head, self.tail, self.fetch_count, self.fetching_done, self.process_target, self.wait_event, self.fetched_event, prep))
961 self.process.start()
962 self.thread = Thread(self.Thread)
963 self.thread.done.connect(self.ProcessData, Qt.QueuedConnection)
964 self.thread.start()
965
966 def Shutdown(self):
967 # Tell the thread and process to exit
968 self.process_target.value = -1
969 self.wait_event.set()
970 self.more = False
971 self.fetching_done.value = True
972 self.fetched_event.set()
973
974 def Thread(self):
975 if not self.more:
976 return True, 0
977 while True:
978 self.fetched_event.clear()
979 fetch_count = self.fetch_count.value
980 if fetch_count != self.last_count:
981 break
982 if self.fetching_done.value:
983 self.more = False
984 return True, 0
985 self.fetched_event.wait()
986 count = fetch_count - self.last_count
987 self.last_count = fetch_count
988 self.fetched += count
989 return False, count
990
991 def Fetch(self, nr):
992 if not self.more:
993 # -1 inidcates there are no more
994 return -1
995 result = self.fetched
996 extra = result + nr - self.target
997 if extra > 0:
998 self.target += extra
999 # process_target < 0 indicates shutting down
1000 if self.process_target.value >= 0:
1001 self.process_target.value = self.target
1002 self.wait_event.set()
1003 return result
1004
1005 def RemoveFromBuffer(self):
1006 pos = self.local_tail
1007 if len(self.buffer) - pos < glb_nsz:
1008 pos = 0
1009 n = cPickle.loads(self.buffer[pos : pos + glb_nsz])
1010 if n == 0:
1011 pos = 0
1012 n = cPickle.loads(self.buffer[0 : glb_nsz])
1013 pos += glb_nsz
1014 obj = cPickle.loads(self.buffer[pos : pos + n])
1015 self.local_tail = pos + n
1016 return obj
1017
1018 def ProcessData(self, count):
1019 for i in xrange(count):
1020 obj = self.RemoveFromBuffer()
1021 self.process_data(obj)
1022 self.tail.value = self.local_tail
1023 self.wait_event.set()
1024 self.done.emit(count)
1025
1026# Fetch more records bar
1027
1028class FetchMoreRecordsBar():
1029
1030 def __init__(self, model, parent):
1031 self.model = model
1032
1033 self.label = QLabel("Number of records (x " + "{:,}".format(glb_chunk_sz) + ") to fetch:")
1034 self.label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1035
1036 self.fetch_count = QSpinBox()
1037 self.fetch_count.setRange(1, 1000000)
1038 self.fetch_count.setValue(10)
1039 self.fetch_count.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1040
1041 self.fetch = QPushButton("Go!")
1042 self.fetch.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1043 self.fetch.released.connect(self.FetchMoreRecords)
1044
1045 self.progress = QProgressBar()
1046 self.progress.setRange(0, 100)
1047 self.progress.hide()
1048
1049 self.done_label = QLabel("All records fetched")
1050 self.done_label.hide()
1051
1052 self.spacer = QLabel("")
1053
1054 self.close_button = QToolButton()
1055 self.close_button.setIcon(parent.style().standardIcon(QStyle.SP_DockWidgetCloseButton))
1056 self.close_button.released.connect(self.Deactivate)
1057
1058 self.hbox = QHBoxLayout()
1059 self.hbox.setContentsMargins(0, 0, 0, 0)
1060
1061 self.hbox.addWidget(self.label)
1062 self.hbox.addWidget(self.fetch_count)
1063 self.hbox.addWidget(self.fetch)
1064 self.hbox.addWidget(self.spacer)
1065 self.hbox.addWidget(self.progress)
1066 self.hbox.addWidget(self.done_label)
1067 self.hbox.addWidget(self.close_button)
1068
1069 self.bar = QWidget()
1070 self.bar.setLayout(self.hbox);
1071 self.bar.show()
1072
1073 self.in_progress = False
1074 self.model.progress.connect(self.Progress)
1075
1076 self.done = False
1077
1078 if not model.HasMoreRecords():
1079 self.Done()
1080
1081 def Widget(self):
1082 return self.bar
1083
1084 def Activate(self):
1085 self.bar.show()
1086 self.fetch.setFocus()
1087
1088 def Deactivate(self):
1089 self.bar.hide()
1090
1091 def Enable(self, enable):
1092 self.fetch.setEnabled(enable)
1093 self.fetch_count.setEnabled(enable)
1094
1095 def Busy(self):
1096 self.Enable(False)
1097 self.fetch.hide()
1098 self.spacer.hide()
1099 self.progress.show()
1100
1101 def Idle(self):
1102 self.in_progress = False
1103 self.Enable(True)
1104 self.progress.hide()
1105 self.fetch.show()
1106 self.spacer.show()
1107
1108 def Target(self):
1109 return self.fetch_count.value() * glb_chunk_sz
1110
1111 def Done(self):
1112 self.done = True
1113 self.Idle()
1114 self.label.hide()
1115 self.fetch_count.hide()
1116 self.fetch.hide()
1117 self.spacer.hide()
1118 self.done_label.show()
1119
1120 def Progress(self, count):
1121 if self.in_progress:
1122 if count:
1123 percent = ((count - self.start) * 100) / self.Target()
1124 if percent >= 100:
1125 self.Idle()
1126 else:
1127 self.progress.setValue(percent)
1128 if not count:
1129 # Count value of zero means no more records
1130 self.Done()
1131
1132 def FetchMoreRecords(self):
1133 if self.done:
1134 return
1135 self.progress.setValue(0)
1136 self.Busy()
1137 self.in_progress = True
1138 self.start = self.model.FetchMoreRecords(self.Target())
1139
1140# Brance data model level two item
1141
1142class BranchLevelTwoItem():
1143
1144 def __init__(self, row, text, parent_item):
1145 self.row = row
1146 self.parent_item = parent_item
1147 self.data = [""] * 8
1148 self.data[7] = text
1149 self.level = 2
1150
1151 def getParentItem(self):
1152 return self.parent_item
1153
1154 def getRow(self):
1155 return self.row
1156
1157 def childCount(self):
1158 return 0
1159
1160 def hasChildren(self):
1161 return False
1162
1163 def getData(self, column):
1164 return self.data[column]
1165
1166# Brance data model level one item
1167
1168class BranchLevelOneItem():
1169
1170 def __init__(self, glb, row, data, parent_item):
1171 self.glb = glb
1172 self.row = row
1173 self.parent_item = parent_item
1174 self.child_count = 0
1175 self.child_items = []
1176 self.data = data[1:]
1177 self.dbid = data[0]
1178 self.level = 1
1179 self.query_done = False
1180
1181 def getChildItem(self, row):
1182 return self.child_items[row]
1183
1184 def getParentItem(self):
1185 return self.parent_item
1186
1187 def getRow(self):
1188 return self.row
1189
1190 def Select(self):
1191 self.query_done = True
1192
1193 if not self.glb.have_disassembler:
1194 return
1195
1196 query = QSqlQuery(self.glb.db)
1197
1198 QueryExec(query, "SELECT cpu, to_dso_id, to_symbol_id, to_sym_offset, short_name, long_name, build_id, sym_start, to_ip"
1199 " FROM samples"
1200 " INNER JOIN dsos ON samples.to_dso_id = dsos.id"
1201 " INNER JOIN symbols ON samples.to_symbol_id = symbols.id"
1202 " WHERE samples.id = " + str(self.dbid))
1203 if not query.next():
1204 return
1205 cpu = query.value(0)
1206 dso = query.value(1)
1207 sym = query.value(2)
1208 if dso == 0 or sym == 0:
1209 return
1210 off = query.value(3)
1211 short_name = query.value(4)
1212 long_name = query.value(5)
1213 build_id = query.value(6)
1214 sym_start = query.value(7)
1215 ip = query.value(8)
1216
1217 QueryExec(query, "SELECT samples.dso_id, symbol_id, sym_offset, sym_start"
1218 " FROM samples"
1219 " INNER JOIN symbols ON samples.symbol_id = symbols.id"
1220 " WHERE samples.id > " + str(self.dbid) + " AND cpu = " + str(cpu) +
1221 " ORDER BY samples.id"
1222 " LIMIT 1")
1223 if not query.next():
1224 return
1225 if query.value(0) != dso:
1226 # Cannot disassemble from one dso to another
1227 return
1228 bsym = query.value(1)
1229 boff = query.value(2)
1230 bsym_start = query.value(3)
1231 if bsym == 0:
1232 return
1233 tot = bsym_start + boff + 1 - sym_start - off
1234 if tot <= 0 or tot > 16384:
1235 return
1236
1237 inst = self.glb.disassembler.Instruction()
1238 f = self.glb.FileFromNamesAndBuildId(short_name, long_name, build_id)
1239 if not f:
1240 return
1241 mode = 0 if Is64Bit(f) else 1
1242 self.glb.disassembler.SetMode(inst, mode)
1243
1244 buf_sz = tot + 16
1245 buf = create_string_buffer(tot + 16)
1246 f.seek(sym_start + off)
1247 buf.value = f.read(buf_sz)
1248 buf_ptr = addressof(buf)
1249 i = 0
1250 while tot > 0:
1251 cnt, text = self.glb.disassembler.DisassembleOne(inst, buf_ptr, buf_sz, ip)
1252 if cnt:
1253 byte_str = tohex(ip).rjust(16)
1254 for k in xrange(cnt):
1255 byte_str += " %02x" % ord(buf[i])
1256 i += 1
1257 while k < 15:
1258 byte_str += " "
1259 k += 1
1260 self.child_items.append(BranchLevelTwoItem(0, byte_str + " " + text, self))
1261 self.child_count += 1
1262 else:
1263 return
1264 buf_ptr += cnt
1265 tot -= cnt
1266 buf_sz -= cnt
1267 ip += cnt
1268
1269 def childCount(self):
1270 if not self.query_done:
1271 self.Select()
1272 if not self.child_count:
1273 return -1
1274 return self.child_count
1275
1276 def hasChildren(self):
1277 if not self.query_done:
1278 return True
1279 return self.child_count > 0
1280
1281 def getData(self, column):
1282 return self.data[column]
1283
1284# Brance data model root item
1285
1286class BranchRootItem():
1287
1288 def __init__(self):
1289 self.child_count = 0
1290 self.child_items = []
1291 self.level = 0
1292
1293 def getChildItem(self, row):
1294 return self.child_items[row]
1295
1296 def getParentItem(self):
1297 return None
1298
1299 def getRow(self):
1300 return 0
1301
1302 def childCount(self):
1303 return self.child_count
1304
1305 def hasChildren(self):
1306 return self.child_count > 0
1307
1308 def getData(self, column):
1309 return ""
1310
1311# Branch data preparation
1312
1313def BranchDataPrep(query):
1314 data = []
1315 for i in xrange(0, 8):
1316 data.append(query.value(i))
1317 data.append(tohex(query.value(8)).rjust(16) + " " + query.value(9) + offstr(query.value(10)) +
1318 " (" + dsoname(query.value(11)) + ")" + " -> " +
1319 tohex(query.value(12)) + " " + query.value(13) + offstr(query.value(14)) +
1320 " (" + dsoname(query.value(15)) + ")")
1321 return data
1322
1323# Branch data model
1324
1325class BranchModel(TreeModel):
1326
1327 progress = Signal(object)
1328
1329 def __init__(self, glb, event_id, where_clause, parent=None):
1330 super(BranchModel, self).__init__(BranchRootItem(), parent)
1331 self.glb = glb
1332 self.event_id = event_id
1333 self.more = True
1334 self.populated = 0
1335 sql = ("SELECT samples.id, time, cpu, comm, pid, tid, branch_types.name,"
1336 " CASE WHEN in_tx = '0' THEN 'No' ELSE 'Yes' END,"
1337 " ip, symbols.name, sym_offset, dsos.short_name,"
1338 " to_ip, to_symbols.name, to_sym_offset, to_dsos.short_name"
1339 " FROM samples"
1340 " INNER JOIN comms ON comm_id = comms.id"
1341 " INNER JOIN threads ON thread_id = threads.id"
1342 " INNER JOIN branch_types ON branch_type = branch_types.id"
1343 " INNER JOIN symbols ON symbol_id = symbols.id"
1344 " INNER JOIN symbols to_symbols ON to_symbol_id = to_symbols.id"
1345 " INNER JOIN dsos ON samples.dso_id = dsos.id"
1346 " INNER JOIN dsos AS to_dsos ON samples.to_dso_id = to_dsos.id"
1347 " WHERE samples.id > $$last_id$$" + where_clause +
1348 " AND evsel_id = " + str(self.event_id) +
1349 " ORDER BY samples.id"
1350 " LIMIT " + str(glb_chunk_sz))
1351 self.fetcher = SQLFetcher(glb, sql, BranchDataPrep, self.AddSample)
1352 self.fetcher.done.connect(self.Update)
1353 self.fetcher.Fetch(glb_chunk_sz)
1354
1355 def columnCount(self, parent=None):
1356 return 8
1357
1358 def columnHeader(self, column):
1359 return ("Time", "CPU", "Command", "PID", "TID", "Branch Type", "In Tx", "Branch")[column]
1360
1361 def columnFont(self, column):
1362 if column != 7:
1363 return None
1364 return QFont("Monospace")
1365
1366 def DisplayData(self, item, index):
1367 if item.level == 1:
1368 self.FetchIfNeeded(item.row)
1369 return item.getData(index.column())
1370
1371 def AddSample(self, data):
1372 child = BranchLevelOneItem(self.glb, self.populated, data, self.root)
1373 self.root.child_items.append(child)
1374 self.populated += 1
1375
1376 def Update(self, fetched):
1377 if not fetched:
1378 self.more = False
1379 self.progress.emit(0)
1380 child_count = self.root.child_count
1381 count = self.populated - child_count
1382 if count > 0:
1383 parent = QModelIndex()
1384 self.beginInsertRows(parent, child_count, child_count + count - 1)
1385 self.insertRows(child_count, count, parent)
1386 self.root.child_count += count
1387 self.endInsertRows()
1388 self.progress.emit(self.root.child_count)
1389
1390 def FetchMoreRecords(self, count):
1391 current = self.root.child_count
1392 if self.more:
1393 self.fetcher.Fetch(count)
1394 else:
1395 self.progress.emit(0)
1396 return current
1397
1398 def HasMoreRecords(self):
1399 return self.more
1400
1401# Branch window
1402
1403class BranchWindow(QMdiSubWindow):
1404
1405 def __init__(self, glb, event_id, name, where_clause, parent=None):
1406 super(BranchWindow, self).__init__(parent)
1407
1408 model_name = "Branch Events " + str(event_id)
1409 if len(where_clause):
1410 model_name = where_clause + " " + model_name
1411
1412 self.model = LookupCreateModel(model_name, lambda: BranchModel(glb, event_id, where_clause))
1413
1414 self.view = QTreeView()
1415 self.view.setUniformRowHeights(True)
1416 self.view.setModel(self.model)
1417
1418 self.ResizeColumnsToContents()
1419
1420 self.find_bar = FindBar(self, self, True)
1421
1422 self.finder = ChildDataItemFinder(self.model.root)
1423
1424 self.fetch_bar = FetchMoreRecordsBar(self.model, self)
1425
1426 self.vbox = VBox(self.view, self.find_bar.Widget(), self.fetch_bar.Widget())
1427
1428 self.setWidget(self.vbox.Widget())
1429
1430 AddSubWindow(glb.mainwindow.mdi_area, self, name + " Branch Events")
1431
1432 def ResizeColumnToContents(self, column, n):
1433 # Using the view's resizeColumnToContents() here is extrememly slow
1434 # so implement a crude alternative
1435 mm = "MM" if column else "MMMM"
1436 font = self.view.font()
1437 metrics = QFontMetrics(font)
1438 max = 0
1439 for row in xrange(n):
1440 val = self.model.root.child_items[row].data[column]
1441 len = metrics.width(str(val) + mm)
1442 max = len if len > max else max
1443 val = self.model.columnHeader(column)
1444 len = metrics.width(str(val) + mm)
1445 max = len if len > max else max
1446 self.view.setColumnWidth(column, max)
1447
1448 def ResizeColumnsToContents(self):
1449 n = min(self.model.root.child_count, 100)
1450 if n < 1:
1451 # No data yet, so connect a signal to notify when there is
1452 self.model.rowsInserted.connect(self.UpdateColumnWidths)
1453 return
1454 columns = self.model.columnCount()
1455 for i in xrange(columns):
1456 self.ResizeColumnToContents(i, n)
1457
1458 def UpdateColumnWidths(self, *x):
1459 # This only needs to be done once, so disconnect the signal now
1460 self.model.rowsInserted.disconnect(self.UpdateColumnWidths)
1461 self.ResizeColumnsToContents()
1462
1463 def Find(self, value, direction, pattern, context):
1464 self.view.setFocus()
1465 self.find_bar.Busy()
1466 self.finder.Find(value, direction, pattern, context, self.FindDone)
1467
1468 def FindDone(self, row):
1469 self.find_bar.Idle()
1470 if row >= 0:
1471 self.view.setCurrentIndex(self.model.index(row, 0, QModelIndex()))
1472 else:
1473 self.find_bar.NotFound()
1474
1475# Dialog data item converted and validated using a SQL table
1476
1477class SQLTableDialogDataItem():
1478
1479 def __init__(self, glb, label, placeholder_text, table_name, match_column, column_name1, column_name2, parent):
1480 self.glb = glb
1481 self.label = label
1482 self.placeholder_text = placeholder_text
1483 self.table_name = table_name
1484 self.match_column = match_column
1485 self.column_name1 = column_name1
1486 self.column_name2 = column_name2
1487 self.parent = parent
1488
1489 self.value = ""
1490
1491 self.widget = QLineEdit()
1492 self.widget.editingFinished.connect(self.Validate)
1493 self.widget.textChanged.connect(self.Invalidate)
1494 self.red = False
1495 self.error = ""
1496 self.validated = True
1497
1498 self.last_id = 0
1499 self.first_time = 0
1500 self.last_time = 2 ** 64
1501 if self.table_name == "<timeranges>":
1502 query = QSqlQuery(self.glb.db)
1503 QueryExec(query, "SELECT id, time FROM samples ORDER BY id DESC LIMIT 1")
1504 if query.next():
1505 self.last_id = int(query.value(0))
1506 self.last_time = int(query.value(1))
1507 QueryExec(query, "SELECT time FROM samples WHERE time != 0 ORDER BY id LIMIT 1")
1508 if query.next():
1509 self.first_time = int(query.value(0))
1510 if placeholder_text:
1511 placeholder_text += ", between " + str(self.first_time) + " and " + str(self.last_time)
1512
1513 if placeholder_text:
1514 self.widget.setPlaceholderText(placeholder_text)
1515
1516 def ValueToIds(self, value):
1517 ids = []
1518 query = QSqlQuery(self.glb.db)
1519 stmt = "SELECT id FROM " + self.table_name + " WHERE " + self.match_column + " = '" + value + "'"
1520 ret = query.exec_(stmt)
1521 if ret:
1522 while query.next():
1523 ids.append(str(query.value(0)))
1524 return ids
1525
1526 def IdBetween(self, query, lower_id, higher_id, order):
1527 QueryExec(query, "SELECT id FROM samples WHERE id > " + str(lower_id) + " AND id < " + str(higher_id) + " ORDER BY id " + order + " LIMIT 1")
1528 if query.next():
1529 return True, int(query.value(0))
1530 else:
1531 return False, 0
1532
1533 def BinarySearchTime(self, lower_id, higher_id, target_time, get_floor):
1534 query = QSqlQuery(self.glb.db)
1535 while True:
1536 next_id = int((lower_id + higher_id) / 2)
1537 QueryExec(query, "SELECT time FROM samples WHERE id = " + str(next_id))
1538 if not query.next():
1539 ok, dbid = self.IdBetween(query, lower_id, next_id, "DESC")
1540 if not ok:
1541 ok, dbid = self.IdBetween(query, next_id, higher_id, "")
1542 if not ok:
1543 return str(higher_id)
1544 next_id = dbid
1545 QueryExec(query, "SELECT time FROM samples WHERE id = " + str(next_id))
1546 next_time = int(query.value(0))
1547 if get_floor:
1548 if target_time > next_time:
1549 lower_id = next_id
1550 else:
1551 higher_id = next_id
1552 if higher_id <= lower_id + 1:
1553 return str(higher_id)
1554 else:
1555 if target_time >= next_time:
1556 lower_id = next_id
1557 else:
1558 higher_id = next_id
1559 if higher_id <= lower_id + 1:
1560 return str(lower_id)
1561
1562 def ConvertRelativeTime(self, val):
1563 print "val ", val
1564 mult = 1
1565 suffix = val[-2:]
1566 if suffix == "ms":
1567 mult = 1000000
1568 elif suffix == "us":
1569 mult = 1000
1570 elif suffix == "ns":
1571 mult = 1
1572 else:
1573 return val
1574 val = val[:-2].strip()
1575 if not self.IsNumber(val):
1576 return val
1577 val = int(val) * mult
1578 if val >= 0:
1579 val += self.first_time
1580 else:
1581 val += self.last_time
1582 return str(val)
1583
1584 def ConvertTimeRange(self, vrange):
1585 print "vrange ", vrange
1586 if vrange[0] == "":
1587 vrange[0] = str(self.first_time)
1588 if vrange[1] == "":
1589 vrange[1] = str(self.last_time)
1590 vrange[0] = self.ConvertRelativeTime(vrange[0])
1591 vrange[1] = self.ConvertRelativeTime(vrange[1])
1592 print "vrange2 ", vrange
1593 if not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1594 return False
1595 print "ok1"
1596 beg_range = max(int(vrange[0]), self.first_time)
1597 end_range = min(int(vrange[1]), self.last_time)
1598 if beg_range > self.last_time or end_range < self.first_time:
1599 return False
1600 print "ok2"
1601 vrange[0] = self.BinarySearchTime(0, self.last_id, beg_range, True)
1602 vrange[1] = self.BinarySearchTime(1, self.last_id + 1, end_range, False)
1603 print "vrange3 ", vrange
1604 return True
1605
1606 def AddTimeRange(self, value, ranges):
1607 print "value ", value
1608 n = value.count("-")
1609 if n == 1:
1610 pass
1611 elif n == 2:
1612 if value.split("-")[1].strip() == "":
1613 n = 1
1614 elif n == 3:
1615 n = 2
1616 else:
1617 return False
1618 pos = findnth(value, "-", n)
1619 vrange = [value[:pos].strip() ,value[pos+1:].strip()]
1620 if self.ConvertTimeRange(vrange):
1621 ranges.append(vrange)
1622 return True
1623 return False
1624
1625 def InvalidValue(self, value):
1626 self.value = ""
1627 palette = QPalette()
1628 palette.setColor(QPalette.Text,Qt.red)
1629 self.widget.setPalette(palette)
1630 self.red = True
1631 self.error = self.label + " invalid value '" + value + "'"
1632 self.parent.ShowMessage(self.error)
1633
1634 def IsNumber(self, value):
1635 try:
1636 x = int(value)
1637 except:
1638 x = 0
1639 return str(x) == value
1640
1641 def Invalidate(self):
1642 self.validated = False
1643
1644 def Validate(self):
1645 input_string = self.widget.text()
1646 self.validated = True
1647 if self.red:
1648 palette = QPalette()
1649 self.widget.setPalette(palette)
1650 self.red = False
1651 if not len(input_string.strip()):
1652 self.error = ""
1653 self.value = ""
1654 return
1655 if self.table_name == "<timeranges>":
1656 ranges = []
1657 for value in [x.strip() for x in input_string.split(",")]:
1658 if not self.AddTimeRange(value, ranges):
1659 return self.InvalidValue(value)
1660 ranges = [("(" + self.column_name1 + " >= " + r[0] + " AND " + self.column_name1 + " <= " + r[1] + ")") for r in ranges]
1661 self.value = " OR ".join(ranges)
1662 elif self.table_name == "<ranges>":
1663 singles = []
1664 ranges = []
1665 for value in [x.strip() for x in input_string.split(",")]:
1666 if "-" in value:
1667 vrange = value.split("-")
1668 if len(vrange) != 2 or not self.IsNumber(vrange[0]) or not self.IsNumber(vrange[1]):
1669 return self.InvalidValue(value)
1670 ranges.append(vrange)
1671 else:
1672 if not self.IsNumber(value):
1673 return self.InvalidValue(value)
1674 singles.append(value)
1675 ranges = [("(" + self.column_name1 + " >= " + r[0] + " AND " + self.column_name1 + " <= " + r[1] + ")") for r in ranges]
1676 if len(singles):
1677 ranges.append(self.column_name1 + " IN (" + ",".join(singles) + ")")
1678 self.value = " OR ".join(ranges)
1679 elif self.table_name:
1680 all_ids = []
1681 for value in [x.strip() for x in input_string.split(",")]:
1682 ids = self.ValueToIds(value)
1683 if len(ids):
1684 all_ids.extend(ids)
1685 else:
1686 return self.InvalidValue(value)
1687 self.value = self.column_name1 + " IN (" + ",".join(all_ids) + ")"
1688 if self.column_name2:
1689 self.value = "( " + self.value + " OR " + self.column_name2 + " IN (" + ",".join(all_ids) + ") )"
1690 else:
1691 self.value = input_string.strip()
1692 self.error = ""
1693 self.parent.ClearMessage()
1694
1695 def IsValid(self):
1696 if not self.validated:
1697 self.Validate()
1698 if len(self.error):
1699 self.parent.ShowMessage(self.error)
1700 return False
1701 return True
1702
1703# Selected branch report creation dialog
1704
1705class SelectedBranchDialog(QDialog):
1706
1707 def __init__(self, glb, parent=None):
1708 super(SelectedBranchDialog, self).__init__(parent)
1709
1710 self.glb = glb
1711
1712 self.name = ""
1713 self.where_clause = ""
1714
1715 self.setWindowTitle("Selected Branches")
1716 self.setMinimumWidth(600)
1717
1718 items = (
1719 ("Report name:", "Enter a name to appear in the window title bar", "", "", "", ""),
1720 ("Time ranges:", "Enter time ranges", "<timeranges>", "", "samples.id", ""),
1721 ("CPUs:", "Enter CPUs or ranges e.g. 0,5-6", "<ranges>", "", "cpu", ""),
1722 ("Commands:", "Only branches with these commands will be included", "comms", "comm", "comm_id", ""),
1723 ("PIDs:", "Only branches with these process IDs will be included", "threads", "pid", "thread_id", ""),
1724 ("TIDs:", "Only branches with these thread IDs will be included", "threads", "tid", "thread_id", ""),
1725 ("DSOs:", "Only branches with these DSOs will be included", "dsos", "short_name", "samples.dso_id", "to_dso_id"),
1726 ("Symbols:", "Only branches with these symbols will be included", "symbols", "name", "symbol_id", "to_symbol_id"),
1727 ("Raw SQL clause: ", "Enter a raw SQL WHERE clause", "", "", "", ""),
1728 )
1729 self.data_items = [SQLTableDialogDataItem(glb, *x, parent=self) for x in items]
1730
1731 self.grid = QGridLayout()
1732
1733 for row in xrange(len(self.data_items)):
1734 self.grid.addWidget(QLabel(self.data_items[row].label), row, 0)
1735 self.grid.addWidget(self.data_items[row].widget, row, 1)
1736
1737 self.status = QLabel()
1738
1739 self.ok_button = QPushButton("Ok", self)
1740 self.ok_button.setDefault(True)
1741 self.ok_button.released.connect(self.Ok)
1742 self.ok_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1743
1744 self.cancel_button = QPushButton("Cancel", self)
1745 self.cancel_button.released.connect(self.reject)
1746 self.cancel_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1747
1748 self.hbox = QHBoxLayout()
1749 #self.hbox.addStretch()
1750 self.hbox.addWidget(self.status)
1751 self.hbox.addWidget(self.ok_button)
1752 self.hbox.addWidget(self.cancel_button)
1753
1754 self.vbox = QVBoxLayout()
1755 self.vbox.addLayout(self.grid)
1756 self.vbox.addLayout(self.hbox)
1757
1758 self.setLayout(self.vbox);
1759
1760 def Ok(self):
1761 self.name = self.data_items[0].value
1762 if not self.name:
1763 self.ShowMessage("Report name is required")
1764 return
1765 for d in self.data_items:
1766 if not d.IsValid():
1767 return
1768 for d in self.data_items[1:]:
1769 if len(d.value):
1770 if len(self.where_clause):
1771 self.where_clause += " AND "
1772 self.where_clause += d.value
1773 if len(self.where_clause):
1774 self.where_clause = " AND ( " + self.where_clause + " ) "
1775 else:
1776 self.ShowMessage("No selection")
1777 return
1778 self.accept()
1779
1780 def ShowMessage(self, msg):
1781 self.status.setText("<font color=#FF0000>" + msg)
1782
1783 def ClearMessage(self):
1784 self.status.setText("")
1785
1786# Event list
1787
1788def GetEventList(db):
1789 events = []
1790 query = QSqlQuery(db)
1791 QueryExec(query, "SELECT name FROM selected_events WHERE id > 0 ORDER BY id")
1792 while query.next():
1793 events.append(query.value(0))
1794 return events
1795
1796# SQL data preparation
1797
1798def SQLTableDataPrep(query, count):
1799 data = []
1800 for i in xrange(count):
1801 data.append(query.value(i))
1802 return data
1803
1804# SQL table data model item
1805
1806class SQLTableItem():
1807
1808 def __init__(self, row, data):
1809 self.row = row
1810 self.data = data
1811
1812 def getData(self, column):
1813 return self.data[column]
1814
1815# SQL table data model
1816
1817class SQLTableModel(TableModel):
1818
1819 progress = Signal(object)
1820
1821 def __init__(self, glb, sql, column_count, parent=None):
1822 super(SQLTableModel, self).__init__(parent)
1823 self.glb = glb
1824 self.more = True
1825 self.populated = 0
1826 self.fetcher = SQLFetcher(glb, sql, lambda x, y=column_count: SQLTableDataPrep(x, y), self.AddSample)
1827 self.fetcher.done.connect(self.Update)
1828 self.fetcher.Fetch(glb_chunk_sz)
1829
1830 def DisplayData(self, item, index):
1831 self.FetchIfNeeded(item.row)
1832 return item.getData(index.column())
1833
1834 def AddSample(self, data):
1835 child = SQLTableItem(self.populated, data)
1836 self.child_items.append(child)
1837 self.populated += 1
1838
1839 def Update(self, fetched):
1840 if not fetched:
1841 self.more = False
1842 self.progress.emit(0)
1843 child_count = self.child_count
1844 count = self.populated - child_count
1845 if count > 0:
1846 parent = QModelIndex()
1847 self.beginInsertRows(parent, child_count, child_count + count - 1)
1848 self.insertRows(child_count, count, parent)
1849 self.child_count += count
1850 self.endInsertRows()
1851 self.progress.emit(self.child_count)
1852
1853 def FetchMoreRecords(self, count):
1854 current = self.child_count
1855 if self.more:
1856 self.fetcher.Fetch(count)
1857 else:
1858 self.progress.emit(0)
1859 return current
1860
1861 def HasMoreRecords(self):
1862 return self.more
1863
1864# SQL automatic table data model
1865
1866class SQLAutoTableModel(SQLTableModel):
1867
1868 def __init__(self, glb, table_name, parent=None):
1869 sql = "SELECT * FROM " + table_name + " WHERE id > $$last_id$$ ORDER BY id LIMIT " + str(glb_chunk_sz)
1870 if table_name == "comm_threads_view":
1871 # For now, comm_threads_view has no id column
1872 sql = "SELECT * FROM " + table_name + " WHERE comm_id > $$last_id$$ ORDER BY comm_id LIMIT " + str(glb_chunk_sz)
1873 self.column_headers = []
1874 query = QSqlQuery(glb.db)
1875 if glb.dbref.is_sqlite3:
1876 QueryExec(query, "PRAGMA table_info(" + table_name + ")")
1877 while query.next():
1878 self.column_headers.append(query.value(1))
1879 if table_name == "sqlite_master":
1880 sql = "SELECT * FROM " + table_name
1881 else:
1882 if table_name[:19] == "information_schema.":
1883 sql = "SELECT * FROM " + table_name
1884 select_table_name = table_name[19:]
1885 schema = "information_schema"
1886 else:
1887 select_table_name = table_name
1888 schema = "public"
1889 QueryExec(query, "SELECT column_name FROM information_schema.columns WHERE table_schema = '" + schema + "' and table_name = '" + select_table_name + "'")
1890 while query.next():
1891 self.column_headers.append(query.value(0))
1892 super(SQLAutoTableModel, self).__init__(glb, sql, len(self.column_headers), parent)
1893
1894 def columnCount(self, parent=None):
1895 return len(self.column_headers)
1896
1897 def columnHeader(self, column):
1898 return self.column_headers[column]
1899
1900# Base class for custom ResizeColumnsToContents
1901
1902class ResizeColumnsToContentsBase(QObject):
1903
1904 def __init__(self, parent=None):
1905 super(ResizeColumnsToContentsBase, self).__init__(parent)
1906
1907 def ResizeColumnToContents(self, column, n):
1908 # Using the view's resizeColumnToContents() here is extrememly slow
1909 # so implement a crude alternative
1910 font = self.view.font()
1911 metrics = QFontMetrics(font)
1912 max = 0
1913 for row in xrange(n):
1914 val = self.data_model.child_items[row].data[column]
1915 len = metrics.width(str(val) + "MM")
1916 max = len if len > max else max
1917 val = self.data_model.columnHeader(column)
1918 len = metrics.width(str(val) + "MM")
1919 max = len if len > max else max
1920 self.view.setColumnWidth(column, max)
1921
1922 def ResizeColumnsToContents(self):
1923 n = min(self.data_model.child_count, 100)
1924 if n < 1:
1925 # No data yet, so connect a signal to notify when there is
1926 self.data_model.rowsInserted.connect(self.UpdateColumnWidths)
1927 return
1928 columns = self.data_model.columnCount()
1929 for i in xrange(columns):
1930 self.ResizeColumnToContents(i, n)
1931
1932 def UpdateColumnWidths(self, *x):
1933 # This only needs to be done once, so disconnect the signal now
1934 self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths)
1935 self.ResizeColumnsToContents()
1936
1937# Table window
1938
1939class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase):
1940
1941 def __init__(self, glb, table_name, parent=None):
1942 super(TableWindow, self).__init__(parent)
1943
1944 self.data_model = LookupCreateModel(table_name + " Table", lambda: SQLAutoTableModel(glb, table_name))
1945
1946 self.model = QSortFilterProxyModel()
1947 self.model.setSourceModel(self.data_model)
1948
1949 self.view = QTableView()
1950 self.view.setModel(self.model)
1951 self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
1952 self.view.verticalHeader().setVisible(False)
1953 self.view.sortByColumn(-1, Qt.AscendingOrder)
1954 self.view.setSortingEnabled(True)
1955
1956 self.ResizeColumnsToContents()
1957
1958 self.find_bar = FindBar(self, self, True)
1959
1960 self.finder = ChildDataItemFinder(self.data_model)
1961
1962 self.fetch_bar = FetchMoreRecordsBar(self.data_model, self)
1963
1964 self.vbox = VBox(self.view, self.find_bar.Widget(), self.fetch_bar.Widget())
1965
1966 self.setWidget(self.vbox.Widget())
1967
1968 AddSubWindow(glb.mainwindow.mdi_area, self, table_name + " Table")
1969
1970 def Find(self, value, direction, pattern, context):
1971 self.view.setFocus()
1972 self.find_bar.Busy()
1973 self.finder.Find(value, direction, pattern, context, self.FindDone)
1974
1975 def FindDone(self, row):
1976 self.find_bar.Idle()
1977 if row >= 0:
1978 self.view.setCurrentIndex(self.model.mapFromSource(self.data_model.index(row, 0, QModelIndex())))
1979 else:
1980 self.find_bar.NotFound()
1981
1982# Table list
1983
1984def GetTableList(glb):
1985 tables = []
1986 query = QSqlQuery(glb.db)
1987 if glb.dbref.is_sqlite3:
1988 QueryExec(query, "SELECT name FROM sqlite_master WHERE type IN ( 'table' , 'view' ) ORDER BY name")
1989 else:
1990 QueryExec(query, "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_type IN ( 'BASE TABLE' , 'VIEW' ) ORDER BY table_name")
1991 while query.next():
1992 tables.append(query.value(0))
1993 if glb.dbref.is_sqlite3:
1994 tables.append("sqlite_master")
1995 else:
1996 tables.append("information_schema.tables")
1997 tables.append("information_schema.views")
1998 tables.append("information_schema.columns")
1999 return tables
2000
2001# Action Definition
2002
2003def CreateAction(label, tip, callback, parent=None, shortcut=None):
2004 action = QAction(label, parent)
2005 if shortcut != None:
2006 action.setShortcuts(shortcut)
2007 action.setStatusTip(tip)
2008 action.triggered.connect(callback)
2009 return action
2010
2011# Typical application actions
2012
2013def CreateExitAction(app, parent=None):
2014 return CreateAction("&Quit", "Exit the application", app.closeAllWindows, parent, QKeySequence.Quit)
2015
2016# Typical MDI actions
2017
2018def CreateCloseActiveWindowAction(mdi_area):
2019 return CreateAction("Cl&ose", "Close the active window", mdi_area.closeActiveSubWindow, mdi_area)
2020
2021def CreateCloseAllWindowsAction(mdi_area):
2022 return CreateAction("Close &All", "Close all the windows", mdi_area.closeAllSubWindows, mdi_area)
2023
2024def CreateTileWindowsAction(mdi_area):
2025 return CreateAction("&Tile", "Tile the windows", mdi_area.tileSubWindows, mdi_area)
2026
2027def CreateCascadeWindowsAction(mdi_area):
2028 return CreateAction("&Cascade", "Cascade the windows", mdi_area.cascadeSubWindows, mdi_area)
2029
2030def CreateNextWindowAction(mdi_area):
2031 return CreateAction("Ne&xt", "Move the focus to the next window", mdi_area.activateNextSubWindow, mdi_area, QKeySequence.NextChild)
2032
2033def CreatePreviousWindowAction(mdi_area):
2034 return CreateAction("Pre&vious", "Move the focus to the previous window", mdi_area.activatePreviousSubWindow, mdi_area, QKeySequence.PreviousChild)
2035
2036# Typical MDI window menu
2037
2038class WindowMenu():
2039
2040 def __init__(self, mdi_area, menu):
2041 self.mdi_area = mdi_area
2042 self.window_menu = menu.addMenu("&Windows")
2043 self.close_active_window = CreateCloseActiveWindowAction(mdi_area)
2044 self.close_all_windows = CreateCloseAllWindowsAction(mdi_area)
2045 self.tile_windows = CreateTileWindowsAction(mdi_area)
2046 self.cascade_windows = CreateCascadeWindowsAction(mdi_area)
2047 self.next_window = CreateNextWindowAction(mdi_area)
2048 self.previous_window = CreatePreviousWindowAction(mdi_area)
2049 self.window_menu.aboutToShow.connect(self.Update)
2050
2051 def Update(self):
2052 self.window_menu.clear()
2053 sub_window_count = len(self.mdi_area.subWindowList())
2054 have_sub_windows = sub_window_count != 0
2055 self.close_active_window.setEnabled(have_sub_windows)
2056 self.close_all_windows.setEnabled(have_sub_windows)
2057 self.tile_windows.setEnabled(have_sub_windows)
2058 self.cascade_windows.setEnabled(have_sub_windows)
2059 self.next_window.setEnabled(have_sub_windows)
2060 self.previous_window.setEnabled(have_sub_windows)
2061 self.window_menu.addAction(self.close_active_window)
2062 self.window_menu.addAction(self.close_all_windows)
2063 self.window_menu.addSeparator()
2064 self.window_menu.addAction(self.tile_windows)
2065 self.window_menu.addAction(self.cascade_windows)
2066 self.window_menu.addSeparator()
2067 self.window_menu.addAction(self.next_window)
2068 self.window_menu.addAction(self.previous_window)
2069 if sub_window_count == 0:
2070 return
2071 self.window_menu.addSeparator()
2072 nr = 1
2073 for sub_window in self.mdi_area.subWindowList():
2074 label = str(nr) + " " + sub_window.name
2075 if nr < 10:
2076 label = "&" + label
2077 action = self.window_menu.addAction(label)
2078 action.setCheckable(True)
2079 action.setChecked(sub_window == self.mdi_area.activeSubWindow())
2080 action.triggered.connect(lambda x=nr: self.setActiveSubWindow(x))
2081 self.window_menu.addAction(action)
2082 nr += 1
2083
2084 def setActiveSubWindow(self, nr):
2085 self.mdi_area.setActiveSubWindow(self.mdi_area.subWindowList()[nr - 1])
2086
2087# Help text
2088
2089glb_help_text = """
2090<h1>Contents</h1>
2091<style>
2092p.c1 {
2093 text-indent: 40px;
2094}
2095p.c2 {
2096 text-indent: 80px;
2097}
2098}
2099</style>
2100<p class=c1><a href=#reports>1. Reports</a></p>
2101<p class=c2><a href=#callgraph>1.1 Context-Sensitive Call Graph</a></p>
2102<p class=c2><a href=#allbranches>1.2 All branches</a></p>
2103<p class=c2><a href=#selectedbranches>1.3 Selected branches</a></p>
2104<p class=c1><a href=#tables>2. Tables</a></p>
2105<h1 id=reports>1. Reports</h1>
2106<h2 id=callgraph>1.1 Context-Sensitive Call Graph</h2>
2107The result is a GUI window with a tree representing a context-sensitive
2108call-graph. Expanding a couple of levels of the tree and adjusting column
2109widths to suit will display something like:
2110<pre>
2111 Call Graph: pt_example
2112Call Path Object Count Time(ns) Time(%) Branch Count Branch Count(%)
2113v- ls
2114 v- 2638:2638
2115 v- _start ld-2.19.so 1 10074071 100.0 211135 100.0
2116 |- unknown unknown 1 13198 0.1 1 0.0
2117 >- _dl_start ld-2.19.so 1 1400980 13.9 19637 9.3
2118 >- _d_linit_internal ld-2.19.so 1 448152 4.4 11094 5.3
2119 v-__libc_start_main@plt ls 1 8211741 81.5 180397 85.4
2120 >- _dl_fixup ld-2.19.so 1 7607 0.1 108 0.1
2121 >- __cxa_atexit libc-2.19.so 1 11737 0.1 10 0.0
2122 >- __libc_csu_init ls 1 10354 0.1 10 0.0
2123 |- _setjmp libc-2.19.so 1 0 0.0 4 0.0
2124 v- main ls 1 8182043 99.6 180254 99.9
2125</pre>
2126<h3>Points to note:</h3>
2127<ul>
2128<li>The top level is a command name (comm)</li>
2129<li>The next level is a thread (pid:tid)</li>
2130<li>Subsequent levels are functions</li>
2131<li>'Count' is the number of calls</li>
2132<li>'Time' is the elapsed time until the function returns</li>
2133<li>Percentages are relative to the level above</li>
2134<li>'Branch Count' is the total number of branches for that function and all functions that it calls
2135</ul>
2136<h3>Find</h3>
2137Ctrl-F displays a Find bar which finds function names by either an exact match or a pattern match.
2138The pattern matching symbols are ? for any character and * for zero or more characters.
2139<h2 id=allbranches>1.2 All branches</h2>
2140The All branches report displays all branches in chronological order.
2141Not all data is fetched immediately. More records can be fetched using the Fetch bar provided.
2142<h3>Disassembly</h3>
2143Open a branch to display disassembly. This only works if:
2144<ol>
2145<li>The disassembler is available. Currently, only Intel XED is supported - see <a href=#xed>Intel XED Setup</a></li>
2146<li>The object code is available. Currently, only the perf build ID cache is searched for object code.
2147The default directory ~/.debug can be overridden by setting environment variable PERF_BUILDID_DIR.
2148One exception is kcore where the DSO long name is used (refer dsos_view on the Tables menu),
2149or alternatively, set environment variable PERF_KCORE to the kcore file name.</li>
2150</ol>
2151<h4 id=xed>Intel XED Setup</h4>
2152To use Intel XED, libxed.so must be present. To build and install libxed.so:
2153<pre>
2154git clone https://github.com/intelxed/mbuild.git mbuild
2155git clone https://github.com/intelxed/xed
2156cd xed
2157./mfile.py --share
2158sudo ./mfile.py --prefix=/usr/local install
2159sudo ldconfig
2160</pre>
2161<h3>Find</h3>
2162Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match.
2163Refer to Python documentation for the regular expression syntax.
2164All columns are searched, but only currently fetched rows are searched.
2165<h2 id=selectedbranches>1.3 Selected branches</h2>
2166This is the same as the <a href=#allbranches>All branches</a> report but with the data reduced
2167by various selection criteria. A dialog box displays available criteria which are AND'ed together.
2168<h3>1.3.1 Time ranges</h3>
2169The time ranges hint text shows the total time range. Relative time ranges can also be entered in
2170ms, us or ns. Also, negative values are relative to the end of trace. Examples:
2171<pre>
2172 81073085947329-81073085958238 From 81073085947329 to 81073085958238
2173 100us-200us From 100us to 200us
2174 10ms- From 10ms to the end
2175 -100ns The first 100ns
2176 -10ms- The last 10ms
2177</pre>
2178N.B. Due to the granularity of timestamps, there could be no branches in any given time range.
2179<h1 id=tables>2. Tables</h1>
2180The Tables menu shows all tables and views in the database. Most tables have an associated view
2181which displays the information in a more friendly way. Not all data for large tables is fetched
2182immediately. More records can be fetched using the Fetch bar provided. Columns can be sorted,
2183but that can be slow for large tables.
2184<p>There are also tables of database meta-information.
2185For SQLite3 databases, the sqlite_master table is included.
2186For PostgreSQL databases, information_schema.tables/views/columns are included.
2187<h3>Find</h3>
2188Ctrl-F displays a Find bar which finds substrings by either an exact match or a regular expression match.
2189Refer to Python documentation for the regular expression syntax.
2190All columns are searched, but only currently fetched rows are searched.
2191<p>N.B. Results are found in id order, so if the table is re-ordered, find-next and find-previous
2192will go to the next/previous result in id order, instead of display order.
2193"""
2194
2195# Help window
2196
2197class HelpWindow(QMdiSubWindow):
2198
2199 def __init__(self, glb, parent=None):
2200 super(HelpWindow, self).__init__(parent)
2201
2202 self.text = QTextBrowser()
2203 self.text.setHtml(glb_help_text)
2204 self.text.setReadOnly(True)
2205 self.text.setOpenExternalLinks(True)
2206
2207 self.setWidget(self.text)
2208
2209 AddSubWindow(glb.mainwindow.mdi_area, self, "Exported SQL Viewer Help")
2210
2211# Main window that only displays the help text
2212
2213class HelpOnlyWindow(QMainWindow):
2214
2215 def __init__(self, parent=None):
2216 super(HelpOnlyWindow, self).__init__(parent)
2217
2218 self.setMinimumSize(200, 100)
2219 self.resize(800, 600)
2220 self.setWindowTitle("Exported SQL Viewer Help")
2221 self.setWindowIcon(self.style().standardIcon(QStyle.SP_MessageBoxInformation))
2222
2223 self.text = QTextBrowser()
2224 self.text.setHtml(glb_help_text)
2225 self.text.setReadOnly(True)
2226 self.text.setOpenExternalLinks(True)
2227
2228 self.setCentralWidget(self.text)
2229
2230# Font resize
2231
2232def ResizeFont(widget, diff):
2233 font = widget.font()
2234 sz = font.pointSize()
2235 font.setPointSize(sz + diff)
2236 widget.setFont(font)
2237
2238def ShrinkFont(widget):
2239 ResizeFont(widget, -1)
2240
2241def EnlargeFont(widget):
2242 ResizeFont(widget, 1)
2243
2244# Unique name for sub-windows
2245
2246def NumberedWindowName(name, nr):
2247 if nr > 1:
2248 name += " <" + str(nr) + ">"
2249 return name
2250
2251def UniqueSubWindowName(mdi_area, name):
2252 nr = 1
2253 while True:
2254 unique_name = NumberedWindowName(name, nr)
2255 ok = True
2256 for sub_window in mdi_area.subWindowList():
2257 if sub_window.name == unique_name:
2258 ok = False
2259 break
2260 if ok:
2261 return unique_name
2262 nr += 1
2263
2264# Add a sub-window
2265
2266def AddSubWindow(mdi_area, sub_window, name):
2267 unique_name = UniqueSubWindowName(mdi_area, name)
2268 sub_window.setMinimumSize(200, 100)
2269 sub_window.resize(800, 600)
2270 sub_window.setWindowTitle(unique_name)
2271 sub_window.setAttribute(Qt.WA_DeleteOnClose)
2272 sub_window.setWindowIcon(sub_window.style().standardIcon(QStyle.SP_FileIcon))
2273 sub_window.name = unique_name
2274 mdi_area.addSubWindow(sub_window)
2275 sub_window.show()
2276
2277# Main window
2278
2279class MainWindow(QMainWindow):
2280
2281 def __init__(self, glb, parent=None):
2282 super(MainWindow, self).__init__(parent)
2283
2284 self.glb = glb
2285
2286 self.setWindowTitle("Exported SQL Viewer: " + glb.dbname)
2287 self.setWindowIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))
2288 self.setMinimumSize(200, 100)
2289
2290 self.mdi_area = QMdiArea()
2291 self.mdi_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
2292 self.mdi_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
2293
2294 self.setCentralWidget(self.mdi_area)
2295
2296 menu = self.menuBar()
2297
2298 file_menu = menu.addMenu("&File")
2299 file_menu.addAction(CreateExitAction(glb.app, self))
2300
2301 edit_menu = menu.addMenu("&Edit")
2302 edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find))
2303 edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)]))
2304 edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")]))
2305 edit_menu.addAction(CreateAction("&Enlarge Font", "Make text bigger", self.EnlargeFont, self, [QKeySequence("Ctrl++")]))
2306
2307 reports_menu = menu.addMenu("&Reports")
2308 reports_menu.addAction(CreateAction("Context-Sensitive Call &Graph", "Create a new window containing a context-sensitive call graph", self.NewCallGraph, self))
2309
2310 self.EventMenu(GetEventList(glb.db), reports_menu)
2311
2312 self.TableMenu(GetTableList(glb), menu)
2313
2314 self.window_menu = WindowMenu(self.mdi_area, menu)
2315
2316 help_menu = menu.addMenu("&Help")
2317 help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents))
2318
2319 def Find(self):
2320 win = self.mdi_area.activeSubWindow()
2321 if win:
2322 try:
2323 win.find_bar.Activate()
2324 except:
2325 pass
2326
2327 def FetchMoreRecords(self):
2328 win = self.mdi_area.activeSubWindow()
2329 if win:
2330 try:
2331 win.fetch_bar.Activate()
2332 except:
2333 pass
2334
2335 def ShrinkFont(self):
2336 win = self.mdi_area.activeSubWindow()
2337 ShrinkFont(win.view)
2338
2339 def EnlargeFont(self):
2340 win = self.mdi_area.activeSubWindow()
2341 EnlargeFont(win.view)
2342
2343 def EventMenu(self, events, reports_menu):
2344 branches_events = 0
2345 for event in events:
2346 event = event.split(":")[0]
2347 if event == "branches":
2348 branches_events += 1
2349 dbid = 0
2350 for event in events:
2351 dbid += 1
2352 event = event.split(":")[0]
2353 if event == "branches":
2354 label = "All branches" if branches_events == 1 else "All branches " + "(id=" + dbid + ")"
2355 reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda x=dbid: self.NewBranchView(x), self))
2356 label = "Selected branches" if branches_events == 1 else "Selected branches " + "(id=" + dbid + ")"
2357 reports_menu.addAction(CreateAction(label, "Create a new window displaying branch events", lambda x=dbid: self.NewSelectedBranchView(x), self))
2358
2359 def TableMenu(self, tables, menu):
2360 table_menu = menu.addMenu("&Tables")
2361 for table in tables:
2362 table_menu.addAction(CreateAction(table, "Create a new window containing a table view", lambda t=table: self.NewTableView(t), self))
2363
2364 def NewCallGraph(self):
2365 CallGraphWindow(self.glb, self)
2366
2367 def NewBranchView(self, event_id):
2368 BranchWindow(self.glb, event_id, "", "", self)
2369
2370 def NewSelectedBranchView(self, event_id):
2371 dialog = SelectedBranchDialog(self.glb, self)
2372 ret = dialog.exec_()
2373 if ret:
2374 BranchWindow(self.glb, event_id, dialog.name, dialog.where_clause, self)
2375
2376 def NewTableView(self, table_name):
2377 TableWindow(self.glb, table_name, self)
2378
2379 def Help(self):
2380 HelpWindow(self.glb, self)
2381
2382# XED Disassembler
2383
2384class xed_state_t(Structure):
2385
2386 _fields_ = [
2387 ("mode", c_int),
2388 ("width", c_int)
2389 ]
2390
2391class XEDInstruction():
2392
2393 def __init__(self, libxed):
2394 # Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion
2395 xedd_t = c_byte * 512
2396 self.xedd = xedd_t()
2397 self.xedp = addressof(self.xedd)
2398 libxed.xed_decoded_inst_zero(self.xedp)
2399 self.state = xed_state_t()
2400 self.statep = addressof(self.state)
2401 # Buffer for disassembled instruction text
2402 self.buffer = create_string_buffer(256)
2403 self.bufferp = addressof(self.buffer)
2404
2405class LibXED():
2406
2407 def __init__(self):
2408 try:
2409 self.libxed = CDLL("libxed.so")
2410 except:
2411 self.libxed = None
2412 if not self.libxed:
2413 self.libxed = CDLL("/usr/local/lib/libxed.so")
2414
2415 self.xed_tables_init = self.libxed.xed_tables_init
2416 self.xed_tables_init.restype = None
2417 self.xed_tables_init.argtypes = []
2418
2419 self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero
2420 self.xed_decoded_inst_zero.restype = None
2421 self.xed_decoded_inst_zero.argtypes = [ c_void_p ]
2422
2423 self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode
2424 self.xed_operand_values_set_mode.restype = None
2425 self.xed_operand_values_set_mode.argtypes = [ c_void_p, c_void_p ]
2426
2427 self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode
2428 self.xed_decoded_inst_zero_keep_mode.restype = None
2429 self.xed_decoded_inst_zero_keep_mode.argtypes = [ c_void_p ]
2430
2431 self.xed_decode = self.libxed.xed_decode
2432 self.xed_decode.restype = c_int
2433 self.xed_decode.argtypes = [ c_void_p, c_void_p, c_uint ]
2434
2435 self.xed_format_context = self.libxed.xed_format_context
2436 self.xed_format_context.restype = c_uint
2437 self.xed_format_context.argtypes = [ c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p ]
2438
2439 self.xed_tables_init()
2440
2441 def Instruction(self):
2442 return XEDInstruction(self)
2443
2444 def SetMode(self, inst, mode):
2445 if mode:
2446 inst.state.mode = 4 # 32-bit
2447 inst.state.width = 4 # 4 bytes
2448 else:
2449 inst.state.mode = 1 # 64-bit
2450 inst.state.width = 8 # 8 bytes
2451 self.xed_operand_values_set_mode(inst.xedp, inst.statep)
2452
2453 def DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip):
2454 self.xed_decoded_inst_zero_keep_mode(inst.xedp)
2455 err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt)
2456 if err:
2457 return 0, ""
2458 # Use AT&T mode (2), alternative is Intel (3)
2459 ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0)
2460 if not ok:
2461 return 0, ""
2462 # Return instruction length and the disassembled instruction text
2463 # For now, assume the length is in byte 166
2464 return inst.xedd[166], inst.buffer.value
2465
2466def TryOpen(file_name):
2467 try:
2468 return open(file_name, "rb")
2469 except:
2470 return None
2471
2472def Is64Bit(f):
2473 result = sizeof(c_void_p)
2474 # ELF support only
2475 pos = f.tell()
2476 f.seek(0)
2477 header = f.read(7)
2478 f.seek(pos)
2479 magic = header[0:4]
2480 eclass = ord(header[4])
2481 encoding = ord(header[5])
2482 version = ord(header[6])
2483 if magic == chr(127) + "ELF" and eclass > 0 and eclass < 3 and encoding > 0 and encoding < 3 and version == 1:
2484 result = True if eclass == 2 else False
2485 return result
2486
2487# Global data
2488
2489class Glb():
2490
2491 def __init__(self, dbref, db, dbname):
2492 self.dbref = dbref
2493 self.db = db
2494 self.dbname = dbname
2495 self.home_dir = os.path.expanduser("~")
2496 self.buildid_dir = os.getenv("PERF_BUILDID_DIR")
2497 if self.buildid_dir:
2498 self.buildid_dir += "/.build-id/"
2499 else:
2500 self.buildid_dir = self.home_dir + "/.debug/.build-id/"
2501 self.app = None
2502 self.mainwindow = None
2503 self.instances_to_shutdown_on_exit = weakref.WeakSet()
2504 try:
2505 self.disassembler = LibXED()
2506 self.have_disassembler = True
2507 except:
2508 self.have_disassembler = False
2509
2510 def FileFromBuildId(self, build_id):
2511 file_name = self.buildid_dir + build_id[0:2] + "/" + build_id[2:] + "/elf"
2512 return TryOpen(file_name)
2513
2514 def FileFromNamesAndBuildId(self, short_name, long_name, build_id):
2515 # Assume current machine i.e. no support for virtualization
2516 if short_name[0:7] == "[kernel" and os.path.basename(long_name) == "kcore":
2517 file_name = os.getenv("PERF_KCORE")
2518 f = TryOpen(file_name) if file_name else None
2519 if f:
2520 return f
2521 # For now, no special handling if long_name is /proc/kcore
2522 f = TryOpen(long_name)
2523 if f:
2524 return f
2525 f = self.FileFromBuildId(build_id)
2526 if f:
2527 return f
2528 return None
2529
2530 def AddInstanceToShutdownOnExit(self, instance):
2531 self.instances_to_shutdown_on_exit.add(instance)
2532
2533 # Shutdown any background processes or threads
2534 def ShutdownInstances(self):
2535 for x in self.instances_to_shutdown_on_exit:
2536 try:
2537 x.Shutdown()
2538 except:
2539 pass
2540
2541# Database reference
2542
2543class DBRef():
2544
2545 def __init__(self, is_sqlite3, dbname):
2546 self.is_sqlite3 = is_sqlite3
2547 self.dbname = dbname
2548
2549 def Open(self, connection_name):
2550 dbname = self.dbname
2551 if self.is_sqlite3:
2552 db = QSqlDatabase.addDatabase("QSQLITE", connection_name)
2553 else:
2554 db = QSqlDatabase.addDatabase("QPSQL", connection_name)
2555 opts = dbname.split()
2556 for opt in opts:
2557 if "=" in opt:
2558 opt = opt.split("=")
2559 if opt[0] == "hostname":
2560 db.setHostName(opt[1])
2561 elif opt[0] == "port":
2562 db.setPort(int(opt[1]))
2563 elif opt[0] == "username":
2564 db.setUserName(opt[1])
2565 elif opt[0] == "password":
2566 db.setPassword(opt[1])
2567 elif opt[0] == "dbname":
2568 dbname = opt[1]
2569 else:
2570 dbname = opt
2571
2572 db.setDatabaseName(dbname)
2573 if not db.open():
2574 raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
2575 return db, dbname
2576
2577# Main
2578
2579def Main():
2580 if (len(sys.argv) < 2):
2581 print >> sys.stderr, "Usage is: exported-sql-viewer.py {<database name> | --help-only}"
2582 raise Exception("Too few arguments")
2583
2584 dbname = sys.argv[1]
2585 if dbname == "--help-only":
2586 app = QApplication(sys.argv)
2587 mainwindow = HelpOnlyWindow()
2588 mainwindow.show()
2589 err = app.exec_()
2590 sys.exit(err)
2591
2592 is_sqlite3 = False
2593 try:
2594 f = open(dbname)
2595 if f.read(15) == "SQLite format 3":
2596 is_sqlite3 = True
2597 f.close()
2598 except:
2599 pass
2600
2601 dbref = DBRef(is_sqlite3, dbname)
2602 db, dbname = dbref.Open("main")
2603 glb = Glb(dbref, db, dbname)
2604 app = QApplication(sys.argv)
2605 glb.app = app
2606 mainwindow = MainWindow(glb)
2607 glb.mainwindow = mainwindow
2608 mainwindow.show()
2609 err = app.exec_()
2610 glb.ShutdownInstances()
2611 db.close()
2612 sys.exit(err)
2613
2614if __name__ == "__main__":
2615 Main()
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 6c108fa79ae3..0b2b8305c965 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -21,6 +21,7 @@ perf-y += python-use.o
21perf-y += bp_signal.o 21perf-y += bp_signal.o
22perf-y += bp_signal_overflow.o 22perf-y += bp_signal_overflow.o
23perf-y += bp_account.o 23perf-y += bp_account.o
24perf-y += wp.o
24perf-y += task-exit.o 25perf-y += task-exit.o
25perf-y += sw-clock.o 26perf-y += sw-clock.o
26perf-y += mmap-thread-lookup.o 27perf-y += mmap-thread-lookup.o
diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling
index 8a33ca4f9e1f..f0729c454f16 100644
--- a/tools/perf/tests/attr/test-record-group-sampling
+++ b/tools/perf/tests/attr/test-record-group-sampling
@@ -37,4 +37,3 @@ sample_freq=0
37sample_period=0 37sample_period=0
38freq=0 38freq=0
39write_backward=0 39write_backward=0
40sample_id_all=0
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d7a5e1b9aa6f..12c09e0ece71 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -121,6 +121,16 @@ static struct test generic_tests[] = {
121 .is_supported = test__bp_signal_is_supported, 121 .is_supported = test__bp_signal_is_supported,
122 }, 122 },
123 { 123 {
124 .desc = "Watchpoint",
125 .func = test__wp,
126 .is_supported = test__wp_is_supported,
127 .subtest = {
128 .skip_if_fail = false,
129 .get_nr = test__wp_subtest_get_nr,
130 .get_desc = test__wp_subtest_get_desc,
131 },
132 },
133 {
124 .desc = "Number of exit events of a simple workload", 134 .desc = "Number of exit events of a simple workload",
125 .func = test__task_exit, 135 .func = test__task_exit,
126 }, 136 },
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c
index 699561fa512c..5f8501c68da4 100644
--- a/tools/perf/tests/evsel-tp-sched.c
+++ b/tools/perf/tests/evsel-tp-sched.c
@@ -8,7 +8,7 @@
8static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, 8static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
9 int size, bool should_be_signed) 9 int size, bool should_be_signed)
10{ 10{
11 struct format_field *field = perf_evsel__field(evsel, name); 11 struct tep_format_field *field = perf_evsel__field(evsel, name);
12 int is_signed; 12 int is_signed;
13 int ret = 0; 13 int ret = 0;
14 14
@@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
17 return -1; 17 return -1;
18 } 18 }
19 19
20 is_signed = !!(field->flags | FIELD_IS_SIGNED); 20 is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED);
21 if (should_be_signed && !is_signed) { 21 if (should_be_signed && !is_signed) {
22 pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", 22 pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
23 evsel->name, name, is_signed, should_be_signed); 23 evsel->name, name, is_signed, should_be_signed);
diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index 3013ac8f83d0..cab7b0aea6ea 100755
--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -48,7 +48,7 @@ trace_libc_inet_pton_backtrace() {
48 *) 48 *)
49 eventattr='max-stack=3' 49 eventattr='max-stack=3'
50 echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected 50 echo "getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$" >> $expected
51 echo ".*\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected 51 echo ".*(\+0x[[:xdigit:]]+|\[unknown\])[[:space:]]\(.*/bin/ping.*\)$" >> $expected
52 ;; 52 ;;
53 esac 53 esac
54 54
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index a9760e790563..b82f55fcc294 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -59,6 +59,9 @@ int test__python_use(struct test *test, int subtest);
59int test__bp_signal(struct test *test, int subtest); 59int test__bp_signal(struct test *test, int subtest);
60int test__bp_signal_overflow(struct test *test, int subtest); 60int test__bp_signal_overflow(struct test *test, int subtest);
61int test__bp_accounting(struct test *test, int subtest); 61int test__bp_accounting(struct test *test, int subtest);
62int test__wp(struct test *test, int subtest);
63const char *test__wp_subtest_get_desc(int subtest);
64int test__wp_subtest_get_nr(void);
62int test__task_exit(struct test *test, int subtest); 65int test__task_exit(struct test *test, int subtest);
63int test__mem(struct test *test, int subtest); 66int test__mem(struct test *test, int subtest);
64int test__sw_clock_freq(struct test *test, int subtest); 67int test__sw_clock_freq(struct test *test, int subtest);
@@ -106,6 +109,7 @@ int test__unit_number__scnprint(struct test *test, int subtest);
106int test__mem2node(struct test *t, int subtest); 109int test__mem2node(struct test *t, int subtest);
107 110
108bool test__bp_signal_is_supported(void); 111bool test__bp_signal_is_supported(void);
112bool test__wp_is_supported(void);
109 113
110#if defined(__arm__) || defined(__aarch64__) 114#if defined(__arm__) || defined(__aarch64__)
111#ifdef HAVE_DWARF_UNWIND_SUPPORT 115#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/wp.c b/tools/perf/tests/wp.c
new file mode 100644
index 000000000000..f89e6806557b
--- /dev/null
+++ b/tools/perf/tests/wp.c
@@ -0,0 +1,241 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <stdlib.h>
3#include <sys/ioctl.h>
4#include <linux/hw_breakpoint.h>
5#include "tests.h"
6#include "debug.h"
7#include "cloexec.h"
8
9#define WP_TEST_ASSERT_VAL(fd, text, val) \
10do { \
11 long long count; \
12 wp_read(fd, &count, sizeof(long long)); \
13 TEST_ASSERT_VAL(text, count == val); \
14} while (0)
15
16volatile u64 data1;
17volatile u8 data2[3];
18
19static int wp_read(int fd, long long *count, int size)
20{
21 int ret = read(fd, count, size);
22
23 if (ret != size) {
24 pr_debug("failed to read: %d\n", ret);
25 return -1;
26 }
27 return 0;
28}
29
30static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type,
31 void *wp_addr, unsigned long wp_len)
32{
33 memset(attr, 0, sizeof(struct perf_event_attr));
34 attr->type = PERF_TYPE_BREAKPOINT;
35 attr->size = sizeof(struct perf_event_attr);
36 attr->config = 0;
37 attr->bp_type = wp_type;
38 attr->bp_addr = (unsigned long)wp_addr;
39 attr->bp_len = wp_len;
40 attr->sample_period = 1;
41 attr->sample_type = PERF_SAMPLE_IP;
42 attr->exclude_kernel = 1;
43 attr->exclude_hv = 1;
44}
45
46static int __event(int wp_type, void *wp_addr, unsigned long wp_len)
47{
48 int fd;
49 struct perf_event_attr attr;
50
51 get__perf_event_attr(&attr, wp_type, wp_addr, wp_len);
52 fd = sys_perf_event_open(&attr, 0, -1, -1,
53 perf_event_open_cloexec_flag());
54 if (fd < 0)
55 pr_debug("failed opening event %x\n", attr.bp_type);
56
57 return fd;
58}
59
60static int wp_ro_test(void)
61{
62 int fd;
63 unsigned long tmp, tmp1 = rand();
64
65 fd = __event(HW_BREAKPOINT_R, (void *)&data1, sizeof(data1));
66 if (fd < 0)
67 return -1;
68
69 tmp = data1;
70 WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
71
72 data1 = tmp1 + tmp;
73 WP_TEST_ASSERT_VAL(fd, "RO watchpoint", 1);
74
75 close(fd);
76 return 0;
77}
78
79static int wp_wo_test(void)
80{
81 int fd;
82 unsigned long tmp, tmp1 = rand();
83
84 fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
85 if (fd < 0)
86 return -1;
87
88 tmp = data1;
89 WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 0);
90
91 data1 = tmp1 + tmp;
92 WP_TEST_ASSERT_VAL(fd, "WO watchpoint", 1);
93
94 close(fd);
95 return 0;
96}
97
98static int wp_rw_test(void)
99{
100 int fd;
101 unsigned long tmp, tmp1 = rand();
102
103 fd = __event(HW_BREAKPOINT_R | HW_BREAKPOINT_W, (void *)&data1,
104 sizeof(data1));
105 if (fd < 0)
106 return -1;
107
108 tmp = data1;
109 WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 1);
110
111 data1 = tmp1 + tmp;
112 WP_TEST_ASSERT_VAL(fd, "RW watchpoint", 2);
113
114 close(fd);
115 return 0;
116}
117
118static int wp_modify_test(void)
119{
120 int fd, ret;
121 unsigned long tmp = rand();
122 struct perf_event_attr new_attr;
123
124 fd = __event(HW_BREAKPOINT_W, (void *)&data1, sizeof(data1));
125 if (fd < 0)
126 return -1;
127
128 data1 = tmp;
129 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
130
131 /* Modify watchpoint with disabled = 1 */
132 get__perf_event_attr(&new_attr, HW_BREAKPOINT_W, (void *)&data2[0],
133 sizeof(u8) * 2);
134 new_attr.disabled = 1;
135 ret = ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr);
136 if (ret < 0) {
137 pr_debug("ioctl(PERF_EVENT_IOC_MODIFY_ATTRIBUTES) failed\n");
138 close(fd);
139 return ret;
140 }
141
142 data2[1] = tmp; /* Not Counted */
143 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 1);
144
145 /* Enable the event */
146 ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
147 if (ret < 0) {
148 pr_debug("Failed to enable event\n");
149 close(fd);
150 return ret;
151 }
152
153 data2[1] = tmp; /* Counted */
154 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
155
156 data2[2] = tmp; /* Not Counted */
157 WP_TEST_ASSERT_VAL(fd, "Modify watchpoint", 2);
158
159 close(fd);
160 return 0;
161}
162
163static bool wp_ro_supported(void)
164{
165#if defined (__x86_64__) || defined (__i386__)
166 return false;
167#else
168 return true;
169#endif
170}
171
172static void wp_ro_skip_msg(void)
173{
174#if defined (__x86_64__) || defined (__i386__)
175 pr_debug("Hardware does not support read only watchpoints.\n");
176#endif
177}
178
179static struct {
180 const char *desc;
181 int (*target_func)(void);
182 bool (*is_supported)(void);
183 void (*skip_msg)(void);
184} wp_testcase_table[] = {
185 {
186 .desc = "Read Only Watchpoint",
187 .target_func = &wp_ro_test,
188 .is_supported = &wp_ro_supported,
189 .skip_msg = &wp_ro_skip_msg,
190 },
191 {
192 .desc = "Write Only Watchpoint",
193 .target_func = &wp_wo_test,
194 },
195 {
196 .desc = "Read / Write Watchpoint",
197 .target_func = &wp_rw_test,
198 },
199 {
200 .desc = "Modify Watchpoint",
201 .target_func = &wp_modify_test,
202 },
203};
204
205int test__wp_subtest_get_nr(void)
206{
207 return (int)ARRAY_SIZE(wp_testcase_table);
208}
209
210const char *test__wp_subtest_get_desc(int i)
211{
212 if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table))
213 return NULL;
214 return wp_testcase_table[i].desc;
215}
216
217int test__wp(struct test *test __maybe_unused, int i)
218{
219 if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table))
220 return TEST_FAIL;
221
222 if (wp_testcase_table[i].is_supported &&
223 !wp_testcase_table[i].is_supported()) {
224 wp_testcase_table[i].skip_msg();
225 return TEST_SKIP;
226 }
227
228 return !wp_testcase_table[i].target_func() ? TEST_OK : TEST_FAIL;
229}
230
231/* The s390 so far does not have support for
232 * instruction breakpoint using the perf_event_open() system call.
233 */
234bool test__wp_is_supported(void)
235{
236#if defined(__s390x__)
237 return false;
238#else
239 return true;
240#endif
241}
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
index f528ba35e140..304313073242 100644
--- a/tools/perf/trace/beauty/Build
+++ b/tools/perf/trace/beauty/Build
@@ -5,7 +5,9 @@ ifeq ($(SRCARCH),$(filter $(SRCARCH),x86))
5libperf-y += ioctl.o 5libperf-y += ioctl.o
6endif 6endif
7libperf-y += kcmp.o 7libperf-y += kcmp.o
8libperf-y += mount_flags.o
8libperf-y += pkey_alloc.o 9libperf-y += pkey_alloc.o
9libperf-y += prctl.o 10libperf-y += prctl.o
11libperf-y += sockaddr.o
10libperf-y += socket.o 12libperf-y += socket.o
11libperf-y += statx.o 13libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
index 9615af5d412b..039c29039b2c 100644
--- a/tools/perf/trace/beauty/beauty.h
+++ b/tools/perf/trace/beauty/beauty.h
@@ -24,15 +24,43 @@ struct strarray {
24} 24}
25 25
26size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val); 26size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val);
27size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, unsigned long flags);
27 28
28struct trace; 29struct trace;
29struct thread; 30struct thread;
30 31
31size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size); 32size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size);
32 33
34extern struct strarray strarray__socket_families;
35
36/**
37 * augmented_arg: extra payload for syscall pointer arguments
38
39 * If perf_sample->raw_size is more than what a syscall sys_enter_FOO puts,
40 * then its the arguments contents, so that we can show more than just a
41 * pointer. This will be done initially with eBPF, the start of that is at the
42 * tools/perf/examples/bpf/augmented_syscalls.c example for the openat, but
43 * will eventually be done automagically caching the running kernel tracefs
44 * events data into an eBPF C script, that then gets compiled and its .o file
45 * cached for subsequent use. For char pointers like the ones for 'open' like
46 * syscalls its easy, for the rest we should use DWARF or better, BTF, much
47 * more compact.
48 *
49 * @size: 8 if all we need is an integer, otherwise all of the augmented arg.
50 * @int_arg: will be used for integer like pointer contents, like 'accept's 'upeer_addrlen'
51 * @value: u64 aligned, for structs, pathnames
52 */
53struct augmented_arg {
54 int size;
55 int int_arg;
56 u64 value[];
57};
58
33/** 59/**
34 * @val: value of syscall argument being formatted 60 * @val: value of syscall argument being formatted
35 * @args: All the args, use syscall_args__val(arg, nth) to access one 61 * @args: All the args, use syscall_args__val(arg, nth) to access one
62 * @augmented_args: Extra data that can be collected, for instance, with eBPF for expanding the pathname for open, etc
63 * @augmented_args_size: augmented_args total payload size
36 * @thread: tid state (maps, pid, tid, etc) 64 * @thread: tid state (maps, pid, tid, etc)
37 * @trace: 'perf trace' internals: all threads, etc 65 * @trace: 'perf trace' internals: all threads, etc
38 * @parm: private area, may be an strarray, for instance 66 * @parm: private area, may be an strarray, for instance
@@ -43,6 +71,10 @@ size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_
43struct syscall_arg { 71struct syscall_arg {
44 unsigned long val; 72 unsigned long val;
45 unsigned char *args; 73 unsigned char *args;
74 struct {
75 struct augmented_arg *args;
76 int size;
77 } augmented;
46 struct thread *thread; 78 struct thread *thread;
47 struct trace *trace; 79 struct trace *trace;
48 void *parm; 80 void *parm;
@@ -91,6 +123,12 @@ size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_ar
91size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg); 123size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg);
92#define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx 124#define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx
93 125
126unsigned long syscall_arg__mask_val_mount_flags(struct syscall_arg *arg, unsigned long flags);
127#define SCAMV_MOUNT_FLAGS syscall_arg__mask_val_mount_flags
128
129size_t syscall_arg__scnprintf_mount_flags(char *bf, size_t size, struct syscall_arg *arg);
130#define SCA_MOUNT_FLAGS syscall_arg__scnprintf_mount_flags
131
94size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg); 132size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg);
95#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights 133#define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights
96 134
@@ -106,6 +144,9 @@ size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_a
106size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg); 144size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg);
107#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3 145#define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3
108 146
147size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg);
148#define SCA_SOCKADDR syscall_arg__scnprintf_sockaddr
149
109size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg); 150size_t syscall_arg__scnprintf_socket_protocol(char *bf, size_t size, struct syscall_arg *arg);
110#define SCA_SK_PROTO syscall_arg__scnprintf_socket_protocol 151#define SCA_SK_PROTO syscall_arg__scnprintf_socket_protocol
111 152
diff --git a/tools/perf/trace/beauty/clone.c b/tools/perf/trace/beauty/clone.c
index d64d049ab991..010406500c30 100644
--- a/tools/perf/trace/beauty/clone.c
+++ b/tools/perf/trace/beauty/clone.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/cone.c 3 * trace/beauty/cone.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/drm_ioctl.sh b/tools/perf/trace/beauty/drm_ioctl.sh
index 9d3816815e60..9aa94fd523a9 100755
--- a/tools/perf/trace/beauty/drm_ioctl.sh
+++ b/tools/perf/trace/beauty/drm_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/drm/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/drm/
4 5
diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c
index 5d6a477a6400..db5b9b492113 100644
--- a/tools/perf/trace/beauty/eventfd.c
+++ b/tools/perf/trace/beauty/eventfd.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#ifndef EFD_SEMAPHORE 2#ifndef EFD_SEMAPHORE
3#define EFD_SEMAPHORE 1 3#define EFD_SEMAPHORE 1
4#endif 4#endif
diff --git a/tools/perf/trace/beauty/fcntl.c b/tools/perf/trace/beauty/fcntl.c
index 9e8900c13cb1..e6de31674e24 100644
--- a/tools/perf/trace/beauty/fcntl.c
+++ b/tools/perf/trace/beauty/fcntl.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/fcntl.c 3 * trace/beauty/fcntl.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/flock.c b/tools/perf/trace/beauty/flock.c
index c4ff6ad30b06..cf02ae5f0ba6 100644
--- a/tools/perf/trace/beauty/flock.c
+++ b/tools/perf/trace/beauty/flock.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2 2
3#include "trace/beauty/beauty.h" 3#include "trace/beauty/beauty.h"
4#include <linux/kernel.h> 4#include <linux/kernel.h>
diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c
index 61850fbc85ff..1136bde56406 100644
--- a/tools/perf/trace/beauty/futex_op.c
+++ b/tools/perf/trace/beauty/futex_op.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <linux/futex.h> 2#include <linux/futex.h>
3 3
4#ifndef FUTEX_WAIT_BITSET 4#ifndef FUTEX_WAIT_BITSET
diff --git a/tools/perf/trace/beauty/futex_val3.c b/tools/perf/trace/beauty/futex_val3.c
index 26f6b3253511..138b7d588a70 100644
--- a/tools/perf/trace/beauty/futex_val3.c
+++ b/tools/perf/trace/beauty/futex_val3.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <linux/futex.h> 2#include <linux/futex.h>
3 3
4#ifndef FUTEX_BITSET_MATCH_ANY 4#ifndef FUTEX_BITSET_MATCH_ANY
diff --git a/tools/perf/trace/beauty/ioctl.c b/tools/perf/trace/beauty/ioctl.c
index 1be3b4cf0827..5d2a7fd8d407 100644
--- a/tools/perf/trace/beauty/ioctl.c
+++ b/tools/perf/trace/beauty/ioctl.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/ioctl.c 3 * trace/beauty/ioctl.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/kcmp.c b/tools/perf/trace/beauty/kcmp.c
index f62040eb9d5c..b276a274f203 100644
--- a/tools/perf/trace/beauty/kcmp.c
+++ b/tools/perf/trace/beauty/kcmp.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/kcmp.c 3 * trace/beauty/kcmp.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/kcmp_type.sh b/tools/perf/trace/beauty/kcmp_type.sh
index a3c304caa336..df8b17486d57 100755
--- a/tools/perf/trace/beauty/kcmp_type.sh
+++ b/tools/perf/trace/beauty/kcmp_type.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/kvm_ioctl.sh b/tools/perf/trace/beauty/kvm_ioctl.sh
index c4699fd46bb6..4ce54f5bf756 100755
--- a/tools/perf/trace/beauty/kvm_ioctl.sh
+++ b/tools/perf/trace/beauty/kvm_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/madvise_behavior.sh b/tools/perf/trace/beauty/madvise_behavior.sh
index 431639eb4d29..4527d290cdfc 100755
--- a/tools/perf/trace/beauty/madvise_behavior.sh
+++ b/tools/perf/trace/beauty/madvise_behavior.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/
4 5
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index 9f68077b241b..c534bd96ef5c 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -1,5 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <uapi/linux/mman.h> 2#include <uapi/linux/mman.h>
3#include <linux/log2.h>
3 4
4static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 5static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
5 struct syscall_arg *arg) 6 struct syscall_arg *arg)
@@ -30,50 +31,23 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
30 31
31#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot 32#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
32 33
34static size_t mmap__scnprintf_flags(unsigned long flags, char *bf, size_t size)
35{
36#include "trace/beauty/generated/mmap_flags_array.c"
37 static DEFINE_STRARRAY(mmap_flags);
38
39 return strarray__scnprintf_flags(&strarray__mmap_flags, bf, size, flags);
40}
41
33static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, 42static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
34 struct syscall_arg *arg) 43 struct syscall_arg *arg)
35{ 44{
36 int printed = 0, flags = arg->val; 45 unsigned long flags = arg->val;
37 46
38 if (flags & MAP_ANONYMOUS) 47 if (flags & MAP_ANONYMOUS)
39 arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */ 48 arg->mask |= (1 << 4) | (1 << 5); /* Mask 4th ('fd') and 5th ('offset') args, ignored */
40 49
41#define P_MMAP_FLAG(n) \ 50 return mmap__scnprintf_flags(flags, bf, size);
42 if (flags & MAP_##n) { \
43 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
44 flags &= ~MAP_##n; \
45 }
46
47 P_MMAP_FLAG(SHARED);
48 P_MMAP_FLAG(PRIVATE);
49#ifdef MAP_32BIT
50 P_MMAP_FLAG(32BIT);
51#endif
52 P_MMAP_FLAG(ANONYMOUS);
53 P_MMAP_FLAG(DENYWRITE);
54 P_MMAP_FLAG(EXECUTABLE);
55 P_MMAP_FLAG(FILE);
56 P_MMAP_FLAG(FIXED);
57#ifdef MAP_FIXED_NOREPLACE
58 P_MMAP_FLAG(FIXED_NOREPLACE);
59#endif
60 P_MMAP_FLAG(GROWSDOWN);
61 P_MMAP_FLAG(HUGETLB);
62 P_MMAP_FLAG(LOCKED);
63 P_MMAP_FLAG(NONBLOCK);
64 P_MMAP_FLAG(NORESERVE);
65 P_MMAP_FLAG(POPULATE);
66 P_MMAP_FLAG(STACK);
67 P_MMAP_FLAG(UNINITIALIZED);
68#ifdef MAP_SYNC
69 P_MMAP_FLAG(SYNC);
70#endif
71#undef P_MMAP_FLAG
72
73 if (flags)
74 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
75
76 return printed;
77} 51}
78 52
79#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 53#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
diff --git a/tools/perf/trace/beauty/mmap_flags.sh b/tools/perf/trace/beauty/mmap_flags.sh
new file mode 100755
index 000000000000..22c3fdca8975
--- /dev/null
+++ b/tools/perf/trace/beauty/mmap_flags.sh
@@ -0,0 +1,32 @@
1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
3
4if [ $# -ne 2 ] ; then
5 [ $# -eq 1 ] && hostarch=$1 || hostarch=`uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/`
6 header_dir=tools/include/uapi/asm-generic
7 arch_header_dir=tools/arch/${hostarch}/include/uapi/asm
8else
9 header_dir=$1
10 arch_header_dir=$2
11fi
12
13arch_mman=${arch_header_dir}/mman.h
14
15# those in egrep -vw are flags, we want just the bits
16
17printf "static const char *mmap_flags[] = {\n"
18regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MAP_([[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
19egrep -q $regex ${arch_mman} && \
20(egrep $regex ${arch_mman} | \
21 sed -r "s/$regex/\2 \1/g" | \
22 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
23egrep -q '#[[:space:]]*include[[:space:]]+<uapi/asm-generic/mman.*' ${arch_mman} &&
24(egrep $regex ${header_dir}/mman-common.h | \
25 egrep -vw 'MAP_(UNINITIALIZED|TYPE|SHARED_VALIDATE)' | \
26 sed -r "s/$regex/\2 \1/g" | \
27 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
28egrep -q '#[[:space:]]*include[[:space:]]+<uapi/asm-generic/mman.h>.*' ${arch_mman} &&
29(egrep $regex ${header_dir}/mman.h | \
30 sed -r "s/$regex/\2 \1/g" | \
31 xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n")
32printf "};\n"
diff --git a/tools/perf/trace/beauty/mode_t.c b/tools/perf/trace/beauty/mode_t.c
index d929ad7dd97b..6879d36d3004 100644
--- a/tools/perf/trace/beauty/mode_t.c
+++ b/tools/perf/trace/beauty/mode_t.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/stat.h> 3#include <sys/stat.h>
4#include <unistd.h> 4#include <unistd.h>
diff --git a/tools/perf/trace/beauty/mount_flags.c b/tools/perf/trace/beauty/mount_flags.c
new file mode 100644
index 000000000000..712935c6620a
--- /dev/null
+++ b/tools/perf/trace/beauty/mount_flags.c
@@ -0,0 +1,43 @@
1// SPDX-License-Identifier: LGPL-2.1
2/*
3 * trace/beauty/mount_flags.c
4 *
5 * Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
6 */
7
8#include "trace/beauty/beauty.h"
9#include <linux/compiler.h>
10#include <linux/kernel.h>
11#include <linux/log2.h>
12#include <sys/mount.h>
13
14static size_t mount__scnprintf_flags(unsigned long flags, char *bf, size_t size)
15{
16#include "trace/beauty/generated/mount_flags_array.c"
17 static DEFINE_STRARRAY(mount_flags);
18
19 return strarray__scnprintf_flags(&strarray__mount_flags, bf, size, flags);
20}
21
22unsigned long syscall_arg__mask_val_mount_flags(struct syscall_arg *arg __maybe_unused, unsigned long flags)
23{
24 // do_mount in fs/namespace.c:
25 /*
26 * Pre-0.97 versions of mount() didn't have a flags word. When the
27 * flags word was introduced its top half was required to have the
28 * magic value 0xC0ED, and this remained so until 2.4.0-test9.
29 * Therefore, if this magic number is present, it carries no
30 * information and must be discarded.
31 */
32 if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
33 flags &= ~MS_MGC_MSK;
34
35 return flags;
36}
37
38size_t syscall_arg__scnprintf_mount_flags(char *bf, size_t size, struct syscall_arg *arg)
39{
40 unsigned long flags = arg->val;
41
42 return mount__scnprintf_flags(flags, bf, size);
43}
diff --git a/tools/perf/trace/beauty/mount_flags.sh b/tools/perf/trace/beauty/mount_flags.sh
new file mode 100755
index 000000000000..45547573a1db
--- /dev/null
+++ b/tools/perf/trace/beauty/mount_flags.sh
@@ -0,0 +1,15 @@
1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
3
4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
5
6printf "static const char *mount_flags[] = {\n"
7regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+([[:digit:]]+)[[:space:]]*.*'
8egrep $regex ${header_dir}/fs.h | egrep -v '(MSK|VERBOSE|MGC_VAL)\>' | \
9 sed -r "s/$regex/\2 \2 \1/g" | sort -n | \
10 xargs printf "\t[%s ? (ilog2(%s) + 1) : 0] = \"%s\",\n"
11regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+\(1<<([[:digit:]]+)\)[[:space:]]*.*'
12egrep $regex ${header_dir}/fs.h | \
13 sed -r "s/$regex/\2 \1/g" | \
14 xargs printf "\t[%s + 1] = \"%s\",\n"
15printf "};\n"
diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c
index c064d6aae659..1b9d6306d274 100644
--- a/tools/perf/trace/beauty/msg_flags.c
+++ b/tools/perf/trace/beauty/msg_flags.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/socket.h> 3#include <sys/socket.h>
4 4
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index 6aec6178a99d..cc673fec9184 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/stat.h> 3#include <sys/stat.h>
4#include <fcntl.h> 4#include <fcntl.h>
diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c
index 2bafd7c995ff..981185c1974b 100644
--- a/tools/perf/trace/beauty/perf_event_open.c
+++ b/tools/perf/trace/beauty/perf_event_open.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#ifndef PERF_FLAG_FD_NO_GROUP 2#ifndef PERF_FLAG_FD_NO_GROUP
3# define PERF_FLAG_FD_NO_GROUP (1UL << 0) 3# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
4#endif 4#endif
diff --git a/tools/perf/trace/beauty/perf_ioctl.sh b/tools/perf/trace/beauty/perf_ioctl.sh
index 6492c74df928..9aabd9743ef6 100755
--- a/tools/perf/trace/beauty/perf_ioctl.sh
+++ b/tools/perf/trace/beauty/perf_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
index 0313df342830..1a6acc46807b 100644
--- a/tools/perf/trace/beauty/pid.c
+++ b/tools/perf/trace/beauty/pid.c
@@ -1,4 +1,5 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2
2size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg) 3size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
3{ 4{
4 int pid = arg->val; 5 int pid = arg->val;
diff --git a/tools/perf/trace/beauty/pkey_alloc.c b/tools/perf/trace/beauty/pkey_alloc.c
index 2ba784a3734a..1b8ed4cac815 100644
--- a/tools/perf/trace/beauty/pkey_alloc.c
+++ b/tools/perf/trace/beauty/pkey_alloc.c
@@ -1,40 +1,36 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/pkey_alloc.c 3 * trace/beauty/pkey_alloc.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
10#include <linux/kernel.h> 9#include <linux/kernel.h>
11#include <linux/log2.h> 10#include <linux/log2.h>
12 11
13static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size) 12size_t strarray__scnprintf_flags(struct strarray *sa, char *bf, size_t size, unsigned long flags)
14{ 13{
15 int i, printed = 0; 14 int i, printed = 0;
16 15
17#include "trace/beauty/generated/pkey_alloc_access_rights_array.c" 16 if (flags == 0) {
18 static DEFINE_STRARRAY(pkey_alloc_access_rights); 17 const char *s = sa->entries[0];
19
20 if (access_rights == 0) {
21 const char *s = strarray__pkey_alloc_access_rights.entries[0];
22 if (s) 18 if (s)
23 return scnprintf(bf, size, "%s", s); 19 return scnprintf(bf, size, "%s", s);
24 return scnprintf(bf, size, "%d", 0); 20 return scnprintf(bf, size, "%d", 0);
25 } 21 }
26 22
27 for (i = 1; i < strarray__pkey_alloc_access_rights.nr_entries; ++i) { 23 for (i = 1; i < sa->nr_entries; ++i) {
28 int bit = 1 << (i - 1); 24 unsigned long bit = 1UL << (i - 1);
29 25
30 if (!(access_rights & bit)) 26 if (!(flags & bit))
31 continue; 27 continue;
32 28
33 if (printed != 0) 29 if (printed != 0)
34 printed += scnprintf(bf + printed, size - printed, "|"); 30 printed += scnprintf(bf + printed, size - printed, "|");
35 31
36 if (strarray__pkey_alloc_access_rights.entries[i] != NULL) 32 if (sa->entries[i] != NULL)
37 printed += scnprintf(bf + printed, size - printed, "%s", strarray__pkey_alloc_access_rights.entries[i]); 33 printed += scnprintf(bf + printed, size - printed, "%s", sa->entries[i]);
38 else 34 else
39 printed += scnprintf(bf + printed, size - printed, "0x%#", bit); 35 printed += scnprintf(bf + printed, size - printed, "0x%#", bit);
40 } 36 }
@@ -42,6 +38,14 @@ static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, s
42 return printed; 38 return printed;
43} 39}
44 40
41static size_t pkey_alloc__scnprintf_access_rights(int access_rights, char *bf, size_t size)
42{
43#include "trace/beauty/generated/pkey_alloc_access_rights_array.c"
44 static DEFINE_STRARRAY(pkey_alloc_access_rights);
45
46 return strarray__scnprintf_flags(&strarray__pkey_alloc_access_rights, bf, size, access_rights);
47}
48
45size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg) 49size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg)
46{ 50{
47 unsigned long cmd = arg->val; 51 unsigned long cmd = arg->val;
diff --git a/tools/perf/trace/beauty/pkey_alloc_access_rights.sh b/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
index e0a51aeb20b2..f8f1b560cf8a 100755
--- a/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
+++ b/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/asm-generic/
4 5
diff --git a/tools/perf/trace/beauty/prctl.c b/tools/perf/trace/beauty/prctl.c
index 246130dad6c4..be7a5d395975 100644
--- a/tools/perf/trace/beauty/prctl.c
+++ b/tools/perf/trace/beauty/prctl.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/prctl.c 3 * trace/beauty/prctl.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/prctl_option.sh b/tools/perf/trace/beauty/prctl_option.sh
index f24722146ebe..d32f8f1124af 100755
--- a/tools/perf/trace/beauty/prctl_option.sh
+++ b/tools/perf/trace/beauty/prctl_option.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c
index ba5096ae76b6..48f2b5c9aa3e 100644
--- a/tools/perf/trace/beauty/sched_policy.c
+++ b/tools/perf/trace/beauty/sched_policy.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sched.h> 2#include <sched.h>
3 3
4/* 4/*
diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c
index b7097fd5fed9..e36156b19c70 100644
--- a/tools/perf/trace/beauty/seccomp.c
+++ b/tools/perf/trace/beauty/seccomp.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#ifndef SECCOMP_SET_MODE_STRICT 2#ifndef SECCOMP_SET_MODE_STRICT
3#define SECCOMP_SET_MODE_STRICT 0 3#define SECCOMP_SET_MODE_STRICT 0
4#endif 4#endif
diff --git a/tools/perf/trace/beauty/signum.c b/tools/perf/trace/beauty/signum.c
index bde18a53f090..587fec545b8a 100644
--- a/tools/perf/trace/beauty/signum.c
+++ b/tools/perf/trace/beauty/signum.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <signal.h> 2#include <signal.h>
3 3
4static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg) 4static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
diff --git a/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh b/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
index eb511bb5fbd3..e0803b957593 100755
--- a/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
+++ b/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/
4 5
diff --git a/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh b/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
index 6818392968b2..7a464a7bf913 100755
--- a/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
+++ b/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/sound/
4 5
diff --git a/tools/perf/trace/beauty/sockaddr.c b/tools/perf/trace/beauty/sockaddr.c
new file mode 100644
index 000000000000..9410ad230f10
--- /dev/null
+++ b/tools/perf/trace/beauty/sockaddr.c
@@ -0,0 +1,76 @@
1// SPDX-License-Identifier: LGPL-2.1
2// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3
4#include "trace/beauty/beauty.h"
5#include <sys/socket.h>
6#include <sys/types.h>
7#include <sys/un.h>
8#include <arpa/inet.h>
9
10static const char *socket_families[] = {
11 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
12 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
13 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
14 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
15 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
16 "ALG", "NFC", "VSOCK",
17};
18DEFINE_STRARRAY(socket_families);
19
20static size_t af_inet__scnprintf(struct sockaddr *sa, char *bf, size_t size)
21{
22 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
23 char tmp[16];
24 return scnprintf(bf, size, ", port: %d, addr: %s", ntohs(sin->sin_port),
25 inet_ntop(sin->sin_family, &sin->sin_addr, tmp, sizeof(tmp)));
26}
27
28static size_t af_inet6__scnprintf(struct sockaddr *sa, char *bf, size_t size)
29{
30 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
31 u32 flowinfo = ntohl(sin6->sin6_flowinfo);
32 char tmp[512];
33 size_t printed = scnprintf(bf, size, ", port: %d, addr: %s", ntohs(sin6->sin6_port),
34 inet_ntop(sin6->sin6_family, &sin6->sin6_addr, tmp, sizeof(tmp)));
35 if (flowinfo != 0)
36 printed += scnprintf(bf + printed, size - printed, ", flowinfo: %lu", flowinfo);
37 if (sin6->sin6_scope_id != 0)
38 printed += scnprintf(bf + printed, size - printed, ", scope_id: %lu", sin6->sin6_scope_id);
39
40 return printed;
41}
42
43static size_t af_local__scnprintf(struct sockaddr *sa, char *bf, size_t size)
44{
45 struct sockaddr_un *sun = (struct sockaddr_un *)sa;
46 return scnprintf(bf, size, ", path: %s", sun->sun_path);
47}
48
49static size_t (*af_scnprintfs[])(struct sockaddr *sa, char *bf, size_t size) = {
50 [AF_LOCAL] = af_local__scnprintf,
51 [AF_INET] = af_inet__scnprintf,
52 [AF_INET6] = af_inet6__scnprintf,
53};
54
55static size_t syscall_arg__scnprintf_augmented_sockaddr(struct syscall_arg *arg, char *bf, size_t size)
56{
57 struct sockaddr *sa = (struct sockaddr *)arg->augmented.args;
58 char family[32];
59 size_t printed;
60
61 strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", sa->sa_family);
62 printed = scnprintf(bf, size, "{ .family: %s", family);
63
64 if (sa->sa_family < ARRAY_SIZE(af_scnprintfs) && af_scnprintfs[sa->sa_family])
65 printed += af_scnprintfs[sa->sa_family](sa, bf + printed, size - printed);
66
67 return printed + scnprintf(bf + printed, size - printed, " }");
68}
69
70size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg)
71{
72 if (arg->augmented.args)
73 return syscall_arg__scnprintf_augmented_sockaddr(arg, bf, size);
74
75 return scnprintf(bf, size, "%#x", arg->val);
76}
diff --git a/tools/perf/trace/beauty/socket.c b/tools/perf/trace/beauty/socket.c
index 65227269384b..d971a2596417 100644
--- a/tools/perf/trace/beauty/socket.c
+++ b/tools/perf/trace/beauty/socket.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2/* 2/*
3 * trace/beauty/socket.c 3 * trace/beauty/socket.c
4 * 4 *
diff --git a/tools/perf/trace/beauty/socket_ipproto.sh b/tools/perf/trace/beauty/socket_ipproto.sh
index a3cc24633bec..de0f2f29017f 100755
--- a/tools/perf/trace/beauty/socket_ipproto.sh
+++ b/tools/perf/trace/beauty/socket_ipproto.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/socket_type.c b/tools/perf/trace/beauty/socket_type.c
index bca26aef4a77..a63a9a332aa0 100644
--- a/tools/perf/trace/beauty/socket_type.c
+++ b/tools/perf/trace/beauty/socket_type.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/socket.h> 3#include <sys/socket.h>
4 4
diff --git a/tools/perf/trace/beauty/statx.c b/tools/perf/trace/beauty/statx.c
index 5643b692af4c..630f2760dd66 100644
--- a/tools/perf/trace/beauty/statx.c
+++ b/tools/perf/trace/beauty/statx.c
@@ -1,9 +1,8 @@
1// SPDX-License-Identifier: LGPL-2.1
1/* 2/*
2 * trace/beauty/statx.c 3 * trace/beauty/statx.c
3 * 4 *
4 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * Released under the GPL v2. (and only v2, not any later version)
7 */ 6 */
8 7
9#include "trace/beauty/beauty.h" 8#include "trace/beauty/beauty.h"
diff --git a/tools/perf/trace/beauty/vhost_virtio_ioctl.sh b/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
index 0f6a5197d0be..439773daaf77 100755
--- a/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
+++ b/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
@@ -1,4 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# SPDX-License-Identifier: LGPL-2.1
2 3
3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/ 4[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 5
diff --git a/tools/perf/trace/beauty/waitid_options.c b/tools/perf/trace/beauty/waitid_options.c
index 8465281a093d..42ff58ad613b 100644
--- a/tools/perf/trace/beauty/waitid_options.c
+++ b/tools/perf/trace/beauty/waitid_options.c
@@ -1,4 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: LGPL-2.1
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/wait.h> 3#include <sys/wait.h>
4 4
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 7efe15b9618d..ecd9f9ceda77 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -73,6 +73,7 @@ libperf-y += vdso.o
73libperf-y += counts.o 73libperf-y += counts.o
74libperf-y += stat.o 74libperf-y += stat.o
75libperf-y += stat-shadow.o 75libperf-y += stat-shadow.o
76libperf-y += stat-display.o
76libperf-y += record.o 77libperf-y += record.o
77libperf-y += srcline.o 78libperf-y += srcline.o
78libperf-y += data.o 79libperf-y += data.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 28cd6a17491b..6936daf89ddd 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -139,6 +139,7 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i
139#include "arch/x86/annotate/instructions.c" 139#include "arch/x86/annotate/instructions.c"
140#include "arch/powerpc/annotate/instructions.c" 140#include "arch/powerpc/annotate/instructions.c"
141#include "arch/s390/annotate/instructions.c" 141#include "arch/s390/annotate/instructions.c"
142#include "arch/sparc/annotate/instructions.c"
142 143
143static struct arch architectures[] = { 144static struct arch architectures[] = {
144 { 145 {
@@ -170,6 +171,13 @@ static struct arch architectures[] = {
170 .comment_char = '#', 171 .comment_char = '#',
171 }, 172 },
172 }, 173 },
174 {
175 .name = "sparc",
176 .init = sparc__annotate_init,
177 .objdump = {
178 .comment_char = '#',
179 },
180 },
173}; 181};
174 182
175static void ins__delete(struct ins_operands *ops) 183static void ins__delete(struct ins_operands *ops)
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index db1511359c5e..72d5ba2479bf 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -906,9 +906,8 @@ out_free:
906 return err; 906 return err;
907} 907}
908 908
909int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused, 909int perf_event__process_auxtrace_info(struct perf_session *session,
910 union perf_event *event, 910 union perf_event *event)
911 struct perf_session *session)
912{ 911{
913 enum auxtrace_type type = event->auxtrace_info.type; 912 enum auxtrace_type type = event->auxtrace_info.type;
914 913
@@ -932,9 +931,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
932 } 931 }
933} 932}
934 933
935s64 perf_event__process_auxtrace(struct perf_tool *tool, 934s64 perf_event__process_auxtrace(struct perf_session *session,
936 union perf_event *event, 935 union perf_event *event)
937 struct perf_session *session)
938{ 936{
939 s64 err; 937 s64 err;
940 938
@@ -950,7 +948,7 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool,
950 if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE) 948 if (!session->auxtrace || event->header.type != PERF_RECORD_AUXTRACE)
951 return -EINVAL; 949 return -EINVAL;
952 950
953 err = session->auxtrace->process_auxtrace_event(session, event, tool); 951 err = session->auxtrace->process_auxtrace_event(session, event, session->tool);
954 if (err < 0) 952 if (err < 0)
955 return err; 953 return err;
956 954
@@ -964,16 +962,23 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool,
964#define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64 962#define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64
965#define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024 963#define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024
966 964
967void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) 965void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts,
966 bool no_sample)
968{ 967{
969 synth_opts->instructions = true;
970 synth_opts->branches = true; 968 synth_opts->branches = true;
971 synth_opts->transactions = true; 969 synth_opts->transactions = true;
972 synth_opts->ptwrites = true; 970 synth_opts->ptwrites = true;
973 synth_opts->pwr_events = true; 971 synth_opts->pwr_events = true;
974 synth_opts->errors = true; 972 synth_opts->errors = true;
975 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; 973 if (no_sample) {
976 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 974 synth_opts->period_type = PERF_ITRACE_PERIOD_INSTRUCTIONS;
975 synth_opts->period = 1;
976 synth_opts->calls = true;
977 } else {
978 synth_opts->instructions = true;
979 synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE;
980 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
981 }
977 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; 982 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
978 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ; 983 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
979 synth_opts->initial_skip = 0; 984 synth_opts->initial_skip = 0;
@@ -1001,7 +1006,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
1001 } 1006 }
1002 1007
1003 if (!str) { 1008 if (!str) {
1004 itrace_synth_opts__set_default(synth_opts); 1009 itrace_synth_opts__set_default(synth_opts, false);
1005 return 0; 1010 return 0;
1006 } 1011 }
1007 1012
@@ -1185,9 +1190,8 @@ void events_stats__auxtrace_error_warn(const struct events_stats *stats)
1185 } 1190 }
1186} 1191}
1187 1192
1188int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused, 1193int perf_event__process_auxtrace_error(struct perf_session *session,
1189 union perf_event *event, 1194 union perf_event *event)
1190 struct perf_session *session)
1191{ 1195{
1192 if (auxtrace__dont_decode(session)) 1196 if (auxtrace__dont_decode(session))
1193 return 0; 1197 return 0;
@@ -1196,11 +1200,12 @@ int perf_event__process_auxtrace_error(struct perf_tool *tool __maybe_unused,
1196 return 0; 1200 return 0;
1197} 1201}
1198 1202
1199static int __auxtrace_mmap__read(struct auxtrace_mmap *mm, 1203static int __auxtrace_mmap__read(struct perf_mmap *map,
1200 struct auxtrace_record *itr, 1204 struct auxtrace_record *itr,
1201 struct perf_tool *tool, process_auxtrace_t fn, 1205 struct perf_tool *tool, process_auxtrace_t fn,
1202 bool snapshot, size_t snapshot_size) 1206 bool snapshot, size_t snapshot_size)
1203{ 1207{
1208 struct auxtrace_mmap *mm = &map->auxtrace_mmap;
1204 u64 head, old = mm->prev, offset, ref; 1209 u64 head, old = mm->prev, offset, ref;
1205 unsigned char *data = mm->base; 1210 unsigned char *data = mm->base;
1206 size_t size, head_off, old_off, len1, len2, padding; 1211 size_t size, head_off, old_off, len1, len2, padding;
@@ -1287,7 +1292,7 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
1287 ev.auxtrace.tid = mm->tid; 1292 ev.auxtrace.tid = mm->tid;
1288 ev.auxtrace.cpu = mm->cpu; 1293 ev.auxtrace.cpu = mm->cpu;
1289 1294
1290 if (fn(tool, &ev, data1, len1, data2, len2)) 1295 if (fn(tool, map, &ev, data1, len1, data2, len2))
1291 return -1; 1296 return -1;
1292 1297
1293 mm->prev = head; 1298 mm->prev = head;
@@ -1306,18 +1311,18 @@ static int __auxtrace_mmap__read(struct auxtrace_mmap *mm,
1306 return 1; 1311 return 1;
1307} 1312}
1308 1313
1309int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 1314int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr,
1310 struct perf_tool *tool, process_auxtrace_t fn) 1315 struct perf_tool *tool, process_auxtrace_t fn)
1311{ 1316{
1312 return __auxtrace_mmap__read(mm, itr, tool, fn, false, 0); 1317 return __auxtrace_mmap__read(map, itr, tool, fn, false, 0);
1313} 1318}
1314 1319
1315int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm, 1320int auxtrace_mmap__read_snapshot(struct perf_mmap *map,
1316 struct auxtrace_record *itr, 1321 struct auxtrace_record *itr,
1317 struct perf_tool *tool, process_auxtrace_t fn, 1322 struct perf_tool *tool, process_auxtrace_t fn,
1318 size_t snapshot_size) 1323 size_t snapshot_size)
1319{ 1324{
1320 return __auxtrace_mmap__read(mm, itr, tool, fn, true, snapshot_size); 1325 return __auxtrace_mmap__read(map, itr, tool, fn, true, snapshot_size);
1321} 1326}
1322 1327
1323/** 1328/**
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 71fc3bd74299..8e50f96d4b23 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -23,6 +23,7 @@
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/perf_event.h> 24#include <linux/perf_event.h>
25#include <linux/types.h> 25#include <linux/types.h>
26#include <asm/bitsperlong.h>
26 27
27#include "../perf.h" 28#include "../perf.h"
28#include "event.h" 29#include "event.h"
@@ -33,6 +34,7 @@ union perf_event;
33struct perf_session; 34struct perf_session;
34struct perf_evlist; 35struct perf_evlist;
35struct perf_tool; 36struct perf_tool;
37struct perf_mmap;
36struct option; 38struct option;
37struct record_opts; 39struct record_opts;
38struct auxtrace_info_event; 40struct auxtrace_info_event;
@@ -56,6 +58,7 @@ enum itrace_period_type {
56/** 58/**
57 * struct itrace_synth_opts - AUX area tracing synthesis options. 59 * struct itrace_synth_opts - AUX area tracing synthesis options.
58 * @set: indicates whether or not options have been set 60 * @set: indicates whether or not options have been set
61 * @default_no_sample: Default to no sampling.
59 * @inject: indicates the event (not just the sample) must be fully synthesized 62 * @inject: indicates the event (not just the sample) must be fully synthesized
60 * because 'perf inject' will write it out 63 * because 'perf inject' will write it out
61 * @instructions: whether to synthesize 'instructions' events 64 * @instructions: whether to synthesize 'instructions' events
@@ -80,6 +83,7 @@ enum itrace_period_type {
80 */ 83 */
81struct itrace_synth_opts { 84struct itrace_synth_opts {
82 bool set; 85 bool set;
86 bool default_no_sample;
83 bool inject; 87 bool inject;
84 bool instructions; 88 bool instructions;
85 bool branches; 89 bool branches;
@@ -434,13 +438,14 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
434 bool per_cpu); 438 bool per_cpu);
435 439
436typedef int (*process_auxtrace_t)(struct perf_tool *tool, 440typedef int (*process_auxtrace_t)(struct perf_tool *tool,
441 struct perf_mmap *map,
437 union perf_event *event, void *data1, 442 union perf_event *event, void *data1,
438 size_t len1, void *data2, size_t len2); 443 size_t len1, void *data2, size_t len2);
439 444
440int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr, 445int auxtrace_mmap__read(struct perf_mmap *map, struct auxtrace_record *itr,
441 struct perf_tool *tool, process_auxtrace_t fn); 446 struct perf_tool *tool, process_auxtrace_t fn);
442 447
443int auxtrace_mmap__read_snapshot(struct auxtrace_mmap *mm, 448int auxtrace_mmap__read_snapshot(struct perf_mmap *map,
444 struct auxtrace_record *itr, 449 struct auxtrace_record *itr,
445 struct perf_tool *tool, process_auxtrace_t fn, 450 struct perf_tool *tool, process_auxtrace_t fn,
446 size_t snapshot_size); 451 size_t snapshot_size);
@@ -517,18 +522,16 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
517 struct perf_tool *tool, 522 struct perf_tool *tool,
518 struct perf_session *session, 523 struct perf_session *session,
519 perf_event__handler_t process); 524 perf_event__handler_t process);
520int perf_event__process_auxtrace_info(struct perf_tool *tool, 525int perf_event__process_auxtrace_info(struct perf_session *session,
521 union perf_event *event, 526 union perf_event *event);
522 struct perf_session *session); 527s64 perf_event__process_auxtrace(struct perf_session *session,
523s64 perf_event__process_auxtrace(struct perf_tool *tool, 528 union perf_event *event);
524 union perf_event *event, 529int perf_event__process_auxtrace_error(struct perf_session *session,
525 struct perf_session *session); 530 union perf_event *event);
526int perf_event__process_auxtrace_error(struct perf_tool *tool,
527 union perf_event *event,
528 struct perf_session *session);
529int itrace_parse_synth_opts(const struct option *opt, const char *str, 531int itrace_parse_synth_opts(const struct option *opt, const char *str,
530 int unset); 532 int unset);
531void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts); 533void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts,
534 bool no_sample);
532 535
533size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp); 536size_t perf_event__fprintf_auxtrace_error(union perf_event *event, FILE *fp);
534void perf_session__auxtrace_error_inc(struct perf_session *session, 537void perf_session__auxtrace_error_inc(struct perf_session *session,
@@ -577,6 +580,23 @@ static inline void auxtrace__free(struct perf_session *session)
577 return session->auxtrace->free(session); 580 return session->auxtrace->free(session);
578} 581}
579 582
583#define ITRACE_HELP \
584" i: synthesize instructions events\n" \
585" b: synthesize branches events\n" \
586" c: synthesize branches events (calls only)\n" \
587" r: synthesize branches events (returns only)\n" \
588" x: synthesize transactions events\n" \
589" w: synthesize ptwrite events\n" \
590" p: synthesize power events\n" \
591" e: synthesize error events\n" \
592" d: create a debug log\n" \
593" g[len]: synthesize a call chain (use with i or x)\n" \
594" l[len]: synthesize last branch entries (use with i or x)\n" \
595" sNUMBER: skip initial number of events\n" \
596" PERIOD[ns|us|ms|i|t]: specify period to sample stream\n" \
597" concatenate multiple options. Default is ibxwpe or cewp\n"
598
599
580#else 600#else
581 601
582static inline struct auxtrace_record * 602static inline struct auxtrace_record *
@@ -717,6 +737,8 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
717 struct perf_evlist *evlist, int idx, 737 struct perf_evlist *evlist, int idx,
718 bool per_cpu); 738 bool per_cpu);
719 739
740#define ITRACE_HELP ""
741
720#endif 742#endif
721 743
722#endif 744#endif
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 47aac41349a2..f9ae1a993806 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -1615,7 +1615,7 @@ struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const cha
1615int bpf__setup_stdout(struct perf_evlist *evlist) 1615int bpf__setup_stdout(struct perf_evlist *evlist)
1616{ 1616{
1617 struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__"); 1617 struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
1618 return IS_ERR(evsel) ? PTR_ERR(evsel) : 0; 1618 return PTR_ERR_OR_ZERO(evsel);
1619} 1619}
1620 1620
1621#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) 1621#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 2ae640257fdb..73430b73570d 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -244,6 +244,27 @@ static void cs_etm__free(struct perf_session *session)
244 zfree(&aux); 244 zfree(&aux);
245} 245}
246 246
247static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
248{
249 struct machine *machine;
250
251 machine = etmq->etm->machine;
252
253 if (address >= etmq->etm->kernel_start) {
254 if (machine__is_host(machine))
255 return PERF_RECORD_MISC_KERNEL;
256 else
257 return PERF_RECORD_MISC_GUEST_KERNEL;
258 } else {
259 if (machine__is_host(machine))
260 return PERF_RECORD_MISC_USER;
261 else if (perf_guest)
262 return PERF_RECORD_MISC_GUEST_USER;
263 else
264 return PERF_RECORD_MISC_HYPERVISOR;
265 }
266}
267
247static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address, 268static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
248 size_t size, u8 *buffer) 269 size_t size, u8 *buffer)
249{ 270{
@@ -258,10 +279,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
258 return -1; 279 return -1;
259 280
260 machine = etmq->etm->machine; 281 machine = etmq->etm->machine;
261 if (address >= etmq->etm->kernel_start) 282 cpumode = cs_etm__cpu_mode(etmq, address);
262 cpumode = PERF_RECORD_MISC_KERNEL;
263 else
264 cpumode = PERF_RECORD_MISC_USER;
265 283
266 thread = etmq->thread; 284 thread = etmq->thread;
267 if (!thread) { 285 if (!thread) {
@@ -653,7 +671,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
653 struct perf_sample sample = {.ip = 0,}; 671 struct perf_sample sample = {.ip = 0,};
654 672
655 event->sample.header.type = PERF_RECORD_SAMPLE; 673 event->sample.header.type = PERF_RECORD_SAMPLE;
656 event->sample.header.misc = PERF_RECORD_MISC_USER; 674 event->sample.header.misc = cs_etm__cpu_mode(etmq, addr);
657 event->sample.header.size = sizeof(struct perf_event_header); 675 event->sample.header.size = sizeof(struct perf_event_header);
658 676
659 sample.ip = addr; 677 sample.ip = addr;
@@ -665,7 +683,7 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
665 sample.cpu = etmq->packet->cpu; 683 sample.cpu = etmq->packet->cpu;
666 sample.flags = 0; 684 sample.flags = 0;
667 sample.insn_len = 1; 685 sample.insn_len = 1;
668 sample.cpumode = event->header.misc; 686 sample.cpumode = event->sample.header.misc;
669 687
670 if (etm->synth_opts.last_branch) { 688 if (etm->synth_opts.last_branch) {
671 cs_etm__copy_last_branch_rb(etmq); 689 cs_etm__copy_last_branch_rb(etmq);
@@ -706,12 +724,15 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
706 u64 nr; 724 u64 nr;
707 struct branch_entry entries; 725 struct branch_entry entries;
708 } dummy_bs; 726 } dummy_bs;
727 u64 ip;
728
729 ip = cs_etm__last_executed_instr(etmq->prev_packet);
709 730
710 event->sample.header.type = PERF_RECORD_SAMPLE; 731 event->sample.header.type = PERF_RECORD_SAMPLE;
711 event->sample.header.misc = PERF_RECORD_MISC_USER; 732 event->sample.header.misc = cs_etm__cpu_mode(etmq, ip);
712 event->sample.header.size = sizeof(struct perf_event_header); 733 event->sample.header.size = sizeof(struct perf_event_header);
713 734
714 sample.ip = cs_etm__last_executed_instr(etmq->prev_packet); 735 sample.ip = ip;
715 sample.pid = etmq->pid; 736 sample.pid = etmq->pid;
716 sample.tid = etmq->tid; 737 sample.tid = etmq->tid;
717 sample.addr = cs_etm__first_executed_instr(etmq->packet); 738 sample.addr = cs_etm__first_executed_instr(etmq->packet);
@@ -720,7 +741,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq)
720 sample.period = 1; 741 sample.period = 1;
721 sample.cpu = etmq->packet->cpu; 742 sample.cpu = etmq->packet->cpu;
722 sample.flags = 0; 743 sample.flags = 0;
723 sample.cpumode = PERF_RECORD_MISC_USER; 744 sample.cpumode = event->sample.header.misc;
724 745
725 /* 746 /*
726 * perf report cannot handle events without a branch stack 747 * perf report cannot handle events without a branch stack
@@ -1432,7 +1453,8 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
1432 if (session->itrace_synth_opts && session->itrace_synth_opts->set) { 1453 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
1433 etm->synth_opts = *session->itrace_synth_opts; 1454 etm->synth_opts = *session->itrace_synth_opts;
1434 } else { 1455 } else {
1435 itrace_synth_opts__set_default(&etm->synth_opts); 1456 itrace_synth_opts__set_default(&etm->synth_opts,
1457 session->itrace_synth_opts->default_no_sample);
1436 etm->synth_opts.callchain = false; 1458 etm->synth_opts.callchain = false;
1437 } 1459 }
1438 1460
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index abd38abf1d91..2a36fab76994 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -182,20 +182,20 @@ err_put_field:
182} 182}
183 183
184static struct bt_ctf_field_type* 184static struct bt_ctf_field_type*
185get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) 185get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field)
186{ 186{
187 unsigned long flags = field->flags; 187 unsigned long flags = field->flags;
188 188
189 if (flags & FIELD_IS_STRING) 189 if (flags & TEP_FIELD_IS_STRING)
190 return cw->data.string; 190 return cw->data.string;
191 191
192 if (!(flags & FIELD_IS_SIGNED)) { 192 if (!(flags & TEP_FIELD_IS_SIGNED)) {
193 /* unsigned long are mostly pointers */ 193 /* unsigned long are mostly pointers */
194 if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) 194 if (flags & TEP_FIELD_IS_LONG || flags & TEP_FIELD_IS_POINTER)
195 return cw->data.u64_hex; 195 return cw->data.u64_hex;
196 } 196 }
197 197
198 if (flags & FIELD_IS_SIGNED) { 198 if (flags & TEP_FIELD_IS_SIGNED) {
199 if (field->size == 8) 199 if (field->size == 8)
200 return cw->data.s64; 200 return cw->data.s64;
201 else 201 else
@@ -287,7 +287,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
287 struct bt_ctf_event_class *event_class, 287 struct bt_ctf_event_class *event_class,
288 struct bt_ctf_event *event, 288 struct bt_ctf_event *event,
289 struct perf_sample *sample, 289 struct perf_sample *sample,
290 struct format_field *fmtf) 290 struct tep_format_field *fmtf)
291{ 291{
292 struct bt_ctf_field_type *type; 292 struct bt_ctf_field_type *type;
293 struct bt_ctf_field *array_field; 293 struct bt_ctf_field *array_field;
@@ -304,10 +304,10 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
304 name = fmtf->alias; 304 name = fmtf->alias;
305 offset = fmtf->offset; 305 offset = fmtf->offset;
306 len = fmtf->size; 306 len = fmtf->size;
307 if (flags & FIELD_IS_STRING) 307 if (flags & TEP_FIELD_IS_STRING)
308 flags &= ~FIELD_IS_ARRAY; 308 flags &= ~TEP_FIELD_IS_ARRAY;
309 309
310 if (flags & FIELD_IS_DYNAMIC) { 310 if (flags & TEP_FIELD_IS_DYNAMIC) {
311 unsigned long long tmp_val; 311 unsigned long long tmp_val;
312 312
313 tmp_val = tep_read_number(fmtf->event->pevent, 313 tmp_val = tep_read_number(fmtf->event->pevent,
@@ -317,7 +317,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
317 offset &= 0xffff; 317 offset &= 0xffff;
318 } 318 }
319 319
320 if (flags & FIELD_IS_ARRAY) { 320 if (flags & TEP_FIELD_IS_ARRAY) {
321 321
322 type = bt_ctf_event_class_get_field_by_name( 322 type = bt_ctf_event_class_get_field_by_name(
323 event_class, name); 323 event_class, name);
@@ -338,7 +338,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
338 type = get_tracepoint_field_type(cw, fmtf); 338 type = get_tracepoint_field_type(cw, fmtf);
339 339
340 for (i = 0; i < n_items; i++) { 340 for (i = 0; i < n_items; i++) {
341 if (flags & FIELD_IS_ARRAY) 341 if (flags & TEP_FIELD_IS_ARRAY)
342 field = bt_ctf_field_array_get_field(array_field, i); 342 field = bt_ctf_field_array_get_field(array_field, i);
343 else 343 else
344 field = bt_ctf_field_create(type); 344 field = bt_ctf_field_create(type);
@@ -348,7 +348,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
348 return -1; 348 return -1;
349 } 349 }
350 350
351 if (flags & FIELD_IS_STRING) 351 if (flags & TEP_FIELD_IS_STRING)
352 ret = string_set_value(field, data + offset + i * len); 352 ret = string_set_value(field, data + offset + i * len);
353 else { 353 else {
354 unsigned long long value_int; 354 unsigned long long value_int;
@@ -357,7 +357,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
357 fmtf->event->pevent, 357 fmtf->event->pevent,
358 data + offset + i * len, len); 358 data + offset + i * len, len);
359 359
360 if (!(flags & FIELD_IS_SIGNED)) 360 if (!(flags & TEP_FIELD_IS_SIGNED))
361 ret = bt_ctf_field_unsigned_integer_set_value( 361 ret = bt_ctf_field_unsigned_integer_set_value(
362 field, value_int); 362 field, value_int);
363 else 363 else
@@ -369,7 +369,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
369 pr_err("failed to set file value %s\n", name); 369 pr_err("failed to set file value %s\n", name);
370 goto err_put_field; 370 goto err_put_field;
371 } 371 }
372 if (!(flags & FIELD_IS_ARRAY)) { 372 if (!(flags & TEP_FIELD_IS_ARRAY)) {
373 ret = bt_ctf_event_set_payload(event, name, field); 373 ret = bt_ctf_event_set_payload(event, name, field);
374 if (ret) { 374 if (ret) {
375 pr_err("failed to set payload %s\n", name); 375 pr_err("failed to set payload %s\n", name);
@@ -378,7 +378,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
378 } 378 }
379 bt_ctf_field_put(field); 379 bt_ctf_field_put(field);
380 } 380 }
381 if (flags & FIELD_IS_ARRAY) { 381 if (flags & TEP_FIELD_IS_ARRAY) {
382 ret = bt_ctf_event_set_payload(event, name, array_field); 382 ret = bt_ctf_event_set_payload(event, name, array_field);
383 if (ret) { 383 if (ret) {
384 pr_err("Failed add payload array %s\n", name); 384 pr_err("Failed add payload array %s\n", name);
@@ -396,10 +396,10 @@ err_put_field:
396static int add_tracepoint_fields_values(struct ctf_writer *cw, 396static int add_tracepoint_fields_values(struct ctf_writer *cw,
397 struct bt_ctf_event_class *event_class, 397 struct bt_ctf_event_class *event_class,
398 struct bt_ctf_event *event, 398 struct bt_ctf_event *event,
399 struct format_field *fields, 399 struct tep_format_field *fields,
400 struct perf_sample *sample) 400 struct perf_sample *sample)
401{ 401{
402 struct format_field *field; 402 struct tep_format_field *field;
403 int ret; 403 int ret;
404 404
405 for (field = fields; field; field = field->next) { 405 for (field = fields; field; field = field->next) {
@@ -417,8 +417,8 @@ static int add_tracepoint_values(struct ctf_writer *cw,
417 struct perf_evsel *evsel, 417 struct perf_evsel *evsel,
418 struct perf_sample *sample) 418 struct perf_sample *sample)
419{ 419{
420 struct format_field *common_fields = evsel->tp_format->format.common_fields; 420 struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
421 struct format_field *fields = evsel->tp_format->format.fields; 421 struct tep_format_field *fields = evsel->tp_format->format.fields;
422 int ret; 422 int ret;
423 423
424 ret = add_tracepoint_fields_values(cw, event_class, event, 424 ret = add_tracepoint_fields_values(cw, event_class, event,
@@ -970,7 +970,7 @@ out:
970 970
971static int event_class_add_field(struct bt_ctf_event_class *event_class, 971static int event_class_add_field(struct bt_ctf_event_class *event_class,
972 struct bt_ctf_field_type *type, 972 struct bt_ctf_field_type *type,
973 struct format_field *field) 973 struct tep_format_field *field)
974{ 974{
975 struct bt_ctf_field_type *t = NULL; 975 struct bt_ctf_field_type *t = NULL;
976 char *name; 976 char *name;
@@ -1009,10 +1009,10 @@ static int event_class_add_field(struct bt_ctf_event_class *event_class,
1009} 1009}
1010 1010
1011static int add_tracepoint_fields_types(struct ctf_writer *cw, 1011static int add_tracepoint_fields_types(struct ctf_writer *cw,
1012 struct format_field *fields, 1012 struct tep_format_field *fields,
1013 struct bt_ctf_event_class *event_class) 1013 struct bt_ctf_event_class *event_class)
1014{ 1014{
1015 struct format_field *field; 1015 struct tep_format_field *field;
1016 int ret; 1016 int ret;
1017 1017
1018 for (field = fields; field; field = field->next) { 1018 for (field = fields; field; field = field->next) {
@@ -1030,15 +1030,15 @@ static int add_tracepoint_fields_types(struct ctf_writer *cw,
1030 * type and don't care that it is an array. What we don't 1030 * type and don't care that it is an array. What we don't
1031 * support is an array of strings. 1031 * support is an array of strings.
1032 */ 1032 */
1033 if (flags & FIELD_IS_STRING) 1033 if (flags & TEP_FIELD_IS_STRING)
1034 flags &= ~FIELD_IS_ARRAY; 1034 flags &= ~TEP_FIELD_IS_ARRAY;
1035 1035
1036 if (flags & FIELD_IS_ARRAY) 1036 if (flags & TEP_FIELD_IS_ARRAY)
1037 type = bt_ctf_field_type_array_create(type, field->arraylen); 1037 type = bt_ctf_field_type_array_create(type, field->arraylen);
1038 1038
1039 ret = event_class_add_field(event_class, type, field); 1039 ret = event_class_add_field(event_class, type, field);
1040 1040
1041 if (flags & FIELD_IS_ARRAY) 1041 if (flags & TEP_FIELD_IS_ARRAY)
1042 bt_ctf_field_type_put(type); 1042 bt_ctf_field_type_put(type);
1043 1043
1044 if (ret) { 1044 if (ret) {
@@ -1055,8 +1055,8 @@ static int add_tracepoint_types(struct ctf_writer *cw,
1055 struct perf_evsel *evsel, 1055 struct perf_evsel *evsel,
1056 struct bt_ctf_event_class *class) 1056 struct bt_ctf_event_class *class)
1057{ 1057{
1058 struct format_field *common_fields = evsel->tp_format->format.common_fields; 1058 struct tep_format_field *common_fields = evsel->tp_format->format.common_fields;
1059 struct format_field *fields = evsel->tp_format->format.fields; 1059 struct tep_format_field *fields = evsel->tp_format->format.fields;
1060 int ret; 1060 int ret;
1061 1061
1062 ret = add_tracepoint_fields_types(cw, common_fields, class); 1062 ret = add_tracepoint_fields_types(cw, common_fields, class);
@@ -1578,7 +1578,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1578{ 1578{
1579 struct perf_session *session; 1579 struct perf_session *session;
1580 struct perf_data data = { 1580 struct perf_data data = {
1581 .file.path = input, 1581 .file = { .path = input, .fd = -1 },
1582 .mode = PERF_DATA_MODE_READ, 1582 .mode = PERF_DATA_MODE_READ,
1583 .force = opts->force, 1583 .force = opts->force,
1584 }; 1584 };
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 7123746edcf4..69fbb0a72d0c 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -463,6 +463,28 @@ int db_export__branch_types(struct db_export *dbe)
463 if (err) 463 if (err)
464 break; 464 break;
465 } 465 }
466
467 /* Add trace begin / end variants */
468 for (i = 0; branch_types[i].name ; i++) {
469 const char *name = branch_types[i].name;
470 u32 type = branch_types[i].branch_type;
471 char buf[64];
472
473 if (type == PERF_IP_FLAG_BRANCH ||
474 (type & (PERF_IP_FLAG_TRACE_BEGIN | PERF_IP_FLAG_TRACE_END)))
475 continue;
476
477 snprintf(buf, sizeof(buf), "trace begin / %s", name);
478 err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_BEGIN, buf);
479 if (err)
480 break;
481
482 snprintf(buf, sizeof(buf), "%s / trace end", name);
483 err = db_export__branch_type(dbe, type | PERF_IP_FLAG_TRACE_END, buf);
484 if (err)
485 break;
486 }
487
466 return err; 488 return err;
467} 489}
468 490
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 1f3ccc368530..d01b8355f4ca 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -63,6 +63,7 @@ struct perf_env {
63 struct numa_node *numa_nodes; 63 struct numa_node *numa_nodes;
64 struct memory_node *memory_nodes; 64 struct memory_node *memory_nodes;
65 unsigned long long memory_bsize; 65 unsigned long long memory_bsize;
66 u64 clockid_res_ns;
66}; 67};
67 68
68extern struct perf_env perf_env; 69extern struct perf_env perf_env;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 0cd42150f712..e9c108a6b1c3 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -308,6 +308,7 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
308 event->fork.pid = tgid; 308 event->fork.pid = tgid;
309 event->fork.tid = pid; 309 event->fork.tid = pid;
310 event->fork.header.type = PERF_RECORD_FORK; 310 event->fork.header.type = PERF_RECORD_FORK;
311 event->fork.header.misc = PERF_RECORD_MISC_FORK_EXEC;
311 312
312 event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size); 313 event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);
313 314
@@ -1081,6 +1082,7 @@ void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max
1081 } 1082 }
1082 1083
1083 *size += sizeof(struct cpu_map_data); 1084 *size += sizeof(struct cpu_map_data);
1085 *size = PERF_ALIGN(*size, sizeof(u64));
1084 return zalloc(*size); 1086 return zalloc(*size);
1085} 1087}
1086 1088
@@ -1560,26 +1562,9 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
1560 1562
1561 return NULL; 1563 return NULL;
1562 } 1564 }
1563try_again: 1565
1564 al->map = map_groups__find(mg, al->addr); 1566 al->map = map_groups__find(mg, al->addr);
1565 if (al->map == NULL) { 1567 if (al->map != NULL) {
1566 /*
1567 * If this is outside of all known maps, and is a negative
1568 * address, try to look it up in the kernel dso, as it might be
1569 * a vsyscall or vdso (which executes in user-mode).
1570 *
1571 * XXX This is nasty, we should have a symbol list in the
1572 * "[vdso]" dso, but for now lets use the old trick of looking
1573 * in the whole kernel symbol list.
1574 */
1575 if (cpumode == PERF_RECORD_MISC_USER && machine &&
1576 mg != &machine->kmaps &&
1577 machine__kernel_ip(machine, al->addr)) {
1578 mg = &machine->kmaps;
1579 load_map = true;
1580 goto try_again;
1581 }
1582 } else {
1583 /* 1568 /*
1584 * Kernel maps might be changed when loading symbols so loading 1569 * Kernel maps might be changed when loading symbols so loading
1585 * must be done prior to using kernel maps. 1570 * must be done prior to using kernel maps.
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index be440df29615..668d2a9ef0f4 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -358,7 +358,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
358 struct perf_evsel *pos; 358 struct perf_evsel *pos;
359 359
360 evlist__for_each_entry(evlist, pos) { 360 evlist__for_each_entry(evlist, pos) {
361 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 361 if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->fd)
362 continue; 362 continue;
363 perf_evsel__disable(pos); 363 perf_evsel__disable(pos);
364 } 364 }
@@ -1810,3 +1810,30 @@ void perf_evlist__force_leader(struct perf_evlist *evlist)
1810 leader->forced_leader = true; 1810 leader->forced_leader = true;
1811 } 1811 }
1812} 1812}
1813
1814struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list,
1815 struct perf_evsel *evsel)
1816{
1817 struct perf_evsel *c2, *leader;
1818 bool is_open = true;
1819
1820 leader = evsel->leader;
1821 pr_debug("Weak group for %s/%d failed\n",
1822 leader->name, leader->nr_members);
1823
1824 /*
1825 * for_each_group_member doesn't work here because it doesn't
1826 * include the first entry.
1827 */
1828 evlist__for_each_entry(evsel_list, c2) {
1829 if (c2 == evsel)
1830 is_open = false;
1831 if (c2->leader == leader) {
1832 if (is_open)
1833 perf_evsel__close(c2);
1834 c2->leader = c2;
1835 c2->nr_members = 0;
1836 }
1837 }
1838 return leader;
1839}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index dc66436add98..9919eed6d15b 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -312,4 +312,7 @@ bool perf_evlist__exclude_kernel(struct perf_evlist *evlist);
312 312
313void perf_evlist__force_leader(struct perf_evlist *evlist); 313void perf_evlist__force_leader(struct perf_evlist *evlist);
314 314
315struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evlist,
316 struct perf_evsel *evsel);
317
315#endif /* __PERF_EVLIST_H */ 318#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1a61628a1c12..d37bb1566cd9 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -232,6 +232,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
232 evsel->leader = evsel; 232 evsel->leader = evsel;
233 evsel->unit = ""; 233 evsel->unit = "";
234 evsel->scale = 1.0; 234 evsel->scale = 1.0;
235 evsel->max_events = ULONG_MAX;
235 evsel->evlist = NULL; 236 evsel->evlist = NULL;
236 evsel->bpf_fd = -1; 237 evsel->bpf_fd = -1;
237 INIT_LIST_HEAD(&evsel->node); 238 INIT_LIST_HEAD(&evsel->node);
@@ -793,6 +794,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
793 case PERF_EVSEL__CONFIG_TERM_MAX_STACK: 794 case PERF_EVSEL__CONFIG_TERM_MAX_STACK:
794 max_stack = term->val.max_stack; 795 max_stack = term->val.max_stack;
795 break; 796 break;
797 case PERF_EVSEL__CONFIG_TERM_MAX_EVENTS:
798 evsel->max_events = term->val.max_events;
799 break;
796 case PERF_EVSEL__CONFIG_TERM_INHERIT: 800 case PERF_EVSEL__CONFIG_TERM_INHERIT:
797 /* 801 /*
798 * attr->inherit should has already been set by 802 * attr->inherit should has already been set by
@@ -952,7 +956,6 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
952 attr->sample_freq = 0; 956 attr->sample_freq = 0;
953 attr->sample_period = 0; 957 attr->sample_period = 0;
954 attr->write_backward = 0; 958 attr->write_backward = 0;
955 attr->sample_id_all = 0;
956 } 959 }
957 960
958 if (opts->no_samples) 961 if (opts->no_samples)
@@ -1089,6 +1092,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
1089 attr->exclude_user = 1; 1092 attr->exclude_user = 1;
1090 } 1093 }
1091 1094
1095 if (evsel->own_cpus)
1096 evsel->attr.read_format |= PERF_FORMAT_ID;
1097
1092 /* 1098 /*
1093 * Apply event specific term settings, 1099 * Apply event specific term settings,
1094 * it overloads any global configuration. 1100 * it overloads any global configuration.
@@ -1200,16 +1206,27 @@ int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
1200 1206
1201int perf_evsel__enable(struct perf_evsel *evsel) 1207int perf_evsel__enable(struct perf_evsel *evsel)
1202{ 1208{
1203 return perf_evsel__run_ioctl(evsel, 1209 int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
1204 PERF_EVENT_IOC_ENABLE, 1210
1205 0); 1211 if (!err)
1212 evsel->disabled = false;
1213
1214 return err;
1206} 1215}
1207 1216
1208int perf_evsel__disable(struct perf_evsel *evsel) 1217int perf_evsel__disable(struct perf_evsel *evsel)
1209{ 1218{
1210 return perf_evsel__run_ioctl(evsel, 1219 int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
1211 PERF_EVENT_IOC_DISABLE, 1220 /*
1212 0); 1221 * We mark it disabled here so that tools that disable a event can
1222 * ignore events after they disable it. I.e. the ring buffer may have
1223 * already a few more events queued up before the kernel got the stop
1224 * request.
1225 */
1226 if (!err)
1227 evsel->disabled = true;
1228
1229 return err;
1213} 1230}
1214 1231
1215int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 1232int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -2682,7 +2699,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
2682 return 0; 2699 return 0;
2683} 2700}
2684 2701
2685struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) 2702struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
2686{ 2703{
2687 return tep_find_field(evsel->tp_format, name); 2704 return tep_find_field(evsel->tp_format, name);
2688} 2705}
@@ -2690,7 +2707,7 @@ struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *nam
2690void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, 2707void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
2691 const char *name) 2708 const char *name)
2692{ 2709{
2693 struct format_field *field = perf_evsel__field(evsel, name); 2710 struct tep_format_field *field = perf_evsel__field(evsel, name);
2694 int offset; 2711 int offset;
2695 2712
2696 if (!field) 2713 if (!field)
@@ -2698,7 +2715,7 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
2698 2715
2699 offset = field->offset; 2716 offset = field->offset;
2700 2717
2701 if (field->flags & FIELD_IS_DYNAMIC) { 2718 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
2702 offset = *(int *)(sample->raw_data + field->offset); 2719 offset = *(int *)(sample->raw_data + field->offset);
2703 offset &= 0xffff; 2720 offset &= 0xffff;
2704 } 2721 }
@@ -2706,7 +2723,7 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
2706 return sample->raw_data + offset; 2723 return sample->raw_data + offset;
2707} 2724}
2708 2725
2709u64 format_field__intval(struct format_field *field, struct perf_sample *sample, 2726u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample,
2710 bool needs_swap) 2727 bool needs_swap)
2711{ 2728{
2712 u64 value; 2729 u64 value;
@@ -2748,7 +2765,7 @@ u64 format_field__intval(struct format_field *field, struct perf_sample *sample,
2748u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, 2765u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2749 const char *name) 2766 const char *name)
2750{ 2767{
2751 struct format_field *field = perf_evsel__field(evsel, name); 2768 struct tep_format_field *field = perf_evsel__field(evsel, name);
2752 2769
2753 if (!field) 2770 if (!field)
2754 return 0; 2771 return 0;
@@ -2940,3 +2957,32 @@ struct perf_env *perf_evsel__env(struct perf_evsel *evsel)
2940 return evsel->evlist->env; 2957 return evsel->evlist->env;
2941 return NULL; 2958 return NULL;
2942} 2959}
2960
2961static int store_evsel_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
2962{
2963 int cpu, thread;
2964
2965 for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
2966 for (thread = 0; thread < xyarray__max_y(evsel->fd);
2967 thread++) {
2968 int fd = FD(evsel, cpu, thread);
2969
2970 if (perf_evlist__id_add_fd(evlist, evsel,
2971 cpu, thread, fd) < 0)
2972 return -1;
2973 }
2974 }
2975
2976 return 0;
2977}
2978
2979int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist)
2980{
2981 struct cpu_map *cpus = evsel->cpus;
2982 struct thread_map *threads = evsel->threads;
2983
2984 if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr))
2985 return -ENOMEM;
2986
2987 return store_evsel_ids(evsel, evlist);
2988}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 163c960614d3..3147ca76c6fc 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -46,6 +46,7 @@ enum term_type {
46 PERF_EVSEL__CONFIG_TERM_STACK_USER, 46 PERF_EVSEL__CONFIG_TERM_STACK_USER,
47 PERF_EVSEL__CONFIG_TERM_INHERIT, 47 PERF_EVSEL__CONFIG_TERM_INHERIT,
48 PERF_EVSEL__CONFIG_TERM_MAX_STACK, 48 PERF_EVSEL__CONFIG_TERM_MAX_STACK,
49 PERF_EVSEL__CONFIG_TERM_MAX_EVENTS,
49 PERF_EVSEL__CONFIG_TERM_OVERWRITE, 50 PERF_EVSEL__CONFIG_TERM_OVERWRITE,
50 PERF_EVSEL__CONFIG_TERM_DRV_CFG, 51 PERF_EVSEL__CONFIG_TERM_DRV_CFG,
51 PERF_EVSEL__CONFIG_TERM_BRANCH, 52 PERF_EVSEL__CONFIG_TERM_BRANCH,
@@ -65,6 +66,7 @@ struct perf_evsel_config_term {
65 bool inherit; 66 bool inherit;
66 bool overwrite; 67 bool overwrite;
67 char *branch; 68 char *branch;
69 unsigned long max_events;
68 } val; 70 } val;
69 bool weak; 71 bool weak;
70}; 72};
@@ -99,10 +101,12 @@ struct perf_evsel {
99 struct perf_counts *prev_raw_counts; 101 struct perf_counts *prev_raw_counts;
100 int idx; 102 int idx;
101 u32 ids; 103 u32 ids;
104 unsigned long max_events;
105 unsigned long nr_events_printed;
102 char *name; 106 char *name;
103 double scale; 107 double scale;
104 const char *unit; 108 const char *unit;
105 struct event_format *tp_format; 109 struct tep_event_format *tp_format;
106 off_t id_offset; 110 off_t id_offset;
107 struct perf_stat_evsel *stats; 111 struct perf_stat_evsel *stats;
108 void *priv; 112 void *priv;
@@ -119,6 +123,7 @@ struct perf_evsel {
119 bool snapshot; 123 bool snapshot;
120 bool supported; 124 bool supported;
121 bool needs_swap; 125 bool needs_swap;
126 bool disabled;
122 bool no_aux_samples; 127 bool no_aux_samples;
123 bool immediate; 128 bool immediate;
124 bool system_wide; 129 bool system_wide;
@@ -211,7 +216,7 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
211 216
212struct perf_evsel *perf_evsel__new_cycles(bool precise); 217struct perf_evsel *perf_evsel__new_cycles(bool precise);
213 218
214struct event_format *event_format__new(const char *sys, const char *name); 219struct tep_event_format *event_format__new(const char *sys, const char *name);
215 220
216void perf_evsel__init(struct perf_evsel *evsel, 221void perf_evsel__init(struct perf_evsel *evsel,
217 struct perf_event_attr *attr, int idx); 222 struct perf_event_attr *attr, int idx);
@@ -296,11 +301,11 @@ static inline char *perf_evsel__strval(struct perf_evsel *evsel,
296 return perf_evsel__rawptr(evsel, sample, name); 301 return perf_evsel__rawptr(evsel, sample, name);
297} 302}
298 303
299struct format_field; 304struct tep_format_field;
300 305
301u64 format_field__intval(struct format_field *field, struct perf_sample *sample, bool needs_swap); 306u64 format_field__intval(struct tep_format_field *field, struct perf_sample *sample, bool needs_swap);
302 307
303struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); 308struct tep_format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
304 309
305#define perf_evsel__match(evsel, t, c) \ 310#define perf_evsel__match(evsel, t, c) \
306 (evsel->attr.type == PERF_TYPE_##t && \ 311 (evsel->attr.type == PERF_TYPE_##t && \
@@ -481,4 +486,5 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
481 486
482struct perf_env *perf_evsel__env(struct perf_evsel *evsel); 487struct perf_env *perf_evsel__env(struct perf_evsel *evsel);
483 488
489int perf_evsel__store_ids(struct perf_evsel *evsel, struct perf_evlist *evlist);
484#endif /* __PERF_EVSEL_H */ 490#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 06dfb027879d..0d0a4c6f368b 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -73,7 +73,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
73 } 73 }
74 74
75 if (details->trace_fields) { 75 if (details->trace_fields) {
76 struct format_field *field; 76 struct tep_format_field *field;
77 77
78 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { 78 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
79 printed += comma_fprintf(fp, &first, " (not a tracepoint)"); 79 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h
index de322d51c7fe..b72440bf9a79 100644
--- a/tools/perf/util/genelf.h
+++ b/tools/perf/util/genelf.h
@@ -29,6 +29,12 @@ int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_ent
29#elif defined(__powerpc__) 29#elif defined(__powerpc__)
30#define GEN_ELF_ARCH EM_PPC 30#define GEN_ELF_ARCH EM_PPC
31#define GEN_ELF_CLASS ELFCLASS32 31#define GEN_ELF_CLASS ELFCLASS32
32#elif defined(__sparc__) && defined(__arch64__)
33#define GEN_ELF_ARCH EM_SPARCV9
34#define GEN_ELF_CLASS ELFCLASS64
35#elif defined(__sparc__)
36#define GEN_ELF_ARCH EM_SPARC
37#define GEN_ELF_CLASS ELFCLASS32
32#else 38#else
33#error "unsupported architecture" 39#error "unsupported architecture"
34#endif 40#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3cadc252dd89..4fd45be95a43 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1034,6 +1034,13 @@ static int write_auxtrace(struct feat_fd *ff,
1034 return err; 1034 return err;
1035} 1035}
1036 1036
1037static int write_clockid(struct feat_fd *ff,
1038 struct perf_evlist *evlist __maybe_unused)
1039{
1040 return do_write(ff, &ff->ph->env.clockid_res_ns,
1041 sizeof(ff->ph->env.clockid_res_ns));
1042}
1043
1037static int cpu_cache_level__sort(const void *a, const void *b) 1044static int cpu_cache_level__sort(const void *a, const void *b)
1038{ 1045{
1039 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a; 1046 struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
@@ -1508,6 +1515,12 @@ static void print_cpu_topology(struct feat_fd *ff, FILE *fp)
1508 fprintf(fp, "# Core ID and Socket ID information is not available\n"); 1515 fprintf(fp, "# Core ID and Socket ID information is not available\n");
1509} 1516}
1510 1517
1518static void print_clockid(struct feat_fd *ff, FILE *fp)
1519{
1520 fprintf(fp, "# clockid frequency: %"PRIu64" MHz\n",
1521 ff->ph->env.clockid_res_ns * 1000);
1522}
1523
1511static void free_event_desc(struct perf_evsel *events) 1524static void free_event_desc(struct perf_evsel *events)
1512{ 1525{
1513 struct perf_evsel *evsel; 1526 struct perf_evsel *evsel;
@@ -2531,6 +2544,15 @@ out:
2531 return ret; 2544 return ret;
2532} 2545}
2533 2546
2547static int process_clockid(struct feat_fd *ff,
2548 void *data __maybe_unused)
2549{
2550 if (do_read_u64(ff, &ff->ph->env.clockid_res_ns))
2551 return -1;
2552
2553 return 0;
2554}
2555
2534struct feature_ops { 2556struct feature_ops {
2535 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2557 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
2536 void (*print)(struct feat_fd *ff, FILE *fp); 2558 void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2590,6 +2612,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
2590 FEAT_OPN(CACHE, cache, true), 2612 FEAT_OPN(CACHE, cache, true),
2591 FEAT_OPR(SAMPLE_TIME, sample_time, false), 2613 FEAT_OPR(SAMPLE_TIME, sample_time, false),
2592 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true), 2614 FEAT_OPR(MEM_TOPOLOGY, mem_topology, true),
2615 FEAT_OPR(CLOCKID, clockid, false)
2593}; 2616};
2594 2617
2595struct header_print_data { 2618struct header_print_data {
@@ -3206,7 +3229,7 @@ static int read_attr(int fd, struct perf_header *ph,
3206static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, 3229static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3207 struct tep_handle *pevent) 3230 struct tep_handle *pevent)
3208{ 3231{
3209 struct event_format *event; 3232 struct tep_event_format *event;
3210 char bf[128]; 3233 char bf[128];
3211 3234
3212 /* already prepared */ 3235 /* already prepared */
@@ -3448,10 +3471,10 @@ int perf_event__synthesize_features(struct perf_tool *tool,
3448 return ret; 3471 return ret;
3449} 3472}
3450 3473
3451int perf_event__process_feature(struct perf_tool *tool, 3474int perf_event__process_feature(struct perf_session *session,
3452 union perf_event *event, 3475 union perf_event *event)
3453 struct perf_session *session __maybe_unused)
3454{ 3476{
3477 struct perf_tool *tool = session->tool;
3455 struct feat_fd ff = { .fd = 0 }; 3478 struct feat_fd ff = { .fd = 0 };
3456 struct feature_event *fe = (struct feature_event *)event; 3479 struct feature_event *fe = (struct feature_event *)event;
3457 int type = fe->header.type; 3480 int type = fe->header.type;
@@ -3637,13 +3660,13 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp)
3637} 3660}
3638 3661
3639int perf_event__synthesize_attrs(struct perf_tool *tool, 3662int perf_event__synthesize_attrs(struct perf_tool *tool,
3640 struct perf_session *session, 3663 struct perf_evlist *evlist,
3641 perf_event__handler_t process) 3664 perf_event__handler_t process)
3642{ 3665{
3643 struct perf_evsel *evsel; 3666 struct perf_evsel *evsel;
3644 int err = 0; 3667 int err = 0;
3645 3668
3646 evlist__for_each_entry(session->evlist, evsel) { 3669 evlist__for_each_entry(evlist, evsel) {
3647 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, 3670 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
3648 evsel->id, process); 3671 evsel->id, process);
3649 if (err) { 3672 if (err) {
@@ -3856,9 +3879,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
3856 return aligned_size; 3879 return aligned_size;
3857} 3880}
3858 3881
3859int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, 3882int perf_event__process_tracing_data(struct perf_session *session,
3860 union perf_event *event, 3883 union perf_event *event)
3861 struct perf_session *session)
3862{ 3884{
3863 ssize_t size_read, padding, size = event->tracing_data.size; 3885 ssize_t size_read, padding, size = event->tracing_data.size;
3864 int fd = perf_data__fd(session->data); 3886 int fd = perf_data__fd(session->data);
@@ -3924,9 +3946,8 @@ int perf_event__synthesize_build_id(struct perf_tool *tool,
3924 return err; 3946 return err;
3925} 3947}
3926 3948
3927int perf_event__process_build_id(struct perf_tool *tool __maybe_unused, 3949int perf_event__process_build_id(struct perf_session *session,
3928 union perf_event *event, 3950 union perf_event *event)
3929 struct perf_session *session)
3930{ 3951{
3931 __event_process_build_id(&event->build_id, 3952 __event_process_build_id(&event->build_id,
3932 event->build_id.filename, 3953 event->build_id.filename,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 6d7fe44aadc0..0d553ddca0a3 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -38,6 +38,7 @@ enum {
38 HEADER_CACHE, 38 HEADER_CACHE,
39 HEADER_SAMPLE_TIME, 39 HEADER_SAMPLE_TIME,
40 HEADER_MEM_TOPOLOGY, 40 HEADER_MEM_TOPOLOGY,
41 HEADER_CLOCKID,
41 HEADER_LAST_FEATURE, 42 HEADER_LAST_FEATURE,
42 HEADER_FEAT_BITS = 256, 43 HEADER_FEAT_BITS = 256,
43}; 44};
@@ -116,15 +117,14 @@ int perf_event__synthesize_extra_attr(struct perf_tool *tool,
116 perf_event__handler_t process, 117 perf_event__handler_t process,
117 bool is_pipe); 118 bool is_pipe);
118 119
119int perf_event__process_feature(struct perf_tool *tool, 120int perf_event__process_feature(struct perf_session *session,
120 union perf_event *event, 121 union perf_event *event);
121 struct perf_session *session);
122 122
123int perf_event__synthesize_attr(struct perf_tool *tool, 123int perf_event__synthesize_attr(struct perf_tool *tool,
124 struct perf_event_attr *attr, u32 ids, u64 *id, 124 struct perf_event_attr *attr, u32 ids, u64 *id,
125 perf_event__handler_t process); 125 perf_event__handler_t process);
126int perf_event__synthesize_attrs(struct perf_tool *tool, 126int perf_event__synthesize_attrs(struct perf_tool *tool,
127 struct perf_session *session, 127 struct perf_evlist *evlist,
128 perf_event__handler_t process); 128 perf_event__handler_t process);
129int perf_event__synthesize_event_update_unit(struct perf_tool *tool, 129int perf_event__synthesize_event_update_unit(struct perf_tool *tool,
130 struct perf_evsel *evsel, 130 struct perf_evsel *evsel,
@@ -148,17 +148,15 @@ size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp);
148int perf_event__synthesize_tracing_data(struct perf_tool *tool, 148int perf_event__synthesize_tracing_data(struct perf_tool *tool,
149 int fd, struct perf_evlist *evlist, 149 int fd, struct perf_evlist *evlist,
150 perf_event__handler_t process); 150 perf_event__handler_t process);
151int perf_event__process_tracing_data(struct perf_tool *tool, 151int perf_event__process_tracing_data(struct perf_session *session,
152 union perf_event *event, 152 union perf_event *event);
153 struct perf_session *session);
154 153
155int perf_event__synthesize_build_id(struct perf_tool *tool, 154int perf_event__synthesize_build_id(struct perf_tool *tool,
156 struct dso *pos, u16 misc, 155 struct dso *pos, u16 misc,
157 perf_event__handler_t process, 156 perf_event__handler_t process,
158 struct machine *machine); 157 struct machine *machine);
159int perf_event__process_build_id(struct perf_tool *tool, 158int perf_event__process_build_id(struct perf_session *session,
160 union perf_event *event, 159 union perf_event *event);
161 struct perf_session *session);
162bool is_perf_magic(u64 magic); 160bool is_perf_magic(u64 magic);
163 161
164#define NAME_ALIGN 64 162#define NAME_ALIGN 64
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 7f0c83b6332b..7b27d77306c2 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -269,6 +269,13 @@ static int intel_bts_do_fix_overlap(struct auxtrace_queue *queue,
269 return 0; 269 return 0;
270} 270}
271 271
272static inline u8 intel_bts_cpumode(struct intel_bts *bts, uint64_t ip)
273{
274 return machine__kernel_ip(bts->machine, ip) ?
275 PERF_RECORD_MISC_KERNEL :
276 PERF_RECORD_MISC_USER;
277}
278
272static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq, 279static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
273 struct branch *branch) 280 struct branch *branch)
274{ 281{
@@ -281,12 +288,8 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
281 bts->num_events++ <= bts->synth_opts.initial_skip) 288 bts->num_events++ <= bts->synth_opts.initial_skip)
282 return 0; 289 return 0;
283 290
284 event.sample.header.type = PERF_RECORD_SAMPLE;
285 event.sample.header.misc = PERF_RECORD_MISC_USER;
286 event.sample.header.size = sizeof(struct perf_event_header);
287
288 sample.cpumode = PERF_RECORD_MISC_USER;
289 sample.ip = le64_to_cpu(branch->from); 291 sample.ip = le64_to_cpu(branch->from);
292 sample.cpumode = intel_bts_cpumode(bts, sample.ip);
290 sample.pid = btsq->pid; 293 sample.pid = btsq->pid;
291 sample.tid = btsq->tid; 294 sample.tid = btsq->tid;
292 sample.addr = le64_to_cpu(branch->to); 295 sample.addr = le64_to_cpu(branch->to);
@@ -298,6 +301,10 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
298 sample.insn_len = btsq->intel_pt_insn.length; 301 sample.insn_len = btsq->intel_pt_insn.length;
299 memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ); 302 memcpy(sample.insn, btsq->intel_pt_insn.buf, INTEL_PT_INSN_BUF_SZ);
300 303
304 event.sample.header.type = PERF_RECORD_SAMPLE;
305 event.sample.header.misc = sample.cpumode;
306 event.sample.header.size = sizeof(struct perf_event_header);
307
301 if (bts->synth_opts.inject) { 308 if (bts->synth_opts.inject) {
302 event.sample.header.size = bts->branches_event_size; 309 event.sample.header.size = bts->branches_event_size;
303 ret = perf_event__synthesize_sample(&event, 310 ret = perf_event__synthesize_sample(&event,
@@ -910,7 +917,8 @@ int intel_bts_process_auxtrace_info(union perf_event *event,
910 if (session->itrace_synth_opts && session->itrace_synth_opts->set) { 917 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
911 bts->synth_opts = *session->itrace_synth_opts; 918 bts->synth_opts = *session->itrace_synth_opts;
912 } else { 919 } else {
913 itrace_synth_opts__set_default(&bts->synth_opts); 920 itrace_synth_opts__set_default(&bts->synth_opts,
921 session->itrace_synth_opts->default_no_sample);
914 if (session->itrace_synth_opts) 922 if (session->itrace_synth_opts)
915 bts->synth_opts.thread_stack = 923 bts->synth_opts.thread_stack =
916 session->itrace_synth_opts->thread_stack; 924 session->itrace_synth_opts->thread_stack;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index d404bed7003a..4503f3ca45ab 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -1165,7 +1165,7 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1165 decoder->pge = false; 1165 decoder->pge = false;
1166 decoder->continuous_period = false; 1166 decoder->continuous_period = false;
1167 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1167 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1168 decoder->state.to_ip = 0; 1168 decoder->state.type |= INTEL_PT_TRACE_END;
1169 return 0; 1169 return 0;
1170 } 1170 }
1171 if (err == INTEL_PT_RETURN) 1171 if (err == INTEL_PT_RETURN)
@@ -1179,9 +1179,13 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1179 decoder->continuous_period = false; 1179 decoder->continuous_period = false;
1180 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1180 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1181 decoder->state.from_ip = decoder->ip; 1181 decoder->state.from_ip = decoder->ip;
1182 decoder->state.to_ip = 0; 1182 if (decoder->packet.count == 0) {
1183 if (decoder->packet.count != 0) 1183 decoder->state.to_ip = 0;
1184 } else {
1185 decoder->state.to_ip = decoder->last_ip;
1184 decoder->ip = decoder->last_ip; 1186 decoder->ip = decoder->last_ip;
1187 }
1188 decoder->state.type |= INTEL_PT_TRACE_END;
1185 } else { 1189 } else {
1186 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1190 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1187 decoder->state.from_ip = decoder->ip; 1191 decoder->state.from_ip = decoder->ip;
@@ -1208,7 +1212,8 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1208 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1212 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1209 decoder->ip = to_ip; 1213 decoder->ip = to_ip;
1210 decoder->state.from_ip = decoder->ip; 1214 decoder->state.from_ip = decoder->ip;
1211 decoder->state.to_ip = 0; 1215 decoder->state.to_ip = to_ip;
1216 decoder->state.type |= INTEL_PT_TRACE_END;
1212 return 0; 1217 return 0;
1213 } 1218 }
1214 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", 1219 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
@@ -1469,6 +1474,8 @@ static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder)
1469 decoder->have_calc_cyc_to_tsc = false; 1474 decoder->have_calc_cyc_to_tsc = false;
1470 intel_pt_calc_cyc_to_tsc(decoder, true); 1475 intel_pt_calc_cyc_to_tsc(decoder, true);
1471 } 1476 }
1477
1478 intel_pt_log_to("Setting timestamp", decoder->timestamp);
1472} 1479}
1473 1480
1474static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder) 1481static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder)
@@ -1509,6 +1516,8 @@ static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder)
1509 decoder->timestamp = timestamp; 1516 decoder->timestamp = timestamp;
1510 1517
1511 decoder->timestamp_insn_cnt = 0; 1518 decoder->timestamp_insn_cnt = 0;
1519
1520 intel_pt_log_to("Setting timestamp", decoder->timestamp);
1512} 1521}
1513 1522
1514/* Walk PSB+ packets when already in sync. */ 1523/* Walk PSB+ packets when already in sync. */
@@ -1640,14 +1649,15 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1640 1649
1641 case INTEL_PT_TIP_PGD: 1650 case INTEL_PT_TIP_PGD:
1642 decoder->state.from_ip = decoder->ip; 1651 decoder->state.from_ip = decoder->ip;
1643 decoder->state.to_ip = 0; 1652 if (decoder->packet.count == 0) {
1644 if (decoder->packet.count != 0) { 1653 decoder->state.to_ip = 0;
1654 } else {
1645 intel_pt_set_ip(decoder); 1655 intel_pt_set_ip(decoder);
1646 intel_pt_log("Omitting PGD ip " x64_fmt "\n", 1656 decoder->state.to_ip = decoder->ip;
1647 decoder->ip);
1648 } 1657 }
1649 decoder->pge = false; 1658 decoder->pge = false;
1650 decoder->continuous_period = false; 1659 decoder->continuous_period = false;
1660 decoder->state.type |= INTEL_PT_TRACE_END;
1651 return 0; 1661 return 0;
1652 1662
1653 case INTEL_PT_TIP_PGE: 1663 case INTEL_PT_TIP_PGE:
@@ -1661,6 +1671,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
1661 intel_pt_set_ip(decoder); 1671 intel_pt_set_ip(decoder);
1662 decoder->state.to_ip = decoder->ip; 1672 decoder->state.to_ip = decoder->ip;
1663 } 1673 }
1674 decoder->state.type |= INTEL_PT_TRACE_BEGIN;
1664 return 0; 1675 return 0;
1665 1676
1666 case INTEL_PT_TIP: 1677 case INTEL_PT_TIP:
@@ -1739,6 +1750,7 @@ next:
1739 intel_pt_set_ip(decoder); 1750 intel_pt_set_ip(decoder);
1740 decoder->state.from_ip = 0; 1751 decoder->state.from_ip = 0;
1741 decoder->state.to_ip = decoder->ip; 1752 decoder->state.to_ip = decoder->ip;
1753 decoder->state.type |= INTEL_PT_TRACE_BEGIN;
1742 return 0; 1754 return 0;
1743 } 1755 }
1744 1756
@@ -2077,9 +2089,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
2077 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; 2089 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
2078 if (intel_pt_have_ip(decoder)) 2090 if (intel_pt_have_ip(decoder))
2079 intel_pt_set_ip(decoder); 2091 intel_pt_set_ip(decoder);
2080 if (decoder->ip) 2092 if (!decoder->ip)
2081 return 0; 2093 break;
2082 break; 2094 if (decoder->packet.type == INTEL_PT_TIP_PGE)
2095 decoder->state.type |= INTEL_PT_TRACE_BEGIN;
2096 if (decoder->packet.type == INTEL_PT_TIP_PGD)
2097 decoder->state.type |= INTEL_PT_TRACE_END;
2098 return 0;
2083 2099
2084 case INTEL_PT_FUP: 2100 case INTEL_PT_FUP:
2085 if (intel_pt_have_ip(decoder)) 2101 if (intel_pt_have_ip(decoder))
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 51c18d67f4ca..ed088d4726ba 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -37,6 +37,8 @@ enum intel_pt_sample_type {
37 INTEL_PT_EX_STOP = 1 << 6, 37 INTEL_PT_EX_STOP = 1 << 6,
38 INTEL_PT_PWR_EXIT = 1 << 7, 38 INTEL_PT_PWR_EXIT = 1 << 7,
39 INTEL_PT_CBR_CHG = 1 << 8, 39 INTEL_PT_CBR_CHG = 1 << 8,
40 INTEL_PT_TRACE_BEGIN = 1 << 9,
41 INTEL_PT_TRACE_END = 1 << 10,
40}; 42};
41 43
42enum intel_pt_period_type { 44enum intel_pt_period_type {
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
index e02bc7b166a0..5e64da270f97 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c
@@ -31,6 +31,11 @@ static FILE *f;
31static char log_name[MAX_LOG_NAME]; 31static char log_name[MAX_LOG_NAME];
32bool intel_pt_enable_logging; 32bool intel_pt_enable_logging;
33 33
34void *intel_pt_log_fp(void)
35{
36 return f;
37}
38
34void intel_pt_log_enable(void) 39void intel_pt_log_enable(void)
35{ 40{
36 intel_pt_enable_logging = true; 41 intel_pt_enable_logging = true;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
index 45b64f93f358..cc084937f701 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h
@@ -22,6 +22,7 @@
22 22
23struct intel_pt_pkt; 23struct intel_pt_pkt;
24 24
25void *intel_pt_log_fp(void);
25void intel_pt_log_enable(void); 26void intel_pt_log_enable(void);
26void intel_pt_log_disable(void); 27void intel_pt_log_disable(void);
27void intel_pt_log_set_name(const char *name); 28void intel_pt_log_set_name(const char *name);
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index aec68908d604..149ff361ca78 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -206,6 +206,16 @@ static void intel_pt_dump_event(struct intel_pt *pt, unsigned char *buf,
206 intel_pt_dump(pt, buf, len); 206 intel_pt_dump(pt, buf, len);
207} 207}
208 208
209static void intel_pt_log_event(union perf_event *event)
210{
211 FILE *f = intel_pt_log_fp();
212
213 if (!intel_pt_enable_logging || !f)
214 return;
215
216 perf_event__fprintf(event, f);
217}
218
209static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a, 219static int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a,
210 struct auxtrace_buffer *b) 220 struct auxtrace_buffer *b)
211{ 221{
@@ -407,6 +417,13 @@ intel_pt_cache_lookup(struct dso *dso, struct machine *machine, u64 offset)
407 return auxtrace_cache__lookup(dso->auxtrace_cache, offset); 417 return auxtrace_cache__lookup(dso->auxtrace_cache, offset);
408} 418}
409 419
420static inline u8 intel_pt_cpumode(struct intel_pt *pt, uint64_t ip)
421{
422 return ip >= pt->kernel_start ?
423 PERF_RECORD_MISC_KERNEL :
424 PERF_RECORD_MISC_USER;
425}
426
410static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn, 427static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
411 uint64_t *insn_cnt_ptr, uint64_t *ip, 428 uint64_t *insn_cnt_ptr, uint64_t *ip,
412 uint64_t to_ip, uint64_t max_insn_cnt, 429 uint64_t to_ip, uint64_t max_insn_cnt,
@@ -429,10 +446,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
429 if (to_ip && *ip == to_ip) 446 if (to_ip && *ip == to_ip)
430 goto out_no_cache; 447 goto out_no_cache;
431 448
432 if (*ip >= ptq->pt->kernel_start) 449 cpumode = intel_pt_cpumode(ptq->pt, *ip);
433 cpumode = PERF_RECORD_MISC_KERNEL;
434 else
435 cpumode = PERF_RECORD_MISC_USER;
436 450
437 thread = ptq->thread; 451 thread = ptq->thread;
438 if (!thread) { 452 if (!thread) {
@@ -759,7 +773,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
759 if (pt->synth_opts.callchain) { 773 if (pt->synth_opts.callchain) {
760 size_t sz = sizeof(struct ip_callchain); 774 size_t sz = sizeof(struct ip_callchain);
761 775
762 sz += pt->synth_opts.callchain_sz * sizeof(u64); 776 /* Add 1 to callchain_sz for callchain context */
777 sz += (pt->synth_opts.callchain_sz + 1) * sizeof(u64);
763 ptq->chain = zalloc(sz); 778 ptq->chain = zalloc(sz);
764 if (!ptq->chain) 779 if (!ptq->chain)
765 goto out_free; 780 goto out_free;
@@ -908,6 +923,11 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
908 ptq->insn_len = ptq->state->insn_len; 923 ptq->insn_len = ptq->state->insn_len;
909 memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ); 924 memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ);
910 } 925 }
926
927 if (ptq->state->type & INTEL_PT_TRACE_BEGIN)
928 ptq->flags |= PERF_IP_FLAG_TRACE_BEGIN;
929 if (ptq->state->type & INTEL_PT_TRACE_END)
930 ptq->flags |= PERF_IP_FLAG_TRACE_END;
911} 931}
912 932
913static int intel_pt_setup_queue(struct intel_pt *pt, 933static int intel_pt_setup_queue(struct intel_pt *pt,
@@ -1053,15 +1073,11 @@ static void intel_pt_prep_b_sample(struct intel_pt *pt,
1053 union perf_event *event, 1073 union perf_event *event,
1054 struct perf_sample *sample) 1074 struct perf_sample *sample)
1055{ 1075{
1056 event->sample.header.type = PERF_RECORD_SAMPLE;
1057 event->sample.header.misc = PERF_RECORD_MISC_USER;
1058 event->sample.header.size = sizeof(struct perf_event_header);
1059
1060 if (!pt->timeless_decoding) 1076 if (!pt->timeless_decoding)
1061 sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc); 1077 sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
1062 1078
1063 sample->cpumode = PERF_RECORD_MISC_USER;
1064 sample->ip = ptq->state->from_ip; 1079 sample->ip = ptq->state->from_ip;
1080 sample->cpumode = intel_pt_cpumode(pt, sample->ip);
1065 sample->pid = ptq->pid; 1081 sample->pid = ptq->pid;
1066 sample->tid = ptq->tid; 1082 sample->tid = ptq->tid;
1067 sample->addr = ptq->state->to_ip; 1083 sample->addr = ptq->state->to_ip;
@@ -1070,6 +1086,10 @@ static void intel_pt_prep_b_sample(struct intel_pt *pt,
1070 sample->flags = ptq->flags; 1086 sample->flags = ptq->flags;
1071 sample->insn_len = ptq->insn_len; 1087 sample->insn_len = ptq->insn_len;
1072 memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); 1088 memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
1089
1090 event->sample.header.type = PERF_RECORD_SAMPLE;
1091 event->sample.header.misc = sample->cpumode;
1092 event->sample.header.size = sizeof(struct perf_event_header);
1073} 1093}
1074 1094
1075static int intel_pt_inject_event(union perf_event *event, 1095static int intel_pt_inject_event(union perf_event *event,
@@ -1155,7 +1175,8 @@ static void intel_pt_prep_sample(struct intel_pt *pt,
1155 1175
1156 if (pt->synth_opts.callchain) { 1176 if (pt->synth_opts.callchain) {
1157 thread_stack__sample(ptq->thread, ptq->chain, 1177 thread_stack__sample(ptq->thread, ptq->chain,
1158 pt->synth_opts.callchain_sz, sample->ip); 1178 pt->synth_opts.callchain_sz + 1,
1179 sample->ip, pt->kernel_start);
1159 sample->callchain = ptq->chain; 1180 sample->callchain = ptq->chain;
1160 } 1181 }
1161 1182
@@ -1999,9 +2020,9 @@ static int intel_pt_process_event(struct perf_session *session,
1999 event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) 2020 event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)
2000 err = intel_pt_context_switch(pt, event, sample); 2021 err = intel_pt_context_switch(pt, event, sample);
2001 2022
2002 intel_pt_log("event %s (%u): cpu %d time %"PRIu64" tsc %#"PRIx64"\n", 2023 intel_pt_log("event %u: cpu %d time %"PRIu64" tsc %#"PRIx64" ",
2003 perf_event__name(event->header.type), event->header.type, 2024 event->header.type, sample->cpu, sample->time, timestamp);
2004 sample->cpu, sample->time, timestamp); 2025 intel_pt_log_event(event);
2005 2026
2006 return err; 2027 return err;
2007} 2028}
@@ -2554,7 +2575,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2554 if (session->itrace_synth_opts && session->itrace_synth_opts->set) { 2575 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
2555 pt->synth_opts = *session->itrace_synth_opts; 2576 pt->synth_opts = *session->itrace_synth_opts;
2556 } else { 2577 } else {
2557 itrace_synth_opts__set_default(&pt->synth_opts); 2578 itrace_synth_opts__set_default(&pt->synth_opts,
2579 session->itrace_synth_opts->default_no_sample);
2558 if (use_browser != -1) { 2580 if (use_browser != -1) {
2559 pt->synth_opts.branches = false; 2581 pt->synth_opts.branches = false;
2560 pt->synth_opts.callchain = true; 2582 pt->synth_opts.callchain = true;
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 19262f98cd4e..5b0b60f00275 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -19,7 +19,7 @@
19#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ 19#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \
20 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ 20 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
21 "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \ 21 "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \
22 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \ 22 "$CLANG_OPTIONS $PERF_BPF_INC_OPTIONS $KERNEL_INC_OPTIONS " \
23 "-Wno-unused-value -Wno-pointer-sign " \ 23 "-Wno-unused-value -Wno-pointer-sign " \
24 "-working-directory $WORKING_DIR " \ 24 "-working-directory $WORKING_DIR " \
25 "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE" 25 "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index c4acd2001db0..8f36ce813bc5 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1708,6 +1708,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1708 struct thread *parent = machine__findnew_thread(machine, 1708 struct thread *parent = machine__findnew_thread(machine,
1709 event->fork.ppid, 1709 event->fork.ppid,
1710 event->fork.ptid); 1710 event->fork.ptid);
1711 bool do_maps_clone = true;
1711 int err = 0; 1712 int err = 0;
1712 1713
1713 if (dump_trace) 1714 if (dump_trace)
@@ -1736,9 +1737,25 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1736 1737
1737 thread = machine__findnew_thread(machine, event->fork.pid, 1738 thread = machine__findnew_thread(machine, event->fork.pid,
1738 event->fork.tid); 1739 event->fork.tid);
1740 /*
1741 * When synthesizing FORK events, we are trying to create thread
1742 * objects for the already running tasks on the machine.
1743 *
1744 * Normally, for a kernel FORK event, we want to clone the parent's
1745 * maps because that is what the kernel just did.
1746 *
1747 * But when synthesizing, this should not be done. If we do, we end up
1748 * with overlapping maps as we process the sythesized MMAP2 events that
1749 * get delivered shortly thereafter.
1750 *
1751 * Use the FORK event misc flags in an internal way to signal this
1752 * situation, so we can elide the map clone when appropriate.
1753 */
1754 if (event->fork.header.misc & PERF_RECORD_MISC_FORK_EXEC)
1755 do_maps_clone = false;
1739 1756
1740 if (thread == NULL || parent == NULL || 1757 if (thread == NULL || parent == NULL ||
1741 thread__fork(thread, parent, sample->time) < 0) { 1758 thread__fork(thread, parent, sample->time, do_maps_clone) < 0) {
1742 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 1759 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
1743 err = -1; 1760 err = -1;
1744 } 1761 }
@@ -2140,6 +2157,27 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
2140 return 0; 2157 return 0;
2141} 2158}
2142 2159
2160static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,
2161 struct callchain_cursor *cursor,
2162 struct symbol **parent,
2163 struct addr_location *root_al,
2164 u8 *cpumode, int ent)
2165{
2166 int err = 0;
2167
2168 while (--ent >= 0) {
2169 u64 ip = chain->ips[ent];
2170
2171 if (ip >= PERF_CONTEXT_MAX) {
2172 err = add_callchain_ip(thread, cursor, parent,
2173 root_al, cpumode, ip,
2174 false, NULL, NULL, 0);
2175 break;
2176 }
2177 }
2178 return err;
2179}
2180
2143static int thread__resolve_callchain_sample(struct thread *thread, 2181static int thread__resolve_callchain_sample(struct thread *thread,
2144 struct callchain_cursor *cursor, 2182 struct callchain_cursor *cursor,
2145 struct perf_evsel *evsel, 2183 struct perf_evsel *evsel,
@@ -2246,6 +2284,12 @@ static int thread__resolve_callchain_sample(struct thread *thread,
2246 } 2284 }
2247 2285
2248check_calls: 2286check_calls:
2287 if (callchain_param.order != ORDER_CALLEE) {
2288 err = find_prev_cpumode(chain, thread, cursor, parent, root_al,
2289 &cpumode, chain->nr - first_call);
2290 if (err)
2291 return (err < 0) ? err : 0;
2292 }
2249 for (i = first_call, nr_entries = 0; 2293 for (i = first_call, nr_entries = 0;
2250 i < chain_nr && nr_entries < max_stack; i++) { 2294 i < chain_nr && nr_entries < max_stack; i++) {
2251 u64 ip; 2295 u64 ip;
@@ -2260,9 +2304,15 @@ check_calls:
2260 continue; 2304 continue;
2261#endif 2305#endif
2262 ip = chain->ips[j]; 2306 ip = chain->ips[j];
2263
2264 if (ip < PERF_CONTEXT_MAX) 2307 if (ip < PERF_CONTEXT_MAX)
2265 ++nr_entries; 2308 ++nr_entries;
2309 else if (callchain_param.order != ORDER_CALLEE) {
2310 err = find_prev_cpumode(chain, thread, cursor, parent,
2311 root_al, &cpumode, j);
2312 if (err)
2313 return (err < 0) ? err : 0;
2314 continue;
2315 }
2266 2316
2267 err = add_callchain_ip(thread, cursor, parent, 2317 err = add_callchain_ip(thread, cursor, parent,
2268 root_al, &cpumode, ip, 2318 root_al, &cpumode, ip,
@@ -2286,7 +2336,8 @@ static int append_inlines(struct callchain_cursor *cursor,
2286 if (!symbol_conf.inline_name || !map || !sym) 2336 if (!symbol_conf.inline_name || !map || !sym)
2287 return ret; 2337 return ret;
2288 2338
2289 addr = map__rip_2objdump(map, ip); 2339 addr = map__map_ip(map, ip);
2340 addr = map__rip_2objdump(map, addr);
2290 2341
2291 inline_node = inlines__tree_find(&map->dso->inlined_nodes, addr); 2342 inline_node = inlines__tree_find(&map->dso->inlined_nodes, addr);
2292 if (!inline_node) { 2343 if (!inline_node) {
@@ -2312,7 +2363,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
2312{ 2363{
2313 struct callchain_cursor *cursor = arg; 2364 struct callchain_cursor *cursor = arg;
2314 const char *srcline = NULL; 2365 const char *srcline = NULL;
2315 u64 addr; 2366 u64 addr = entry->ip;
2316 2367
2317 if (symbol_conf.hide_unresolved && entry->sym == NULL) 2368 if (symbol_conf.hide_unresolved && entry->sym == NULL)
2318 return 0; 2369 return 0;
@@ -2324,7 +2375,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
2324 * Convert entry->ip from a virtual address to an offset in 2375 * Convert entry->ip from a virtual address to an offset in
2325 * its corresponding binary. 2376 * its corresponding binary.
2326 */ 2377 */
2327 addr = map__map_ip(entry->map, entry->ip); 2378 if (entry->map)
2379 addr = map__map_ip(entry->map, entry->ip);
2328 2380
2329 srcline = callchain_srcline(entry->map, entry->sym, addr); 2381 srcline = callchain_srcline(entry->map, entry->sym, addr);
2330 return callchain_cursor_append(cursor, entry->ip, 2382 return callchain_cursor_append(cursor, entry->ip,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 6a6929f208b4..354e54550d2b 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -320,12 +320,11 @@ int map__load(struct map *map)
320 build_id__sprintf(map->dso->build_id, 320 build_id__sprintf(map->dso->build_id,
321 sizeof(map->dso->build_id), 321 sizeof(map->dso->build_id),
322 sbuild_id); 322 sbuild_id);
323 pr_warning("%s with build id %s not found", 323 pr_debug("%s with build id %s not found", name, sbuild_id);
324 name, sbuild_id);
325 } else 324 } else
326 pr_warning("Failed to open %s", name); 325 pr_debug("Failed to open %s", name);
327 326
328 pr_warning(", continuing without symbols\n"); 327 pr_debug(", continuing without symbols\n");
329 return -1; 328 return -1;
330 } else if (nr == 0) { 329 } else if (nr == 0) {
331#ifdef HAVE_LIBELF_SUPPORT 330#ifdef HAVE_LIBELF_SUPPORT
@@ -334,12 +333,11 @@ int map__load(struct map *map)
334 333
335 if (len > sizeof(DSO__DELETED) && 334 if (len > sizeof(DSO__DELETED) &&
336 strcmp(name + real_len + 1, DSO__DELETED) == 0) { 335 strcmp(name + real_len + 1, DSO__DELETED) == 0) {
337 pr_warning("%.*s was updated (is prelink enabled?). " 336 pr_debug("%.*s was updated (is prelink enabled?). "
338 "Restart the long running apps that use it!\n", 337 "Restart the long running apps that use it!\n",
339 (int)real_len, name); 338 (int)real_len, name);
340 } else { 339 } else {
341 pr_warning("no symbols found in %s, maybe install " 340 pr_debug("no symbols found in %s, maybe install a debug package?\n", name);
342 "a debug package?\n", name);
343 } 341 }
344#endif 342#endif
345 return -1; 343 return -1;
@@ -712,8 +710,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
712 if (verbose >= 2) { 710 if (verbose >= 2) {
713 711
714 if (use_browser) { 712 if (use_browser) {
715 pr_warning("overlapping maps in %s " 713 pr_debug("overlapping maps in %s (disable tui for more info)\n",
716 "(disable tui for more info)\n",
717 map->dso->name); 714 map->dso->name);
718 } else { 715 } else {
719 fputs("overlapping maps:\n", fp); 716 fputs("overlapping maps:\n", fp);
diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
index 215f69f41672..cdb95b3a1213 100644
--- a/tools/perf/util/mmap.c
+++ b/tools/perf/util/mmap.c
@@ -281,7 +281,7 @@ int perf_mmap__read_init(struct perf_mmap *map)
281} 281}
282 282
283int perf_mmap__push(struct perf_mmap *md, void *to, 283int perf_mmap__push(struct perf_mmap *md, void *to,
284 int push(void *to, void *buf, size_t size)) 284 int push(struct perf_mmap *map, void *to, void *buf, size_t size))
285{ 285{
286 u64 head = perf_mmap__read_head(md); 286 u64 head = perf_mmap__read_head(md);
287 unsigned char *data = md->base + page_size; 287 unsigned char *data = md->base + page_size;
@@ -300,7 +300,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to,
300 size = md->mask + 1 - (md->start & md->mask); 300 size = md->mask + 1 - (md->start & md->mask);
301 md->start += size; 301 md->start += size;
302 302
303 if (push(to, buf, size) < 0) { 303 if (push(md, to, buf, size) < 0) {
304 rc = -1; 304 rc = -1;
305 goto out; 305 goto out;
306 } 306 }
@@ -310,7 +310,7 @@ int perf_mmap__push(struct perf_mmap *md, void *to,
310 size = md->end - md->start; 310 size = md->end - md->start;
311 md->start += size; 311 md->start += size;
312 312
313 if (push(to, buf, size) < 0) { 313 if (push(md, to, buf, size) < 0) {
314 rc = -1; 314 rc = -1;
315 goto out; 315 goto out;
316 } 316 }
diff --git a/tools/perf/util/mmap.h b/tools/perf/util/mmap.h
index 05a6d47c7956..cc5e2d6d17a9 100644
--- a/tools/perf/util/mmap.h
+++ b/tools/perf/util/mmap.h
@@ -4,7 +4,7 @@
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <linux/refcount.h> 5#include <linux/refcount.h>
6#include <linux/types.h> 6#include <linux/types.h>
7#include <asm/barrier.h> 7#include <linux/ring_buffer.h>
8#include <stdbool.h> 8#include <stdbool.h>
9#include "auxtrace.h" 9#include "auxtrace.h"
10#include "event.h" 10#include "event.h"
@@ -71,21 +71,12 @@ void perf_mmap__consume(struct perf_mmap *map);
71 71
72static inline u64 perf_mmap__read_head(struct perf_mmap *mm) 72static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
73{ 73{
74 struct perf_event_mmap_page *pc = mm->base; 74 return ring_buffer_read_head(mm->base);
75 u64 head = READ_ONCE(pc->data_head);
76 rmb();
77 return head;
78} 75}
79 76
80static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail) 77static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
81{ 78{
82 struct perf_event_mmap_page *pc = md->base; 79 ring_buffer_write_tail(md->base, tail);
83
84 /*
85 * ensure all reads are done before we write the tail out.
86 */
87 mb();
88 pc->data_tail = tail;
89} 80}
90 81
91union perf_event *perf_mmap__read_forward(struct perf_mmap *map); 82union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
@@ -93,7 +84,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *map);
93union perf_event *perf_mmap__read_event(struct perf_mmap *map); 84union perf_event *perf_mmap__read_event(struct perf_mmap *map);
94 85
95int perf_mmap__push(struct perf_mmap *md, void *to, 86int perf_mmap__push(struct perf_mmap *md, void *to,
96 int push(void *to, void *buf, size_t size)); 87 int push(struct perf_mmap *map, void *to, void *buf, size_t size));
97 88
98size_t perf_mmap__mmap_len(struct perf_mmap *map); 89size_t perf_mmap__mmap_len(struct perf_mmap *map);
99 90
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index bad9e0296e9a..1904e7f6ec84 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -80,14 +80,20 @@ static union perf_event *dup_event(struct ordered_events *oe,
80 return oe->copy_on_queue ? __dup_event(oe, event) : event; 80 return oe->copy_on_queue ? __dup_event(oe, event) : event;
81} 81}
82 82
83static void free_dup_event(struct ordered_events *oe, union perf_event *event) 83static void __free_dup_event(struct ordered_events *oe, union perf_event *event)
84{ 84{
85 if (event && oe->copy_on_queue) { 85 if (event) {
86 oe->cur_alloc_size -= event->header.size; 86 oe->cur_alloc_size -= event->header.size;
87 free(event); 87 free(event);
88 } 88 }
89} 89}
90 90
91static void free_dup_event(struct ordered_events *oe, union perf_event *event)
92{
93 if (oe->copy_on_queue)
94 __free_dup_event(oe, event);
95}
96
91#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event)) 97#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
92static struct ordered_event *alloc_event(struct ordered_events *oe, 98static struct ordered_event *alloc_event(struct ordered_events *oe,
93 union perf_event *event) 99 union perf_event *event)
@@ -95,21 +101,49 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
95 struct list_head *cache = &oe->cache; 101 struct list_head *cache = &oe->cache;
96 struct ordered_event *new = NULL; 102 struct ordered_event *new = NULL;
97 union perf_event *new_event; 103 union perf_event *new_event;
104 size_t size;
98 105
99 new_event = dup_event(oe, event); 106 new_event = dup_event(oe, event);
100 if (!new_event) 107 if (!new_event)
101 return NULL; 108 return NULL;
102 109
110 /*
111 * We maintain the following scheme of buffers for ordered
112 * event allocation:
113 *
114 * to_free list -> buffer1 (64K)
115 * buffer2 (64K)
116 * ...
117 *
118 * Each buffer keeps an array of ordered events objects:
119 * buffer -> event[0]
120 * event[1]
121 * ...
122 *
123 * Each allocated ordered event is linked to one of
124 * following lists:
125 * - time ordered list 'events'
126 * - list of currently removed events 'cache'
127 *
128 * Allocation of the ordered event uses the following order
129 * to get the memory:
130 * - use recently removed object from 'cache' list
131 * - use available object in current allocation buffer
132 * - allocate new buffer if the current buffer is full
133 *
134 * Removal of ordered event object moves it from events to
135 * the cache list.
136 */
137 size = sizeof(*oe->buffer) + MAX_SAMPLE_BUFFER * sizeof(*new);
138
103 if (!list_empty(cache)) { 139 if (!list_empty(cache)) {
104 new = list_entry(cache->next, struct ordered_event, list); 140 new = list_entry(cache->next, struct ordered_event, list);
105 list_del(&new->list); 141 list_del(&new->list);
106 } else if (oe->buffer) { 142 } else if (oe->buffer) {
107 new = oe->buffer + oe->buffer_idx; 143 new = &oe->buffer->event[oe->buffer_idx];
108 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER) 144 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
109 oe->buffer = NULL; 145 oe->buffer = NULL;
110 } else if (oe->cur_alloc_size < oe->max_alloc_size) { 146 } else if ((oe->cur_alloc_size + size) < oe->max_alloc_size) {
111 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
112
113 oe->buffer = malloc(size); 147 oe->buffer = malloc(size);
114 if (!oe->buffer) { 148 if (!oe->buffer) {
115 free_dup_event(oe, new_event); 149 free_dup_event(oe, new_event);
@@ -122,11 +156,11 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
122 oe->cur_alloc_size += size; 156 oe->cur_alloc_size += size;
123 list_add(&oe->buffer->list, &oe->to_free); 157 list_add(&oe->buffer->list, &oe->to_free);
124 158
125 /* First entry is abused to maintain the to_free list. */ 159 oe->buffer_idx = 1;
126 oe->buffer_idx = 2; 160 new = &oe->buffer->event[0];
127 new = oe->buffer + 1;
128 } else { 161 } else {
129 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size); 162 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
163 return NULL;
130 } 164 }
131 165
132 new->event = new_event; 166 new->event = new_event;
@@ -300,15 +334,38 @@ void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t d
300 oe->deliver = deliver; 334 oe->deliver = deliver;
301} 335}
302 336
337static void
338ordered_events_buffer__free(struct ordered_events_buffer *buffer,
339 unsigned int max, struct ordered_events *oe)
340{
341 if (oe->copy_on_queue) {
342 unsigned int i;
343
344 for (i = 0; i < max; i++)
345 __free_dup_event(oe, buffer->event[i].event);
346 }
347
348 free(buffer);
349}
350
303void ordered_events__free(struct ordered_events *oe) 351void ordered_events__free(struct ordered_events *oe)
304{ 352{
305 while (!list_empty(&oe->to_free)) { 353 struct ordered_events_buffer *buffer, *tmp;
306 struct ordered_event *event;
307 354
308 event = list_entry(oe->to_free.next, struct ordered_event, list); 355 if (list_empty(&oe->to_free))
309 list_del(&event->list); 356 return;
310 free_dup_event(oe, event->event); 357
311 free(event); 358 /*
359 * Current buffer might not have all the events allocated
360 * yet, we need to free only allocated ones ...
361 */
362 list_del(&oe->buffer->list);
363 ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
364
365 /* ... and continue with the rest */
366 list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
367 list_del(&buffer->list);
368 ordered_events_buffer__free(buffer, MAX_SAMPLE_BUFFER, oe);
312 } 369 }
313} 370}
314 371
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 8c7a2948593e..1338d5c345dc 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -25,23 +25,28 @@ struct ordered_events;
25typedef int (*ordered_events__deliver_t)(struct ordered_events *oe, 25typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
26 struct ordered_event *event); 26 struct ordered_event *event);
27 27
28struct ordered_events_buffer {
29 struct list_head list;
30 struct ordered_event event[0];
31};
32
28struct ordered_events { 33struct ordered_events {
29 u64 last_flush; 34 u64 last_flush;
30 u64 next_flush; 35 u64 next_flush;
31 u64 max_timestamp; 36 u64 max_timestamp;
32 u64 max_alloc_size; 37 u64 max_alloc_size;
33 u64 cur_alloc_size; 38 u64 cur_alloc_size;
34 struct list_head events; 39 struct list_head events;
35 struct list_head cache; 40 struct list_head cache;
36 struct list_head to_free; 41 struct list_head to_free;
37 struct ordered_event *buffer; 42 struct ordered_events_buffer *buffer;
38 struct ordered_event *last; 43 struct ordered_event *last;
39 ordered_events__deliver_t deliver; 44 ordered_events__deliver_t deliver;
40 int buffer_idx; 45 int buffer_idx;
41 unsigned int nr_events; 46 unsigned int nr_events;
42 enum oe_flush last_flush_type; 47 enum oe_flush last_flush_type;
43 u32 nr_unordered_events; 48 u32 nr_unordered_events;
44 bool copy_on_queue; 49 bool copy_on_queue;
45}; 50};
46 51
47int ordered_events__queue(struct ordered_events *oe, union perf_event *event, 52int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index f8cd3e7c9186..59be3466d64d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -926,6 +926,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
926 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", 926 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit",
927 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", 927 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit",
928 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 928 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack",
929 [PARSE_EVENTS__TERM_TYPE_MAX_EVENTS] = "nr",
929 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 930 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite",
930 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 931 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
931 [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", 932 [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config",
@@ -1037,6 +1038,9 @@ do { \
1037 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1038 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1038 CHECK_TYPE_VAL(NUM); 1039 CHECK_TYPE_VAL(NUM);
1039 break; 1040 break;
1041 case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
1042 CHECK_TYPE_VAL(NUM);
1043 break;
1040 default: 1044 default:
1041 err->str = strdup("unknown term"); 1045 err->str = strdup("unknown term");
1042 err->idx = term->err_term; 1046 err->idx = term->err_term;
@@ -1084,6 +1088,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
1084 case PARSE_EVENTS__TERM_TYPE_INHERIT: 1088 case PARSE_EVENTS__TERM_TYPE_INHERIT:
1085 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1089 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1086 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1090 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1091 case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
1087 case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1092 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1088 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1093 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1089 return config_term_common(attr, term, err); 1094 return config_term_common(attr, term, err);
@@ -1162,6 +1167,9 @@ do { \
1162 case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1167 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1163 ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num); 1168 ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num);
1164 break; 1169 break;
1170 case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
1171 ADD_CONFIG_TERM(MAX_EVENTS, max_events, term->val.num);
1172 break;
1165 case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1173 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1166 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0); 1174 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0);
1167 break; 1175 break;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 4473dac27aee..5ed035cbcbb7 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,6 +71,7 @@ enum {
71 PARSE_EVENTS__TERM_TYPE_NOINHERIT, 71 PARSE_EVENTS__TERM_TYPE_NOINHERIT,
72 PARSE_EVENTS__TERM_TYPE_INHERIT, 72 PARSE_EVENTS__TERM_TYPE_INHERIT,
73 PARSE_EVENTS__TERM_TYPE_MAX_STACK, 73 PARSE_EVENTS__TERM_TYPE_MAX_STACK,
74 PARSE_EVENTS__TERM_TYPE_MAX_EVENTS,
74 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, 75 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
75 PARSE_EVENTS__TERM_TYPE_OVERWRITE, 76 PARSE_EVENTS__TERM_TYPE_OVERWRITE,
76 PARSE_EVENTS__TERM_TYPE_DRV_CFG, 77 PARSE_EVENTS__TERM_TYPE_DRV_CFG,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 5f761f3ed0f3..7805c71aaae2 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -269,6 +269,7 @@ time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
269call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } 269call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
270stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } 270stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
271max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); } 271max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
272nr { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_EVENTS); }
272inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } 273inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
273no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } 274no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
274overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } 275overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index afd68524ffa9..7e49baad304d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -773,7 +773,7 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
773 773
774 if (!is_arm_pmu_core(name)) { 774 if (!is_arm_pmu_core(name)) {
775 pname = pe->pmu ? pe->pmu : "cpu"; 775 pname = pe->pmu ? pe->pmu : "cpu";
776 if (strncmp(pname, name, strlen(pname))) 776 if (strcmp(pname, name))
777 continue; 777 continue;
778 } 778 }
779 779
@@ -930,13 +930,14 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
930 930
931static __u64 pmu_format_max_value(const unsigned long *format) 931static __u64 pmu_format_max_value(const unsigned long *format)
932{ 932{
933 __u64 w = 0; 933 int w;
934 int fbit;
935
936 for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS)
937 w |= (1ULL << fbit);
938 934
939 return w; 935 w = bitmap_weight(format, PERF_PMU_FORMAT_BITS);
936 if (!w)
937 return 0;
938 if (w < 64)
939 return (1ULL << w) - 1;
940 return -1;
940} 941}
941 942
942/* 943/*
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f119eb628dbb..e86f8be89157 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1819,6 +1819,12 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
1819 tp->offset = strtoul(fmt2_str, NULL, 10); 1819 tp->offset = strtoul(fmt2_str, NULL, 10);
1820 } 1820 }
1821 1821
1822 if (tev->uprobes) {
1823 fmt2_str = strchr(p, '(');
1824 if (fmt2_str)
1825 tp->ref_ctr_offset = strtoul(fmt2_str + 1, NULL, 0);
1826 }
1827
1822 tev->nargs = argc - 2; 1828 tev->nargs = argc - 2;
1823 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1829 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1824 if (tev->args == NULL) { 1830 if (tev->args == NULL) {
@@ -2012,6 +2018,22 @@ static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
2012 return err; 2018 return err;
2013} 2019}
2014 2020
2021static int
2022synthesize_uprobe_trace_def(struct probe_trace_event *tev, struct strbuf *buf)
2023{
2024 struct probe_trace_point *tp = &tev->point;
2025 int err;
2026
2027 err = strbuf_addf(buf, "%s:0x%lx", tp->module, tp->address);
2028
2029 if (err >= 0 && tp->ref_ctr_offset) {
2030 if (!uprobe_ref_ctr_is_supported())
2031 return -1;
2032 err = strbuf_addf(buf, "(0x%lx)", tp->ref_ctr_offset);
2033 }
2034 return err >= 0 ? 0 : -1;
2035}
2036
2015char *synthesize_probe_trace_command(struct probe_trace_event *tev) 2037char *synthesize_probe_trace_command(struct probe_trace_event *tev)
2016{ 2038{
2017 struct probe_trace_point *tp = &tev->point; 2039 struct probe_trace_point *tp = &tev->point;
@@ -2041,15 +2063,17 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
2041 } 2063 }
2042 2064
2043 /* Use the tp->address for uprobes */ 2065 /* Use the tp->address for uprobes */
2044 if (tev->uprobes) 2066 if (tev->uprobes) {
2045 err = strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address); 2067 err = synthesize_uprobe_trace_def(tev, &buf);
2046 else if (!strncmp(tp->symbol, "0x", 2)) 2068 } else if (!strncmp(tp->symbol, "0x", 2)) {
2047 /* Absolute address. See try_to_find_absolute_address() */ 2069 /* Absolute address. See try_to_find_absolute_address() */
2048 err = strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "", 2070 err = strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "",
2049 tp->module ? ":" : "", tp->address); 2071 tp->module ? ":" : "", tp->address);
2050 else 2072 } else {
2051 err = strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "", 2073 err = strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
2052 tp->module ? ":" : "", tp->symbol, tp->offset); 2074 tp->module ? ":" : "", tp->symbol, tp->offset);
2075 }
2076
2053 if (err) 2077 if (err)
2054 goto error; 2078 goto error;
2055 2079
@@ -2633,6 +2657,13 @@ static void warn_uprobe_event_compat(struct probe_trace_event *tev)
2633{ 2657{
2634 int i; 2658 int i;
2635 char *buf = synthesize_probe_trace_command(tev); 2659 char *buf = synthesize_probe_trace_command(tev);
2660 struct probe_trace_point *tp = &tev->point;
2661
2662 if (tp->ref_ctr_offset && !uprobe_ref_ctr_is_supported()) {
2663 pr_warning("A semaphore is associated with %s:%s and "
2664 "seems your kernel doesn't support it.\n",
2665 tev->group, tev->event);
2666 }
2636 2667
2637 /* Old uprobe event doesn't support memory dereference */ 2668 /* Old uprobe event doesn't support memory dereference */
2638 if (!tev->uprobes || tev->nargs == 0 || !buf) 2669 if (!tev->uprobes || tev->nargs == 0 || !buf)
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 45b14f020558..15a98c3a2a2f 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -27,6 +27,7 @@ struct probe_trace_point {
27 char *symbol; /* Base symbol */ 27 char *symbol; /* Base symbol */
28 char *module; /* Module name */ 28 char *module; /* Module name */
29 unsigned long offset; /* Offset from symbol */ 29 unsigned long offset; /* Offset from symbol */
30 unsigned long ref_ctr_offset; /* SDT reference counter offset */
30 unsigned long address; /* Actual address of the trace point */ 31 unsigned long address; /* Actual address of the trace point */
31 bool retprobe; /* Return probe flag */ 32 bool retprobe; /* Return probe flag */
32}; 33};
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index b76088fadf3d..aac7817d9e14 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -696,8 +696,16 @@ out_err:
696#ifdef HAVE_GELF_GETNOTE_SUPPORT 696#ifdef HAVE_GELF_GETNOTE_SUPPORT
697static unsigned long long sdt_note__get_addr(struct sdt_note *note) 697static unsigned long long sdt_note__get_addr(struct sdt_note *note)
698{ 698{
699 return note->bit32 ? (unsigned long long)note->addr.a32[0] 699 return note->bit32 ?
700 : (unsigned long long)note->addr.a64[0]; 700 (unsigned long long)note->addr.a32[SDT_NOTE_IDX_LOC] :
701 (unsigned long long)note->addr.a64[SDT_NOTE_IDX_LOC];
702}
703
704static unsigned long long sdt_note__get_ref_ctr_offset(struct sdt_note *note)
705{
706 return note->bit32 ?
707 (unsigned long long)note->addr.a32[SDT_NOTE_IDX_REFCTR] :
708 (unsigned long long)note->addr.a64[SDT_NOTE_IDX_REFCTR];
701} 709}
702 710
703static const char * const type_to_suffix[] = { 711static const char * const type_to_suffix[] = {
@@ -775,14 +783,21 @@ static char *synthesize_sdt_probe_command(struct sdt_note *note,
775{ 783{
776 struct strbuf buf; 784 struct strbuf buf;
777 char *ret = NULL, **args; 785 char *ret = NULL, **args;
778 int i, args_count; 786 int i, args_count, err;
787 unsigned long long ref_ctr_offset;
779 788
780 if (strbuf_init(&buf, 32) < 0) 789 if (strbuf_init(&buf, 32) < 0)
781 return NULL; 790 return NULL;
782 791
783 if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx", 792 err = strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
784 sdtgrp, note->name, pathname, 793 sdtgrp, note->name, pathname,
785 sdt_note__get_addr(note)) < 0) 794 sdt_note__get_addr(note));
795
796 ref_ctr_offset = sdt_note__get_ref_ctr_offset(note);
797 if (ref_ctr_offset && err >= 0)
798 err = strbuf_addf(&buf, "(0x%llx)", ref_ctr_offset);
799
800 if (err < 0)
786 goto error; 801 goto error;
787 802
788 if (!note->args) 803 if (!note->args)
@@ -998,6 +1013,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)
998enum ftrace_readme { 1013enum ftrace_readme {
999 FTRACE_README_PROBE_TYPE_X = 0, 1014 FTRACE_README_PROBE_TYPE_X = 0,
1000 FTRACE_README_KRETPROBE_OFFSET, 1015 FTRACE_README_KRETPROBE_OFFSET,
1016 FTRACE_README_UPROBE_REF_CTR,
1001 FTRACE_README_END, 1017 FTRACE_README_END,
1002}; 1018};
1003 1019
@@ -1009,6 +1025,7 @@ static struct {
1009 [idx] = {.pattern = pat, .avail = false} 1025 [idx] = {.pattern = pat, .avail = false}
1010 DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"), 1026 DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
1011 DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"), 1027 DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
1028 DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR, "*ref_ctr_offset*"),
1012}; 1029};
1013 1030
1014static bool scan_ftrace_readme(enum ftrace_readme type) 1031static bool scan_ftrace_readme(enum ftrace_readme type)
@@ -1064,3 +1081,8 @@ bool kretprobe_offset_is_supported(void)
1064{ 1081{
1065 return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET); 1082 return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET);
1066} 1083}
1084
1085bool uprobe_ref_ctr_is_supported(void)
1086{
1087 return scan_ftrace_readme(FTRACE_README_UPROBE_REF_CTR);
1088}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 63f29b1d22c1..2a249182f2a6 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -69,6 +69,7 @@ struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
69int probe_cache__show_all_caches(struct strfilter *filter); 69int probe_cache__show_all_caches(struct strfilter *filter);
70bool probe_type_is_available(enum probe_type type); 70bool probe_type_is_available(enum probe_type type);
71bool kretprobe_offset_is_supported(void); 71bool kretprobe_offset_is_supported(void);
72bool uprobe_ref_ctr_is_supported(void);
72#else /* ! HAVE_LIBELF_SUPPORT */ 73#else /* ! HAVE_LIBELF_SUPPORT */
73static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused, struct nsinfo *nsi __maybe_unused) 74static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused, struct nsinfo *nsi __maybe_unused)
74{ 75{
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index ce501ba14b08..50150dfc0cdf 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -340,7 +340,7 @@ static bool is_tracepoint(struct pyrf_event *pevent)
340} 340}
341 341
342static PyObject* 342static PyObject*
343tracepoint_field(struct pyrf_event *pe, struct format_field *field) 343tracepoint_field(struct pyrf_event *pe, struct tep_format_field *field)
344{ 344{
345 struct tep_handle *pevent = field->event->pevent; 345 struct tep_handle *pevent = field->event->pevent;
346 void *data = pe->sample.raw_data; 346 void *data = pe->sample.raw_data;
@@ -348,28 +348,28 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
348 unsigned long long val; 348 unsigned long long val;
349 unsigned int offset, len; 349 unsigned int offset, len;
350 350
351 if (field->flags & FIELD_IS_ARRAY) { 351 if (field->flags & TEP_FIELD_IS_ARRAY) {
352 offset = field->offset; 352 offset = field->offset;
353 len = field->size; 353 len = field->size;
354 if (field->flags & FIELD_IS_DYNAMIC) { 354 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
355 val = tep_read_number(pevent, data + offset, len); 355 val = tep_read_number(pevent, data + offset, len);
356 offset = val; 356 offset = val;
357 len = offset >> 16; 357 len = offset >> 16;
358 offset &= 0xffff; 358 offset &= 0xffff;
359 } 359 }
360 if (field->flags & FIELD_IS_STRING && 360 if (field->flags & TEP_FIELD_IS_STRING &&
361 is_printable_array(data + offset, len)) { 361 is_printable_array(data + offset, len)) {
362 ret = _PyUnicode_FromString((char *)data + offset); 362 ret = _PyUnicode_FromString((char *)data + offset);
363 } else { 363 } else {
364 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); 364 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
365 field->flags &= ~FIELD_IS_STRING; 365 field->flags &= ~TEP_FIELD_IS_STRING;
366 } 366 }
367 } else { 367 } else {
368 val = tep_read_number(pevent, data + field->offset, 368 val = tep_read_number(pevent, data + field->offset,
369 field->size); 369 field->size);
370 if (field->flags & FIELD_IS_POINTER) 370 if (field->flags & TEP_FIELD_IS_POINTER)
371 ret = PyLong_FromUnsignedLong((unsigned long) val); 371 ret = PyLong_FromUnsignedLong((unsigned long) val);
372 else if (field->flags & FIELD_IS_SIGNED) 372 else if (field->flags & TEP_FIELD_IS_SIGNED)
373 ret = PyLong_FromLong((long) val); 373 ret = PyLong_FromLong((long) val);
374 else 374 else
375 ret = PyLong_FromUnsignedLong((unsigned long) val); 375 ret = PyLong_FromUnsignedLong((unsigned long) val);
@@ -383,10 +383,10 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
383{ 383{
384 const char *str = _PyUnicode_AsString(PyObject_Str(attr_name)); 384 const char *str = _PyUnicode_AsString(PyObject_Str(attr_name));
385 struct perf_evsel *evsel = pevent->evsel; 385 struct perf_evsel *evsel = pevent->evsel;
386 struct format_field *field; 386 struct tep_format_field *field;
387 387
388 if (!evsel->tp_format) { 388 if (!evsel->tp_format) {
389 struct event_format *tp_format; 389 struct tep_event_format *tp_format;
390 390
391 tp_format = trace_event__tp_format_id(evsel->attr.config); 391 tp_format = trace_event__tp_format_id(evsel->attr.config);
392 if (!tp_format) 392 if (!tp_format)
@@ -1240,7 +1240,7 @@ static struct {
1240static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, 1240static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
1241 PyObject *args, PyObject *kwargs) 1241 PyObject *args, PyObject *kwargs)
1242{ 1242{
1243 struct event_format *tp_format; 1243 struct tep_event_format *tp_format;
1244 static char *kwlist[] = { "sys", "name", NULL }; 1244 static char *kwlist[] = { "sys", "name", NULL };
1245 char *sys = NULL; 1245 char *sys = NULL;
1246 char *name = NULL; 1246 char *name = NULL;
diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c
index d2c78ffd9fee..a2eeebbfb25f 100644
--- a/tools/perf/util/s390-cpumsf.c
+++ b/tools/perf/util/s390-cpumsf.c
@@ -147,6 +147,9 @@
147#include <linux/bitops.h> 147#include <linux/bitops.h>
148#include <linux/log2.h> 148#include <linux/log2.h>
149 149
150#include <sys/stat.h>
151#include <sys/types.h>
152
150#include "cpumap.h" 153#include "cpumap.h"
151#include "color.h" 154#include "color.h"
152#include "evsel.h" 155#include "evsel.h"
@@ -159,6 +162,7 @@
159#include "auxtrace.h" 162#include "auxtrace.h"
160#include "s390-cpumsf.h" 163#include "s390-cpumsf.h"
161#include "s390-cpumsf-kernel.h" 164#include "s390-cpumsf-kernel.h"
165#include "config.h"
162 166
163struct s390_cpumsf { 167struct s390_cpumsf {
164 struct auxtrace auxtrace; 168 struct auxtrace auxtrace;
@@ -170,6 +174,8 @@ struct s390_cpumsf {
170 u32 pmu_type; 174 u32 pmu_type;
171 u16 machine_type; 175 u16 machine_type;
172 bool data_queued; 176 bool data_queued;
177 bool use_logfile;
178 char *logdir;
173}; 179};
174 180
175struct s390_cpumsf_queue { 181struct s390_cpumsf_queue {
@@ -177,6 +183,7 @@ struct s390_cpumsf_queue {
177 unsigned int queue_nr; 183 unsigned int queue_nr;
178 struct auxtrace_buffer *buffer; 184 struct auxtrace_buffer *buffer;
179 int cpu; 185 int cpu;
186 FILE *logfile;
180}; 187};
181 188
182/* Display s390 CPU measurement facility basic-sampling data entry */ 189/* Display s390 CPU measurement facility basic-sampling data entry */
@@ -595,6 +602,12 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
595 buffer->use_size = buffer->size; 602 buffer->use_size = buffer->size;
596 buffer->use_data = buffer->data; 603 buffer->use_data = buffer->data;
597 } 604 }
605 if (sfq->logfile) { /* Write into log file */
606 size_t rc = fwrite(buffer->data, buffer->size, 1,
607 sfq->logfile);
608 if (rc != 1)
609 pr_err("Failed to write auxiliary data\n");
610 }
598 } else 611 } else
599 buffer = sfq->buffer; 612 buffer = sfq->buffer;
600 613
@@ -606,6 +619,13 @@ static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
606 return -ENOMEM; 619 return -ENOMEM;
607 buffer->use_size = buffer->size; 620 buffer->use_size = buffer->size;
608 buffer->use_data = buffer->data; 621 buffer->use_data = buffer->data;
622
623 if (sfq->logfile) { /* Write into log file */
624 size_t rc = fwrite(buffer->data, buffer->size, 1,
625 sfq->logfile);
626 if (rc != 1)
627 pr_err("Failed to write auxiliary data\n");
628 }
609 } 629 }
610 pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n", 630 pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n",
611 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset, 631 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset,
@@ -640,6 +660,23 @@ s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr)
640 sfq->sf = sf; 660 sfq->sf = sf;
641 sfq->queue_nr = queue_nr; 661 sfq->queue_nr = queue_nr;
642 sfq->cpu = -1; 662 sfq->cpu = -1;
663 if (sf->use_logfile) {
664 char *name;
665 int rc;
666
667 rc = (sf->logdir)
668 ? asprintf(&name, "%s/aux.smp.%02x",
669 sf->logdir, queue_nr)
670 : asprintf(&name, "aux.smp.%02x", queue_nr);
671 if (rc > 0)
672 sfq->logfile = fopen(name, "w");
673 if (sfq->logfile == NULL) {
674 pr_err("Failed to open auxiliary log file %s,"
675 "continue...\n", name);
676 sf->use_logfile = false;
677 }
678 free(name);
679 }
643 return sfq; 680 return sfq;
644} 681}
645 682
@@ -850,8 +887,16 @@ static void s390_cpumsf_free_queues(struct perf_session *session)
850 struct auxtrace_queues *queues = &sf->queues; 887 struct auxtrace_queues *queues = &sf->queues;
851 unsigned int i; 888 unsigned int i;
852 889
853 for (i = 0; i < queues->nr_queues; i++) 890 for (i = 0; i < queues->nr_queues; i++) {
891 struct s390_cpumsf_queue *sfq = (struct s390_cpumsf_queue *)
892 queues->queue_array[i].priv;
893
894 if (sfq != NULL && sfq->logfile) {
895 fclose(sfq->logfile);
896 sfq->logfile = NULL;
897 }
854 zfree(&queues->queue_array[i].priv); 898 zfree(&queues->queue_array[i].priv);
899 }
855 auxtrace_queues__free(queues); 900 auxtrace_queues__free(queues);
856} 901}
857 902
@@ -864,6 +909,7 @@ static void s390_cpumsf_free(struct perf_session *session)
864 auxtrace_heap__free(&sf->heap); 909 auxtrace_heap__free(&sf->heap);
865 s390_cpumsf_free_queues(session); 910 s390_cpumsf_free_queues(session);
866 session->auxtrace = NULL; 911 session->auxtrace = NULL;
912 free(sf->logdir);
867 free(sf); 913 free(sf);
868} 914}
869 915
@@ -877,17 +923,55 @@ static int s390_cpumsf_get_type(const char *cpuid)
877 923
878/* Check itrace options set on perf report command. 924/* Check itrace options set on perf report command.
879 * Return true, if none are set or all options specified can be 925 * Return true, if none are set or all options specified can be
880 * handled on s390. 926 * handled on s390 (currently only option 'd' for logging.
881 * Return false otherwise. 927 * Return false otherwise.
882 */ 928 */
883static bool check_auxtrace_itrace(struct itrace_synth_opts *itops) 929static bool check_auxtrace_itrace(struct itrace_synth_opts *itops)
884{ 930{
931 bool ison = false;
932
885 if (!itops || !itops->set) 933 if (!itops || !itops->set)
886 return true; 934 return true;
887 pr_err("No --itrace options supported\n"); 935 ison = itops->inject || itops->instructions || itops->branches ||
936 itops->transactions || itops->ptwrites ||
937 itops->pwr_events || itops->errors ||
938 itops->dont_decode || itops->calls || itops->returns ||
939 itops->callchain || itops->thread_stack ||
940 itops->last_branch;
941 if (!ison)
942 return true;
943 pr_err("Unsupported --itrace options specified\n");
888 return false; 944 return false;
889} 945}
890 946
947/* Check for AUXTRACE dump directory if it is needed.
948 * On failure print an error message but continue.
949 * Return 0 on wrong keyword in config file and 1 otherwise.
950 */
951static int s390_cpumsf__config(const char *var, const char *value, void *cb)
952{
953 struct s390_cpumsf *sf = cb;
954 struct stat stbuf;
955 int rc;
956
957 if (strcmp(var, "auxtrace.dumpdir"))
958 return 0;
959 sf->logdir = strdup(value);
960 if (sf->logdir == NULL) {
961 pr_err("Failed to find auxtrace log directory %s,"
962 " continue with current directory...\n", value);
963 return 1;
964 }
965 rc = stat(sf->logdir, &stbuf);
966 if (rc == -1 || !S_ISDIR(stbuf.st_mode)) {
967 pr_err("Missing auxtrace log directory %s,"
968 " continue with current directory...\n", value);
969 free(sf->logdir);
970 sf->logdir = NULL;
971 }
972 return 1;
973}
974
891int s390_cpumsf_process_auxtrace_info(union perf_event *event, 975int s390_cpumsf_process_auxtrace_info(union perf_event *event,
892 struct perf_session *session) 976 struct perf_session *session)
893{ 977{
@@ -906,6 +990,9 @@ int s390_cpumsf_process_auxtrace_info(union perf_event *event,
906 err = -EINVAL; 990 err = -EINVAL;
907 goto err_free; 991 goto err_free;
908 } 992 }
993 sf->use_logfile = session->itrace_synth_opts->log;
994 if (sf->use_logfile)
995 perf_config(s390_cpumsf__config, sf);
909 996
910 err = auxtrace_queues__init(&sf->queues); 997 err = auxtrace_queues__init(&sf->queues);
911 if (err) 998 if (err)
@@ -940,6 +1027,7 @@ err_free_queues:
940 auxtrace_queues__free(&sf->queues); 1027 auxtrace_queues__free(&sf->queues);
941 session->auxtrace = NULL; 1028 session->auxtrace = NULL;
942err_free: 1029err_free:
1030 free(sf->logdir);
943 free(sf); 1031 free(sf);
944 return err; 1032 return err;
945} 1033}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 45484f0f7292..89cb887648f9 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -99,7 +99,7 @@ static void define_symbolic_value(const char *ev_name,
99 LEAVE; 99 LEAVE;
100} 100}
101 101
102static void define_symbolic_values(struct print_flag_sym *field, 102static void define_symbolic_values(struct tep_print_flag_sym *field,
103 const char *ev_name, 103 const char *ev_name,
104 const char *field_name) 104 const char *field_name)
105{ 105{
@@ -157,7 +157,7 @@ static void define_flag_value(const char *ev_name,
157 LEAVE; 157 LEAVE;
158} 158}
159 159
160static void define_flag_values(struct print_flag_sym *field, 160static void define_flag_values(struct tep_print_flag_sym *field,
161 const char *ev_name, 161 const char *ev_name,
162 const char *field_name) 162 const char *field_name)
163{ 163{
@@ -189,62 +189,62 @@ static void define_flag_field(const char *ev_name,
189 LEAVE; 189 LEAVE;
190} 190}
191 191
192static void define_event_symbols(struct event_format *event, 192static void define_event_symbols(struct tep_event_format *event,
193 const char *ev_name, 193 const char *ev_name,
194 struct print_arg *args) 194 struct tep_print_arg *args)
195{ 195{
196 if (args == NULL) 196 if (args == NULL)
197 return; 197 return;
198 198
199 switch (args->type) { 199 switch (args->type) {
200 case PRINT_NULL: 200 case TEP_PRINT_NULL:
201 break; 201 break;
202 case PRINT_ATOM: 202 case TEP_PRINT_ATOM:
203 define_flag_value(ev_name, cur_field_name, "0", 203 define_flag_value(ev_name, cur_field_name, "0",
204 args->atom.atom); 204 args->atom.atom);
205 zero_flag_atom = 0; 205 zero_flag_atom = 0;
206 break; 206 break;
207 case PRINT_FIELD: 207 case TEP_PRINT_FIELD:
208 free(cur_field_name); 208 free(cur_field_name);
209 cur_field_name = strdup(args->field.name); 209 cur_field_name = strdup(args->field.name);
210 break; 210 break;
211 case PRINT_FLAGS: 211 case TEP_PRINT_FLAGS:
212 define_event_symbols(event, ev_name, args->flags.field); 212 define_event_symbols(event, ev_name, args->flags.field);
213 define_flag_field(ev_name, cur_field_name, args->flags.delim); 213 define_flag_field(ev_name, cur_field_name, args->flags.delim);
214 define_flag_values(args->flags.flags, ev_name, cur_field_name); 214 define_flag_values(args->flags.flags, ev_name, cur_field_name);
215 break; 215 break;
216 case PRINT_SYMBOL: 216 case TEP_PRINT_SYMBOL:
217 define_event_symbols(event, ev_name, args->symbol.field); 217 define_event_symbols(event, ev_name, args->symbol.field);
218 define_symbolic_field(ev_name, cur_field_name); 218 define_symbolic_field(ev_name, cur_field_name);
219 define_symbolic_values(args->symbol.symbols, ev_name, 219 define_symbolic_values(args->symbol.symbols, ev_name,
220 cur_field_name); 220 cur_field_name);
221 break; 221 break;
222 case PRINT_HEX: 222 case TEP_PRINT_HEX:
223 case PRINT_HEX_STR: 223 case TEP_PRINT_HEX_STR:
224 define_event_symbols(event, ev_name, args->hex.field); 224 define_event_symbols(event, ev_name, args->hex.field);
225 define_event_symbols(event, ev_name, args->hex.size); 225 define_event_symbols(event, ev_name, args->hex.size);
226 break; 226 break;
227 case PRINT_INT_ARRAY: 227 case TEP_PRINT_INT_ARRAY:
228 define_event_symbols(event, ev_name, args->int_array.field); 228 define_event_symbols(event, ev_name, args->int_array.field);
229 define_event_symbols(event, ev_name, args->int_array.count); 229 define_event_symbols(event, ev_name, args->int_array.count);
230 define_event_symbols(event, ev_name, args->int_array.el_size); 230 define_event_symbols(event, ev_name, args->int_array.el_size);
231 break; 231 break;
232 case PRINT_BSTRING: 232 case TEP_PRINT_BSTRING:
233 case PRINT_DYNAMIC_ARRAY: 233 case TEP_PRINT_DYNAMIC_ARRAY:
234 case PRINT_DYNAMIC_ARRAY_LEN: 234 case TEP_PRINT_DYNAMIC_ARRAY_LEN:
235 case PRINT_STRING: 235 case TEP_PRINT_STRING:
236 case PRINT_BITMASK: 236 case TEP_PRINT_BITMASK:
237 break; 237 break;
238 case PRINT_TYPE: 238 case TEP_PRINT_TYPE:
239 define_event_symbols(event, ev_name, args->typecast.item); 239 define_event_symbols(event, ev_name, args->typecast.item);
240 break; 240 break;
241 case PRINT_OP: 241 case TEP_PRINT_OP:
242 if (strcmp(args->op.op, ":") == 0) 242 if (strcmp(args->op.op, ":") == 0)
243 zero_flag_atom = 1; 243 zero_flag_atom = 1;
244 define_event_symbols(event, ev_name, args->op.left); 244 define_event_symbols(event, ev_name, args->op.left);
245 define_event_symbols(event, ev_name, args->op.right); 245 define_event_symbols(event, ev_name, args->op.right);
246 break; 246 break;
247 case PRINT_FUNC: 247 case TEP_PRINT_FUNC:
248 default: 248 default:
249 pr_err("Unsupported print arg type\n"); 249 pr_err("Unsupported print arg type\n");
250 /* we should warn... */ 250 /* we should warn... */
@@ -338,8 +338,8 @@ static void perl_process_tracepoint(struct perf_sample *sample,
338 struct addr_location *al) 338 struct addr_location *al)
339{ 339{
340 struct thread *thread = al->thread; 340 struct thread *thread = al->thread;
341 struct event_format *event = evsel->tp_format; 341 struct tep_event_format *event = evsel->tp_format;
342 struct format_field *field; 342 struct tep_format_field *field;
343 static char handler[256]; 343 static char handler[256];
344 unsigned long long val; 344 unsigned long long val;
345 unsigned long s, ns; 345 unsigned long s, ns;
@@ -388,9 +388,9 @@ static void perl_process_tracepoint(struct perf_sample *sample,
388 /* common fields other than pid can be accessed via xsub fns */ 388 /* common fields other than pid can be accessed via xsub fns */
389 389
390 for (field = event->format.fields; field; field = field->next) { 390 for (field = event->format.fields; field; field = field->next) {
391 if (field->flags & FIELD_IS_STRING) { 391 if (field->flags & TEP_FIELD_IS_STRING) {
392 int offset; 392 int offset;
393 if (field->flags & FIELD_IS_DYNAMIC) { 393 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
394 offset = *(int *)(data + field->offset); 394 offset = *(int *)(data + field->offset);
395 offset &= 0xffff; 395 offset &= 0xffff;
396 } else 396 } else
@@ -399,7 +399,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
399 } else { /* FIELD_IS_NUMERIC */ 399 } else { /* FIELD_IS_NUMERIC */
400 val = read_size(event, data + field->offset, 400 val = read_size(event, data + field->offset,
401 field->size); 401 field->size);
402 if (field->flags & FIELD_IS_SIGNED) { 402 if (field->flags & TEP_FIELD_IS_SIGNED) {
403 XPUSHs(sv_2mortal(newSViv(val))); 403 XPUSHs(sv_2mortal(newSViv(val)));
404 } else { 404 } else {
405 XPUSHs(sv_2mortal(newSVuv(val))); 405 XPUSHs(sv_2mortal(newSVuv(val)));
@@ -537,8 +537,8 @@ static int perl_stop_script(void)
537 537
538static int perl_generate_script(struct tep_handle *pevent, const char *outfile) 538static int perl_generate_script(struct tep_handle *pevent, const char *outfile)
539{ 539{
540 struct event_format *event = NULL; 540 struct tep_event_format *event = NULL;
541 struct format_field *f; 541 struct tep_format_field *f;
542 char fname[PATH_MAX]; 542 char fname[PATH_MAX];
543 int not_first, count; 543 int not_first, count;
544 FILE *ofp; 544 FILE *ofp;
@@ -646,11 +646,11 @@ sub print_backtrace\n\
646 count++; 646 count++;
647 647
648 fprintf(ofp, "%s=", f->name); 648 fprintf(ofp, "%s=", f->name);
649 if (f->flags & FIELD_IS_STRING || 649 if (f->flags & TEP_FIELD_IS_STRING ||
650 f->flags & FIELD_IS_FLAG || 650 f->flags & TEP_FIELD_IS_FLAG ||
651 f->flags & FIELD_IS_SYMBOLIC) 651 f->flags & TEP_FIELD_IS_SYMBOLIC)
652 fprintf(ofp, "%%s"); 652 fprintf(ofp, "%%s");
653 else if (f->flags & FIELD_IS_SIGNED) 653 else if (f->flags & TEP_FIELD_IS_SIGNED)
654 fprintf(ofp, "%%d"); 654 fprintf(ofp, "%%d");
655 else 655 else
656 fprintf(ofp, "%%u"); 656 fprintf(ofp, "%%u");
@@ -668,7 +668,7 @@ sub print_backtrace\n\
668 if (++count % 5 == 0) 668 if (++count % 5 == 0)
669 fprintf(ofp, "\n\t "); 669 fprintf(ofp, "\n\t ");
670 670
671 if (f->flags & FIELD_IS_FLAG) { 671 if (f->flags & TEP_FIELD_IS_FLAG) {
672 if ((count - 1) % 5 != 0) { 672 if ((count - 1) % 5 != 0) {
673 fprintf(ofp, "\n\t "); 673 fprintf(ofp, "\n\t ");
674 count = 4; 674 count = 4;
@@ -678,7 +678,7 @@ sub print_backtrace\n\
678 event->name); 678 event->name);
679 fprintf(ofp, "\"%s\", $%s)", f->name, 679 fprintf(ofp, "\"%s\", $%s)", f->name,
680 f->name); 680 f->name);
681 } else if (f->flags & FIELD_IS_SYMBOLIC) { 681 } else if (f->flags & TEP_FIELD_IS_SYMBOLIC) {
682 if ((count - 1) % 5 != 0) { 682 if ((count - 1) % 5 != 0) {
683 fprintf(ofp, "\n\t "); 683 fprintf(ofp, "\n\t ");
684 count = 4; 684 count = 4;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index dfc6093f118c..69aa93d4ee99 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -193,7 +193,7 @@ static void try_call_object(const char *handler_name, PyObject *args)
193 call_object(handler, args, handler_name); 193 call_object(handler, args, handler_name);
194} 194}
195 195
196static void define_value(enum print_arg_type field_type, 196static void define_value(enum tep_print_arg_type field_type,
197 const char *ev_name, 197 const char *ev_name,
198 const char *field_name, 198 const char *field_name,
199 const char *field_value, 199 const char *field_value,
@@ -204,7 +204,7 @@ static void define_value(enum print_arg_type field_type,
204 unsigned long long value; 204 unsigned long long value;
205 unsigned n = 0; 205 unsigned n = 0;
206 206
207 if (field_type == PRINT_SYMBOL) 207 if (field_type == TEP_PRINT_SYMBOL)
208 handler_name = "define_symbolic_value"; 208 handler_name = "define_symbolic_value";
209 209
210 t = PyTuple_New(4); 210 t = PyTuple_New(4);
@@ -223,8 +223,8 @@ static void define_value(enum print_arg_type field_type,
223 Py_DECREF(t); 223 Py_DECREF(t);
224} 224}
225 225
226static void define_values(enum print_arg_type field_type, 226static void define_values(enum tep_print_arg_type field_type,
227 struct print_flag_sym *field, 227 struct tep_print_flag_sym *field,
228 const char *ev_name, 228 const char *ev_name,
229 const char *field_name) 229 const char *field_name)
230{ 230{
@@ -235,7 +235,7 @@ static void define_values(enum print_arg_type field_type,
235 define_values(field_type, field->next, ev_name, field_name); 235 define_values(field_type, field->next, ev_name, field_name);
236} 236}
237 237
238static void define_field(enum print_arg_type field_type, 238static void define_field(enum tep_print_arg_type field_type,
239 const char *ev_name, 239 const char *ev_name,
240 const char *field_name, 240 const char *field_name,
241 const char *delim) 241 const char *delim)
@@ -244,10 +244,10 @@ static void define_field(enum print_arg_type field_type,
244 PyObject *t; 244 PyObject *t;
245 unsigned n = 0; 245 unsigned n = 0;
246 246
247 if (field_type == PRINT_SYMBOL) 247 if (field_type == TEP_PRINT_SYMBOL)
248 handler_name = "define_symbolic_field"; 248 handler_name = "define_symbolic_field";
249 249
250 if (field_type == PRINT_FLAGS) 250 if (field_type == TEP_PRINT_FLAGS)
251 t = PyTuple_New(3); 251 t = PyTuple_New(3);
252 else 252 else
253 t = PyTuple_New(2); 253 t = PyTuple_New(2);
@@ -256,7 +256,7 @@ static void define_field(enum print_arg_type field_type,
256 256
257 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); 257 PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
258 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); 258 PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
259 if (field_type == PRINT_FLAGS) 259 if (field_type == TEP_PRINT_FLAGS)
260 PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); 260 PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim));
261 261
262 try_call_object(handler_name, t); 262 try_call_object(handler_name, t);
@@ -264,54 +264,54 @@ static void define_field(enum print_arg_type field_type,
264 Py_DECREF(t); 264 Py_DECREF(t);
265} 265}
266 266
267static void define_event_symbols(struct event_format *event, 267static void define_event_symbols(struct tep_event_format *event,
268 const char *ev_name, 268 const char *ev_name,
269 struct print_arg *args) 269 struct tep_print_arg *args)
270{ 270{
271 if (args == NULL) 271 if (args == NULL)
272 return; 272 return;
273 273
274 switch (args->type) { 274 switch (args->type) {
275 case PRINT_NULL: 275 case TEP_PRINT_NULL:
276 break; 276 break;
277 case PRINT_ATOM: 277 case TEP_PRINT_ATOM:
278 define_value(PRINT_FLAGS, ev_name, cur_field_name, "0", 278 define_value(TEP_PRINT_FLAGS, ev_name, cur_field_name, "0",
279 args->atom.atom); 279 args->atom.atom);
280 zero_flag_atom = 0; 280 zero_flag_atom = 0;
281 break; 281 break;
282 case PRINT_FIELD: 282 case TEP_PRINT_FIELD:
283 free(cur_field_name); 283 free(cur_field_name);
284 cur_field_name = strdup(args->field.name); 284 cur_field_name = strdup(args->field.name);
285 break; 285 break;
286 case PRINT_FLAGS: 286 case TEP_PRINT_FLAGS:
287 define_event_symbols(event, ev_name, args->flags.field); 287 define_event_symbols(event, ev_name, args->flags.field);
288 define_field(PRINT_FLAGS, ev_name, cur_field_name, 288 define_field(TEP_PRINT_FLAGS, ev_name, cur_field_name,
289 args->flags.delim); 289 args->flags.delim);
290 define_values(PRINT_FLAGS, args->flags.flags, ev_name, 290 define_values(TEP_PRINT_FLAGS, args->flags.flags, ev_name,
291 cur_field_name); 291 cur_field_name);
292 break; 292 break;
293 case PRINT_SYMBOL: 293 case TEP_PRINT_SYMBOL:
294 define_event_symbols(event, ev_name, args->symbol.field); 294 define_event_symbols(event, ev_name, args->symbol.field);
295 define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL); 295 define_field(TEP_PRINT_SYMBOL, ev_name, cur_field_name, NULL);
296 define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, 296 define_values(TEP_PRINT_SYMBOL, args->symbol.symbols, ev_name,
297 cur_field_name); 297 cur_field_name);
298 break; 298 break;
299 case PRINT_HEX: 299 case TEP_PRINT_HEX:
300 case PRINT_HEX_STR: 300 case TEP_PRINT_HEX_STR:
301 define_event_symbols(event, ev_name, args->hex.field); 301 define_event_symbols(event, ev_name, args->hex.field);
302 define_event_symbols(event, ev_name, args->hex.size); 302 define_event_symbols(event, ev_name, args->hex.size);
303 break; 303 break;
304 case PRINT_INT_ARRAY: 304 case TEP_PRINT_INT_ARRAY:
305 define_event_symbols(event, ev_name, args->int_array.field); 305 define_event_symbols(event, ev_name, args->int_array.field);
306 define_event_symbols(event, ev_name, args->int_array.count); 306 define_event_symbols(event, ev_name, args->int_array.count);
307 define_event_symbols(event, ev_name, args->int_array.el_size); 307 define_event_symbols(event, ev_name, args->int_array.el_size);
308 break; 308 break;
309 case PRINT_STRING: 309 case TEP_PRINT_STRING:
310 break; 310 break;
311 case PRINT_TYPE: 311 case TEP_PRINT_TYPE:
312 define_event_symbols(event, ev_name, args->typecast.item); 312 define_event_symbols(event, ev_name, args->typecast.item);
313 break; 313 break;
314 case PRINT_OP: 314 case TEP_PRINT_OP:
315 if (strcmp(args->op.op, ":") == 0) 315 if (strcmp(args->op.op, ":") == 0)
316 zero_flag_atom = 1; 316 zero_flag_atom = 1;
317 define_event_symbols(event, ev_name, args->op.left); 317 define_event_symbols(event, ev_name, args->op.left);
@@ -319,11 +319,11 @@ static void define_event_symbols(struct event_format *event,
319 break; 319 break;
320 default: 320 default:
321 /* gcc warns for these? */ 321 /* gcc warns for these? */
322 case PRINT_BSTRING: 322 case TEP_PRINT_BSTRING:
323 case PRINT_DYNAMIC_ARRAY: 323 case TEP_PRINT_DYNAMIC_ARRAY:
324 case PRINT_DYNAMIC_ARRAY_LEN: 324 case TEP_PRINT_DYNAMIC_ARRAY_LEN:
325 case PRINT_FUNC: 325 case TEP_PRINT_FUNC:
326 case PRINT_BITMASK: 326 case TEP_PRINT_BITMASK:
327 /* we should warn... */ 327 /* we should warn... */
328 return; 328 return;
329 } 329 }
@@ -332,10 +332,10 @@ static void define_event_symbols(struct event_format *event,
332 define_event_symbols(event, ev_name, args->next); 332 define_event_symbols(event, ev_name, args->next);
333} 333}
334 334
335static PyObject *get_field_numeric_entry(struct event_format *event, 335static PyObject *get_field_numeric_entry(struct tep_event_format *event,
336 struct format_field *field, void *data) 336 struct tep_format_field *field, void *data)
337{ 337{
338 bool is_array = field->flags & FIELD_IS_ARRAY; 338 bool is_array = field->flags & TEP_FIELD_IS_ARRAY;
339 PyObject *obj = NULL, *list = NULL; 339 PyObject *obj = NULL, *list = NULL;
340 unsigned long long val; 340 unsigned long long val;
341 unsigned int item_size, n_items, i; 341 unsigned int item_size, n_items, i;
@@ -353,7 +353,7 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
353 353
354 val = read_size(event, data + field->offset + i * item_size, 354 val = read_size(event, data + field->offset + i * item_size,
355 item_size); 355 item_size);
356 if (field->flags & FIELD_IS_SIGNED) { 356 if (field->flags & TEP_FIELD_IS_SIGNED) {
357 if ((long long)val >= LONG_MIN && 357 if ((long long)val >= LONG_MIN &&
358 (long long)val <= LONG_MAX) 358 (long long)val <= LONG_MAX)
359 obj = _PyLong_FromLong(val); 359 obj = _PyLong_FromLong(val);
@@ -790,11 +790,11 @@ static void python_process_tracepoint(struct perf_sample *sample,
790 struct perf_evsel *evsel, 790 struct perf_evsel *evsel,
791 struct addr_location *al) 791 struct addr_location *al)
792{ 792{
793 struct event_format *event = evsel->tp_format; 793 struct tep_event_format *event = evsel->tp_format;
794 PyObject *handler, *context, *t, *obj = NULL, *callchain; 794 PyObject *handler, *context, *t, *obj = NULL, *callchain;
795 PyObject *dict = NULL, *all_entries_dict = NULL; 795 PyObject *dict = NULL, *all_entries_dict = NULL;
796 static char handler_name[256]; 796 static char handler_name[256];
797 struct format_field *field; 797 struct tep_format_field *field;
798 unsigned long s, ns; 798 unsigned long s, ns;
799 unsigned n = 0; 799 unsigned n = 0;
800 int pid; 800 int pid;
@@ -867,22 +867,22 @@ static void python_process_tracepoint(struct perf_sample *sample,
867 unsigned int offset, len; 867 unsigned int offset, len;
868 unsigned long long val; 868 unsigned long long val;
869 869
870 if (field->flags & FIELD_IS_ARRAY) { 870 if (field->flags & TEP_FIELD_IS_ARRAY) {
871 offset = field->offset; 871 offset = field->offset;
872 len = field->size; 872 len = field->size;
873 if (field->flags & FIELD_IS_DYNAMIC) { 873 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
874 val = tep_read_number(scripting_context->pevent, 874 val = tep_read_number(scripting_context->pevent,
875 data + offset, len); 875 data + offset, len);
876 offset = val; 876 offset = val;
877 len = offset >> 16; 877 len = offset >> 16;
878 offset &= 0xffff; 878 offset &= 0xffff;
879 } 879 }
880 if (field->flags & FIELD_IS_STRING && 880 if (field->flags & TEP_FIELD_IS_STRING &&
881 is_printable_array(data + offset, len)) { 881 is_printable_array(data + offset, len)) {
882 obj = _PyUnicode_FromString((char *) data + offset); 882 obj = _PyUnicode_FromString((char *) data + offset);
883 } else { 883 } else {
884 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); 884 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
885 field->flags &= ~FIELD_IS_STRING; 885 field->flags &= ~TEP_FIELD_IS_STRING;
886 } 886 }
887 } else { /* FIELD_IS_NUMERIC */ 887 } else { /* FIELD_IS_NUMERIC */
888 obj = get_field_numeric_entry(event, field, data); 888 obj = get_field_numeric_entry(event, field, data);
@@ -1590,8 +1590,8 @@ static int python_stop_script(void)
1590 1590
1591static int python_generate_script(struct tep_handle *pevent, const char *outfile) 1591static int python_generate_script(struct tep_handle *pevent, const char *outfile)
1592{ 1592{
1593 struct event_format *event = NULL; 1593 struct tep_event_format *event = NULL;
1594 struct format_field *f; 1594 struct tep_format_field *f;
1595 char fname[PATH_MAX]; 1595 char fname[PATH_MAX];
1596 int not_first, count; 1596 int not_first, count;
1597 FILE *ofp; 1597 FILE *ofp;
@@ -1686,12 +1686,12 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
1686 count++; 1686 count++;
1687 1687
1688 fprintf(ofp, "%s=", f->name); 1688 fprintf(ofp, "%s=", f->name);
1689 if (f->flags & FIELD_IS_STRING || 1689 if (f->flags & TEP_FIELD_IS_STRING ||
1690 f->flags & FIELD_IS_FLAG || 1690 f->flags & TEP_FIELD_IS_FLAG ||
1691 f->flags & FIELD_IS_ARRAY || 1691 f->flags & TEP_FIELD_IS_ARRAY ||
1692 f->flags & FIELD_IS_SYMBOLIC) 1692 f->flags & TEP_FIELD_IS_SYMBOLIC)
1693 fprintf(ofp, "%%s"); 1693 fprintf(ofp, "%%s");
1694 else if (f->flags & FIELD_IS_SIGNED) 1694 else if (f->flags & TEP_FIELD_IS_SIGNED)
1695 fprintf(ofp, "%%d"); 1695 fprintf(ofp, "%%d");
1696 else 1696 else
1697 fprintf(ofp, "%%u"); 1697 fprintf(ofp, "%%u");
@@ -1709,7 +1709,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
1709 if (++count % 5 == 0) 1709 if (++count % 5 == 0)
1710 fprintf(ofp, "\n\t\t"); 1710 fprintf(ofp, "\n\t\t");
1711 1711
1712 if (f->flags & FIELD_IS_FLAG) { 1712 if (f->flags & TEP_FIELD_IS_FLAG) {
1713 if ((count - 1) % 5 != 0) { 1713 if ((count - 1) % 5 != 0) {
1714 fprintf(ofp, "\n\t\t"); 1714 fprintf(ofp, "\n\t\t");
1715 count = 4; 1715 count = 4;
@@ -1719,7 +1719,7 @@ static int python_generate_script(struct tep_handle *pevent, const char *outfile
1719 event->name); 1719 event->name);
1720 fprintf(ofp, "\"%s\", %s)", f->name, 1720 fprintf(ofp, "\"%s\", %s)", f->name,
1721 f->name); 1721 f->name);
1722 } else if (f->flags & FIELD_IS_SYMBOLIC) { 1722 } else if (f->flags & TEP_FIELD_IS_SYMBOLIC) {
1723 if ((count - 1) % 5 != 0) { 1723 if ((count - 1) % 5 != 0) {
1724 fprintf(ofp, "\n\t\t"); 1724 fprintf(ofp, "\n\t\t");
1725 count = 4; 1725 count = 4;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8b9369303561..7d2c8ce6cfad 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -199,12 +199,10 @@ void perf_session__delete(struct perf_session *session)
199 free(session); 199 free(session);
200} 200}
201 201
202static int process_event_synth_tracing_data_stub(struct perf_tool *tool 202static int process_event_synth_tracing_data_stub(struct perf_session *session
203 __maybe_unused, 203 __maybe_unused,
204 union perf_event *event 204 union perf_event *event
205 __maybe_unused, 205 __maybe_unused)
206 struct perf_session *session
207 __maybe_unused)
208{ 206{
209 dump_printf(": unhandled!\n"); 207 dump_printf(": unhandled!\n");
210 return 0; 208 return 0;
@@ -277,10 +275,8 @@ static int skipn(int fd, off_t n)
277 return 0; 275 return 0;
278} 276}
279 277
280static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused, 278static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused,
281 union perf_event *event, 279 union perf_event *event)
282 struct perf_session *session
283 __maybe_unused)
284{ 280{
285 dump_printf(": unhandled!\n"); 281 dump_printf(": unhandled!\n");
286 if (perf_data__is_pipe(session->data)) 282 if (perf_data__is_pipe(session->data))
@@ -288,9 +284,8 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
288 return event->auxtrace.size; 284 return event->auxtrace.size;
289} 285}
290 286
291static int process_event_op2_stub(struct perf_tool *tool __maybe_unused, 287static int process_event_op2_stub(struct perf_session *session __maybe_unused,
292 union perf_event *event __maybe_unused, 288 union perf_event *event __maybe_unused)
293 struct perf_session *session __maybe_unused)
294{ 289{
295 dump_printf(": unhandled!\n"); 290 dump_printf(": unhandled!\n");
296 return 0; 291 return 0;
@@ -298,9 +293,8 @@ static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
298 293
299 294
300static 295static
301int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused, 296int process_event_thread_map_stub(struct perf_session *session __maybe_unused,
302 union perf_event *event __maybe_unused, 297 union perf_event *event __maybe_unused)
303 struct perf_session *session __maybe_unused)
304{ 298{
305 if (dump_trace) 299 if (dump_trace)
306 perf_event__fprintf_thread_map(event, stdout); 300 perf_event__fprintf_thread_map(event, stdout);
@@ -310,9 +304,8 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
310} 304}
311 305
312static 306static
313int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused, 307int process_event_cpu_map_stub(struct perf_session *session __maybe_unused,
314 union perf_event *event __maybe_unused, 308 union perf_event *event __maybe_unused)
315 struct perf_session *session __maybe_unused)
316{ 309{
317 if (dump_trace) 310 if (dump_trace)
318 perf_event__fprintf_cpu_map(event, stdout); 311 perf_event__fprintf_cpu_map(event, stdout);
@@ -322,9 +315,8 @@ int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
322} 315}
323 316
324static 317static
325int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused, 318int process_event_stat_config_stub(struct perf_session *session __maybe_unused,
326 union perf_event *event __maybe_unused, 319 union perf_event *event __maybe_unused)
327 struct perf_session *session __maybe_unused)
328{ 320{
329 if (dump_trace) 321 if (dump_trace)
330 perf_event__fprintf_stat_config(event, stdout); 322 perf_event__fprintf_stat_config(event, stdout);
@@ -333,10 +325,8 @@ int process_event_stat_config_stub(struct perf_tool *tool __maybe_unused,
333 return 0; 325 return 0;
334} 326}
335 327
336static int process_stat_stub(struct perf_tool *tool __maybe_unused, 328static int process_stat_stub(struct perf_session *perf_session __maybe_unused,
337 union perf_event *event __maybe_unused, 329 union perf_event *event)
338 struct perf_session *perf_session
339 __maybe_unused)
340{ 330{
341 if (dump_trace) 331 if (dump_trace)
342 perf_event__fprintf_stat(event, stdout); 332 perf_event__fprintf_stat(event, stdout);
@@ -345,10 +335,8 @@ static int process_stat_stub(struct perf_tool *tool __maybe_unused,
345 return 0; 335 return 0;
346} 336}
347 337
348static int process_stat_round_stub(struct perf_tool *tool __maybe_unused, 338static int process_stat_round_stub(struct perf_session *perf_session __maybe_unused,
349 union perf_event *event __maybe_unused, 339 union perf_event *event)
350 struct perf_session *perf_session
351 __maybe_unused)
352{ 340{
353 if (dump_trace) 341 if (dump_trace)
354 perf_event__fprintf_stat_round(event, stdout); 342 perf_event__fprintf_stat_round(event, stdout);
@@ -1374,37 +1362,37 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1374 case PERF_RECORD_HEADER_TRACING_DATA: 1362 case PERF_RECORD_HEADER_TRACING_DATA:
1375 /* setup for reading amidst mmap */ 1363 /* setup for reading amidst mmap */
1376 lseek(fd, file_offset, SEEK_SET); 1364 lseek(fd, file_offset, SEEK_SET);
1377 return tool->tracing_data(tool, event, session); 1365 return tool->tracing_data(session, event);
1378 case PERF_RECORD_HEADER_BUILD_ID: 1366 case PERF_RECORD_HEADER_BUILD_ID:
1379 return tool->build_id(tool, event, session); 1367 return tool->build_id(session, event);
1380 case PERF_RECORD_FINISHED_ROUND: 1368 case PERF_RECORD_FINISHED_ROUND:
1381 return tool->finished_round(tool, event, oe); 1369 return tool->finished_round(tool, event, oe);
1382 case PERF_RECORD_ID_INDEX: 1370 case PERF_RECORD_ID_INDEX:
1383 return tool->id_index(tool, event, session); 1371 return tool->id_index(session, event);
1384 case PERF_RECORD_AUXTRACE_INFO: 1372 case PERF_RECORD_AUXTRACE_INFO:
1385 return tool->auxtrace_info(tool, event, session); 1373 return tool->auxtrace_info(session, event);
1386 case PERF_RECORD_AUXTRACE: 1374 case PERF_RECORD_AUXTRACE:
1387 /* setup for reading amidst mmap */ 1375 /* setup for reading amidst mmap */
1388 lseek(fd, file_offset + event->header.size, SEEK_SET); 1376 lseek(fd, file_offset + event->header.size, SEEK_SET);
1389 return tool->auxtrace(tool, event, session); 1377 return tool->auxtrace(session, event);
1390 case PERF_RECORD_AUXTRACE_ERROR: 1378 case PERF_RECORD_AUXTRACE_ERROR:
1391 perf_session__auxtrace_error_inc(session, event); 1379 perf_session__auxtrace_error_inc(session, event);
1392 return tool->auxtrace_error(tool, event, session); 1380 return tool->auxtrace_error(session, event);
1393 case PERF_RECORD_THREAD_MAP: 1381 case PERF_RECORD_THREAD_MAP:
1394 return tool->thread_map(tool, event, session); 1382 return tool->thread_map(session, event);
1395 case PERF_RECORD_CPU_MAP: 1383 case PERF_RECORD_CPU_MAP:
1396 return tool->cpu_map(tool, event, session); 1384 return tool->cpu_map(session, event);
1397 case PERF_RECORD_STAT_CONFIG: 1385 case PERF_RECORD_STAT_CONFIG:
1398 return tool->stat_config(tool, event, session); 1386 return tool->stat_config(session, event);
1399 case PERF_RECORD_STAT: 1387 case PERF_RECORD_STAT:
1400 return tool->stat(tool, event, session); 1388 return tool->stat(session, event);
1401 case PERF_RECORD_STAT_ROUND: 1389 case PERF_RECORD_STAT_ROUND:
1402 return tool->stat_round(tool, event, session); 1390 return tool->stat_round(session, event);
1403 case PERF_RECORD_TIME_CONV: 1391 case PERF_RECORD_TIME_CONV:
1404 session->time_conv = event->time_conv; 1392 session->time_conv = event->time_conv;
1405 return tool->time_conv(tool, event, session); 1393 return tool->time_conv(session, event);
1406 case PERF_RECORD_HEADER_FEATURE: 1394 case PERF_RECORD_HEADER_FEATURE:
1407 return tool->feature(tool, event, session); 1395 return tool->feature(session, event);
1408 default: 1396 default:
1409 return -EINVAL; 1397 return -EINVAL;
1410 } 1398 }
@@ -2133,9 +2121,8 @@ out:
2133 return err; 2121 return err;
2134} 2122}
2135 2123
2136int perf_event__process_id_index(struct perf_tool *tool __maybe_unused, 2124int perf_event__process_id_index(struct perf_session *session,
2137 union perf_event *event, 2125 union perf_event *event)
2138 struct perf_session *session)
2139{ 2126{
2140 struct perf_evlist *evlist = session->evlist; 2127 struct perf_evlist *evlist = session->evlist;
2141 struct id_index_event *ie = &event->id_index; 2128 struct id_index_event *ie = &event->id_index;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index da40b4b380ca..d96eccd7d27f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -120,9 +120,8 @@ int perf_session__deliver_synth_event(struct perf_session *session,
120 union perf_event *event, 120 union perf_event *event,
121 struct perf_sample *sample); 121 struct perf_sample *sample);
122 122
123int perf_event__process_id_index(struct perf_tool *tool, 123int perf_event__process_id_index(struct perf_session *session,
124 union perf_event *event, 124 union perf_event *event);
125 struct perf_session *session);
126 125
127int perf_event__synthesize_id_index(struct perf_tool *tool, 126int perf_event__synthesize_id_index(struct perf_tool *tool,
128 perf_event__handler_t process, 127 perf_event__handler_t process,
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 97efbcad076e..63f758c655d5 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -5,16 +5,18 @@ from subprocess import Popen, PIPE
5from re import sub 5from re import sub
6 6
7def clang_has_option(option): 7def clang_has_option(option):
8 return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if "unknown argument" in o] == [ ] 8 return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if b"unknown argument" in o] == [ ]
9 9
10cc = getenv("CC") 10cc = getenv("CC")
11if cc == "clang": 11if cc == "clang":
12 from _sysconfigdata import build_time_vars 12 from distutils.sysconfig import get_config_vars
13 build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"]) 13 vars = get_config_vars()
14 if not clang_has_option("-mcet"): 14 for var in ('CFLAGS', 'OPT'):
15 build_time_vars["CFLAGS"] = sub("-mcet", "", build_time_vars["CFLAGS"]) 15 vars[var] = sub("-specs=[^ ]+", "", vars[var])
16 if not clang_has_option("-fcf-protection"): 16 if not clang_has_option("-mcet"):
17 build_time_vars["CFLAGS"] = sub("-fcf-protection", "", build_time_vars["CFLAGS"]) 17 vars[var] = sub("-mcet", "", vars[var])
18 if not clang_has_option("-fcf-protection"):
19 vars[var] = sub("-fcf-protection", "", vars[var])
18 20
19from distutils.core import setup, Extension 21from distutils.core import setup, Extension
20 22
@@ -35,7 +37,7 @@ class install_lib(_install_lib):
35 37
36cflags = getenv('CFLAGS', '').split() 38cflags = getenv('CFLAGS', '').split()
37# switch off several checks (need to be at the end of cflags list) 39# switch off several checks (need to be at the end of cflags list)
38cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ] 40cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter', '-Wno-redundant-decls' ]
39if cc != "clang": 41if cc != "clang":
40 cflags += ['-Wno-cast-function-type' ] 42 cflags += ['-Wno-cast-function-type' ]
41 43
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b284276ec963..f96c005b3c41 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1884,7 +1884,7 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd,
1884struct hpp_dynamic_entry { 1884struct hpp_dynamic_entry {
1885 struct perf_hpp_fmt hpp; 1885 struct perf_hpp_fmt hpp;
1886 struct perf_evsel *evsel; 1886 struct perf_evsel *evsel;
1887 struct format_field *field; 1887 struct tep_format_field *field;
1888 unsigned dynamic_len; 1888 unsigned dynamic_len;
1889 bool raw_trace; 1889 bool raw_trace;
1890}; 1890};
@@ -1899,7 +1899,7 @@ static int hde_width(struct hpp_dynamic_entry *hde)
1899 if (namelen > len) 1899 if (namelen > len)
1900 len = namelen; 1900 len = namelen;
1901 1901
1902 if (!(hde->field->flags & FIELD_IS_STRING)) { 1902 if (!(hde->field->flags & TEP_FIELD_IS_STRING)) {
1903 /* length for print hex numbers */ 1903 /* length for print hex numbers */
1904 fieldlen = hde->field->size * 2 + 2; 1904 fieldlen = hde->field->size * 2 + 2;
1905 } 1905 }
@@ -1915,7 +1915,7 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde,
1915 struct hist_entry *he) 1915 struct hist_entry *he)
1916{ 1916{
1917 char *str, *pos; 1917 char *str, *pos;
1918 struct format_field *field = hde->field; 1918 struct tep_format_field *field = hde->field;
1919 size_t namelen; 1919 size_t namelen;
1920 bool last = false; 1920 bool last = false;
1921 1921
@@ -2000,7 +2000,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
2000 struct hpp_dynamic_entry *hde; 2000 struct hpp_dynamic_entry *hde;
2001 size_t len = fmt->user_len; 2001 size_t len = fmt->user_len;
2002 char *str, *pos; 2002 char *str, *pos;
2003 struct format_field *field; 2003 struct tep_format_field *field;
2004 size_t namelen; 2004 size_t namelen;
2005 bool last = false; 2005 bool last = false;
2006 int ret; 2006 int ret;
@@ -2060,7 +2060,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
2060 struct hist_entry *a, struct hist_entry *b) 2060 struct hist_entry *a, struct hist_entry *b)
2061{ 2061{
2062 struct hpp_dynamic_entry *hde; 2062 struct hpp_dynamic_entry *hde;
2063 struct format_field *field; 2063 struct tep_format_field *field;
2064 unsigned offset, size; 2064 unsigned offset, size;
2065 2065
2066 hde = container_of(fmt, struct hpp_dynamic_entry, hpp); 2066 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
@@ -2071,7 +2071,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
2071 } 2071 }
2072 2072
2073 field = hde->field; 2073 field = hde->field;
2074 if (field->flags & FIELD_IS_DYNAMIC) { 2074 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
2075 unsigned long long dyn; 2075 unsigned long long dyn;
2076 2076
2077 tep_read_number_field(field, a->raw_data, &dyn); 2077 tep_read_number_field(field, a->raw_data, &dyn);
@@ -2117,7 +2117,7 @@ static void hde_free(struct perf_hpp_fmt *fmt)
2117} 2117}
2118 2118
2119static struct hpp_dynamic_entry * 2119static struct hpp_dynamic_entry *
2120__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field, 2120__alloc_dynamic_entry(struct perf_evsel *evsel, struct tep_format_field *field,
2121 int level) 2121 int level)
2122{ 2122{
2123 struct hpp_dynamic_entry *hde; 2123 struct hpp_dynamic_entry *hde;
@@ -2252,7 +2252,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
2252} 2252}
2253 2253
2254static int __dynamic_dimension__add(struct perf_evsel *evsel, 2254static int __dynamic_dimension__add(struct perf_evsel *evsel,
2255 struct format_field *field, 2255 struct tep_format_field *field,
2256 bool raw_trace, int level) 2256 bool raw_trace, int level)
2257{ 2257{
2258 struct hpp_dynamic_entry *hde; 2258 struct hpp_dynamic_entry *hde;
@@ -2270,7 +2270,7 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
2270static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level) 2270static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level)
2271{ 2271{
2272 int ret; 2272 int ret;
2273 struct format_field *field; 2273 struct tep_format_field *field;
2274 2274
2275 field = evsel->tp_format->format.fields; 2275 field = evsel->tp_format->format.fields;
2276 while (field) { 2276 while (field) {
@@ -2305,7 +2305,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
2305{ 2305{
2306 int ret = -ESRCH; 2306 int ret = -ESRCH;
2307 struct perf_evsel *evsel; 2307 struct perf_evsel *evsel;
2308 struct format_field *field; 2308 struct tep_format_field *field;
2309 2309
2310 evlist__for_each_entry(evlist, evsel) { 2310 evlist__for_each_entry(evlist, evsel) {
2311 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 2311 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
@@ -2327,7 +2327,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
2327{ 2327{
2328 char *str, *event_name, *field_name, *opt_name; 2328 char *str, *event_name, *field_name, *opt_name;
2329 struct perf_evsel *evsel; 2329 struct perf_evsel *evsel;
2330 struct format_field *field; 2330 struct tep_format_field *field;
2331 bool raw_trace = symbol_conf.raw_trace; 2331 bool raw_trace = symbol_conf.raw_trace;
2332 int ret = 0; 2332 int ret = 0;
2333 2333
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index 09d6746e6ec8..e767c4a9d4d2 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -85,6 +85,9 @@ static struct symbol *new_inline_sym(struct dso *dso,
85 struct symbol *inline_sym; 85 struct symbol *inline_sym;
86 char *demangled = NULL; 86 char *demangled = NULL;
87 87
88 if (!funcname)
89 funcname = "??";
90
88 if (dso) { 91 if (dso) {
89 demangled = dso__demangle_sym(dso, 0, funcname); 92 demangled = dso__demangle_sym(dso, 0, funcname);
90 if (demangled) 93 if (demangled)
diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
new file mode 100644
index 000000000000..e7b4c44ebb62
--- /dev/null
+++ b/tools/perf/util/stat-display.c
@@ -0,0 +1,1166 @@
1#include <stdio.h>
2#include <inttypes.h>
3#include <linux/time64.h>
4#include <math.h>
5#include "evlist.h"
6#include "evsel.h"
7#include "stat.h"
8#include "top.h"
9#include "thread_map.h"
10#include "cpumap.h"
11#include "string2.h"
12#include "sane_ctype.h"
13#include "cgroup.h"
14#include <math.h>
15#include <api/fs/fs.h>
16
17#define CNTR_NOT_SUPPORTED "<not supported>"
18#define CNTR_NOT_COUNTED "<not counted>"
19
20static bool is_duration_time(struct perf_evsel *evsel)
21{
22 return !strcmp(evsel->name, "duration_time");
23}
24
25static void print_running(struct perf_stat_config *config,
26 u64 run, u64 ena)
27{
28 if (config->csv_output) {
29 fprintf(config->output, "%s%" PRIu64 "%s%.2f",
30 config->csv_sep,
31 run,
32 config->csv_sep,
33 ena ? 100.0 * run / ena : 100.0);
34 } else if (run != ena) {
35 fprintf(config->output, " (%.2f%%)", 100.0 * run / ena);
36 }
37}
38
39static void print_noise_pct(struct perf_stat_config *config,
40 double total, double avg)
41{
42 double pct = rel_stddev_stats(total, avg);
43
44 if (config->csv_output)
45 fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
46 else if (pct)
47 fprintf(config->output, " ( +-%6.2f%% )", pct);
48}
49
50static void print_noise(struct perf_stat_config *config,
51 struct perf_evsel *evsel, double avg)
52{
53 struct perf_stat_evsel *ps;
54
55 if (config->run_count == 1)
56 return;
57
58 ps = evsel->stats;
59 print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
60}
61
62static void aggr_printout(struct perf_stat_config *config,
63 struct perf_evsel *evsel, int id, int nr)
64{
65 switch (config->aggr_mode) {
66 case AGGR_CORE:
67 fprintf(config->output, "S%d-C%*d%s%*d%s",
68 cpu_map__id_to_socket(id),
69 config->csv_output ? 0 : -8,
70 cpu_map__id_to_cpu(id),
71 config->csv_sep,
72 config->csv_output ? 0 : 4,
73 nr,
74 config->csv_sep);
75 break;
76 case AGGR_SOCKET:
77 fprintf(config->output, "S%*d%s%*d%s",
78 config->csv_output ? 0 : -5,
79 id,
80 config->csv_sep,
81 config->csv_output ? 0 : 4,
82 nr,
83 config->csv_sep);
84 break;
85 case AGGR_NONE:
86 fprintf(config->output, "CPU%*d%s",
87 config->csv_output ? 0 : -4,
88 perf_evsel__cpus(evsel)->map[id], config->csv_sep);
89 break;
90 case AGGR_THREAD:
91 fprintf(config->output, "%*s-%*d%s",
92 config->csv_output ? 0 : 16,
93 thread_map__comm(evsel->threads, id),
94 config->csv_output ? 0 : -8,
95 thread_map__pid(evsel->threads, id),
96 config->csv_sep);
97 break;
98 case AGGR_GLOBAL:
99 case AGGR_UNSET:
100 default:
101 break;
102 }
103}
104
105struct outstate {
106 FILE *fh;
107 bool newline;
108 const char *prefix;
109 int nfields;
110 int id, nr;
111 struct perf_evsel *evsel;
112};
113
114#define METRIC_LEN 35
115
116static void new_line_std(struct perf_stat_config *config __maybe_unused,
117 void *ctx)
118{
119 struct outstate *os = ctx;
120
121 os->newline = true;
122}
123
124static void do_new_line_std(struct perf_stat_config *config,
125 struct outstate *os)
126{
127 fputc('\n', os->fh);
128 fputs(os->prefix, os->fh);
129 aggr_printout(config, os->evsel, os->id, os->nr);
130 if (config->aggr_mode == AGGR_NONE)
131 fprintf(os->fh, " ");
132 fprintf(os->fh, " ");
133}
134
135static void print_metric_std(struct perf_stat_config *config,
136 void *ctx, const char *color, const char *fmt,
137 const char *unit, double val)
138{
139 struct outstate *os = ctx;
140 FILE *out = os->fh;
141 int n;
142 bool newline = os->newline;
143
144 os->newline = false;
145
146 if (unit == NULL || fmt == NULL) {
147 fprintf(out, "%-*s", METRIC_LEN, "");
148 return;
149 }
150
151 if (newline)
152 do_new_line_std(config, os);
153
154 n = fprintf(out, " # ");
155 if (color)
156 n += color_fprintf(out, color, fmt, val);
157 else
158 n += fprintf(out, fmt, val);
159 fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
160}
161
162static void new_line_csv(struct perf_stat_config *config, void *ctx)
163{
164 struct outstate *os = ctx;
165 int i;
166
167 fputc('\n', os->fh);
168 if (os->prefix)
169 fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
170 aggr_printout(config, os->evsel, os->id, os->nr);
171 for (i = 0; i < os->nfields; i++)
172 fputs(config->csv_sep, os->fh);
173}
174
175static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
176 void *ctx,
177 const char *color __maybe_unused,
178 const char *fmt, const char *unit, double val)
179{
180 struct outstate *os = ctx;
181 FILE *out = os->fh;
182 char buf[64], *vals, *ends;
183
184 if (unit == NULL || fmt == NULL) {
185 fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
186 return;
187 }
188 snprintf(buf, sizeof(buf), fmt, val);
189 ends = vals = ltrim(buf);
190 while (isdigit(*ends) || *ends == '.')
191 ends++;
192 *ends = 0;
193 while (isspace(*unit))
194 unit++;
195 fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, unit);
196}
197
198/* Filter out some columns that don't work well in metrics only mode */
199
200static bool valid_only_metric(const char *unit)
201{
202 if (!unit)
203 return false;
204 if (strstr(unit, "/sec") ||
205 strstr(unit, "hz") ||
206 strstr(unit, "Hz") ||
207 strstr(unit, "CPUs utilized"))
208 return false;
209 return true;
210}
211
212static const char *fixunit(char *buf, struct perf_evsel *evsel,
213 const char *unit)
214{
215 if (!strncmp(unit, "of all", 6)) {
216 snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
217 unit);
218 return buf;
219 }
220 return unit;
221}
222
223static void print_metric_only(struct perf_stat_config *config,
224 void *ctx, const char *color, const char *fmt,
225 const char *unit, double val)
226{
227 struct outstate *os = ctx;
228 FILE *out = os->fh;
229 char buf[1024], str[1024];
230 unsigned mlen = config->metric_only_len;
231
232 if (!valid_only_metric(unit))
233 return;
234 unit = fixunit(buf, os->evsel, unit);
235 if (mlen < strlen(unit))
236 mlen = strlen(unit) + 1;
237
238 if (color)
239 mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
240
241 color_snprintf(str, sizeof(str), color ?: "", fmt, val);
242 fprintf(out, "%*s ", mlen, str);
243}
244
245static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
246 void *ctx, const char *color __maybe_unused,
247 const char *fmt,
248 const char *unit, double val)
249{
250 struct outstate *os = ctx;
251 FILE *out = os->fh;
252 char buf[64], *vals, *ends;
253 char tbuf[1024];
254
255 if (!valid_only_metric(unit))
256 return;
257 unit = fixunit(tbuf, os->evsel, unit);
258 snprintf(buf, sizeof buf, fmt, val);
259 ends = vals = ltrim(buf);
260 while (isdigit(*ends) || *ends == '.')
261 ends++;
262 *ends = 0;
263 fprintf(out, "%s%s", vals, config->csv_sep);
264}
265
266static void new_line_metric(struct perf_stat_config *config __maybe_unused,
267 void *ctx __maybe_unused)
268{
269}
270
271static void print_metric_header(struct perf_stat_config *config,
272 void *ctx, const char *color __maybe_unused,
273 const char *fmt __maybe_unused,
274 const char *unit, double val __maybe_unused)
275{
276 struct outstate *os = ctx;
277 char tbuf[1024];
278
279 if (!valid_only_metric(unit))
280 return;
281 unit = fixunit(tbuf, os->evsel, unit);
282 if (config->csv_output)
283 fprintf(os->fh, "%s%s", unit, config->csv_sep);
284 else
285 fprintf(os->fh, "%*s ", config->metric_only_len, unit);
286}
287
288static int first_shadow_cpu(struct perf_stat_config *config,
289 struct perf_evsel *evsel, int id)
290{
291 struct perf_evlist *evlist = evsel->evlist;
292 int i;
293
294 if (!config->aggr_get_id)
295 return 0;
296
297 if (config->aggr_mode == AGGR_NONE)
298 return id;
299
300 if (config->aggr_mode == AGGR_GLOBAL)
301 return 0;
302
303 for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
304 int cpu2 = perf_evsel__cpus(evsel)->map[i];
305
306 if (config->aggr_get_id(config, evlist->cpus, cpu2) == id)
307 return cpu2;
308 }
309 return 0;
310}
311
312static void abs_printout(struct perf_stat_config *config,
313 int id, int nr, struct perf_evsel *evsel, double avg)
314{
315 FILE *output = config->output;
316 double sc = evsel->scale;
317 const char *fmt;
318
319 if (config->csv_output) {
320 fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
321 } else {
322 if (config->big_num)
323 fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
324 else
325 fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
326 }
327
328 aggr_printout(config, evsel, id, nr);
329
330 fprintf(output, fmt, avg, config->csv_sep);
331
332 if (evsel->unit)
333 fprintf(output, "%-*s%s",
334 config->csv_output ? 0 : config->unit_width,
335 evsel->unit, config->csv_sep);
336
337 fprintf(output, "%-*s", config->csv_output ? 0 : 25, perf_evsel__name(evsel));
338
339 if (evsel->cgrp)
340 fprintf(output, "%s%s", config->csv_sep, evsel->cgrp->name);
341}
342
343static bool is_mixed_hw_group(struct perf_evsel *counter)
344{
345 struct perf_evlist *evlist = counter->evlist;
346 u32 pmu_type = counter->attr.type;
347 struct perf_evsel *pos;
348
349 if (counter->nr_members < 2)
350 return false;
351
352 evlist__for_each_entry(evlist, pos) {
353 /* software events can be part of any hardware group */
354 if (pos->attr.type == PERF_TYPE_SOFTWARE)
355 continue;
356 if (pmu_type == PERF_TYPE_SOFTWARE) {
357 pmu_type = pos->attr.type;
358 continue;
359 }
360 if (pmu_type != pos->attr.type)
361 return true;
362 }
363
364 return false;
365}
366
367static void printout(struct perf_stat_config *config, int id, int nr,
368 struct perf_evsel *counter, double uval,
369 char *prefix, u64 run, u64 ena, double noise,
370 struct runtime_stat *st)
371{
372 struct perf_stat_output_ctx out;
373 struct outstate os = {
374 .fh = config->output,
375 .prefix = prefix ? prefix : "",
376 .id = id,
377 .nr = nr,
378 .evsel = counter,
379 };
380 print_metric_t pm = print_metric_std;
381 new_line_t nl;
382
383 if (config->metric_only) {
384 nl = new_line_metric;
385 if (config->csv_output)
386 pm = print_metric_only_csv;
387 else
388 pm = print_metric_only;
389 } else
390 nl = new_line_std;
391
392 if (config->csv_output && !config->metric_only) {
393 static int aggr_fields[] = {
394 [AGGR_GLOBAL] = 0,
395 [AGGR_THREAD] = 1,
396 [AGGR_NONE] = 1,
397 [AGGR_SOCKET] = 2,
398 [AGGR_CORE] = 2,
399 };
400
401 pm = print_metric_csv;
402 nl = new_line_csv;
403 os.nfields = 3;
404 os.nfields += aggr_fields[config->aggr_mode];
405 if (counter->cgrp)
406 os.nfields++;
407 }
408 if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
409 if (config->metric_only) {
410 pm(config, &os, NULL, "", "", 0);
411 return;
412 }
413 aggr_printout(config, counter, id, nr);
414
415 fprintf(config->output, "%*s%s",
416 config->csv_output ? 0 : 18,
417 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
418 config->csv_sep);
419
420 if (counter->supported) {
421 config->print_free_counters_hint = 1;
422 if (is_mixed_hw_group(counter))
423 config->print_mixed_hw_group_error = 1;
424 }
425
426 fprintf(config->output, "%-*s%s",
427 config->csv_output ? 0 : config->unit_width,
428 counter->unit, config->csv_sep);
429
430 fprintf(config->output, "%*s",
431 config->csv_output ? 0 : -25,
432 perf_evsel__name(counter));
433
434 if (counter->cgrp)
435 fprintf(config->output, "%s%s",
436 config->csv_sep, counter->cgrp->name);
437
438 if (!config->csv_output)
439 pm(config, &os, NULL, NULL, "", 0);
440 print_noise(config, counter, noise);
441 print_running(config, run, ena);
442 if (config->csv_output)
443 pm(config, &os, NULL, NULL, "", 0);
444 return;
445 }
446
447 if (!config->metric_only)
448 abs_printout(config, id, nr, counter, uval);
449
450 out.print_metric = pm;
451 out.new_line = nl;
452 out.ctx = &os;
453 out.force_header = false;
454
455 if (config->csv_output && !config->metric_only) {
456 print_noise(config, counter, noise);
457 print_running(config, run, ena);
458 }
459
460 perf_stat__print_shadow_stats(config, counter, uval,
461 first_shadow_cpu(config, counter, id),
462 &out, &config->metric_events, st);
463 if (!config->csv_output && !config->metric_only) {
464 print_noise(config, counter, noise);
465 print_running(config, run, ena);
466 }
467}
468
469static void aggr_update_shadow(struct perf_stat_config *config,
470 struct perf_evlist *evlist)
471{
472 int cpu, s2, id, s;
473 u64 val;
474 struct perf_evsel *counter;
475
476 for (s = 0; s < config->aggr_map->nr; s++) {
477 id = config->aggr_map->map[s];
478 evlist__for_each_entry(evlist, counter) {
479 val = 0;
480 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
481 s2 = config->aggr_get_id(config, evlist->cpus, cpu);
482 if (s2 != id)
483 continue;
484 val += perf_counts(counter->counts, cpu, 0)->val;
485 }
486 perf_stat__update_shadow_stats(counter, val,
487 first_shadow_cpu(config, counter, id),
488 &rt_stat);
489 }
490 }
491}
492
493static void uniquify_event_name(struct perf_evsel *counter)
494{
495 char *new_name;
496 char *config;
497
498 if (counter->uniquified_name ||
499 !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
500 strlen(counter->pmu_name)))
501 return;
502
503 config = strchr(counter->name, '/');
504 if (config) {
505 if (asprintf(&new_name,
506 "%s%s", counter->pmu_name, config) > 0) {
507 free(counter->name);
508 counter->name = new_name;
509 }
510 } else {
511 if (asprintf(&new_name,
512 "%s [%s]", counter->name, counter->pmu_name) > 0) {
513 free(counter->name);
514 counter->name = new_name;
515 }
516 }
517
518 counter->uniquified_name = true;
519}
520
521static void collect_all_aliases(struct perf_stat_config *config, struct perf_evsel *counter,
522 void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
523 bool first),
524 void *data)
525{
526 struct perf_evlist *evlist = counter->evlist;
527 struct perf_evsel *alias;
528
529 alias = list_prepare_entry(counter, &(evlist->entries), node);
530 list_for_each_entry_continue (alias, &evlist->entries, node) {
531 if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
532 alias->scale != counter->scale ||
533 alias->cgrp != counter->cgrp ||
534 strcmp(alias->unit, counter->unit) ||
535 perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter))
536 break;
537 alias->merged_stat = true;
538 cb(config, alias, data, false);
539 }
540}
541
542static bool collect_data(struct perf_stat_config *config, struct perf_evsel *counter,
543 void (*cb)(struct perf_stat_config *config, struct perf_evsel *counter, void *data,
544 bool first),
545 void *data)
546{
547 if (counter->merged_stat)
548 return false;
549 cb(config, counter, data, true);
550 if (config->no_merge)
551 uniquify_event_name(counter);
552 else if (counter->auto_merge_stats)
553 collect_all_aliases(config, counter, cb, data);
554 return true;
555}
556
557struct aggr_data {
558 u64 ena, run, val;
559 int id;
560 int nr;
561 int cpu;
562};
563
564static void aggr_cb(struct perf_stat_config *config,
565 struct perf_evsel *counter, void *data, bool first)
566{
567 struct aggr_data *ad = data;
568 int cpu, s2;
569
570 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
571 struct perf_counts_values *counts;
572
573 s2 = config->aggr_get_id(config, perf_evsel__cpus(counter), cpu);
574 if (s2 != ad->id)
575 continue;
576 if (first)
577 ad->nr++;
578 counts = perf_counts(counter->counts, cpu, 0);
579 /*
580 * When any result is bad, make them all to give
581 * consistent output in interval mode.
582 */
583 if (counts->ena == 0 || counts->run == 0 ||
584 counter->counts->scaled == -1) {
585 ad->ena = 0;
586 ad->run = 0;
587 break;
588 }
589 ad->val += counts->val;
590 ad->ena += counts->ena;
591 ad->run += counts->run;
592 }
593}
594
595static void print_aggr(struct perf_stat_config *config,
596 struct perf_evlist *evlist,
597 char *prefix)
598{
599 bool metric_only = config->metric_only;
600 FILE *output = config->output;
601 struct perf_evsel *counter;
602 int s, id, nr;
603 double uval;
604 u64 ena, run, val;
605 bool first;
606
607 if (!(config->aggr_map || config->aggr_get_id))
608 return;
609
610 aggr_update_shadow(config, evlist);
611
612 /*
613 * With metric_only everything is on a single line.
614 * Without each counter has its own line.
615 */
616 for (s = 0; s < config->aggr_map->nr; s++) {
617 struct aggr_data ad;
618 if (prefix && metric_only)
619 fprintf(output, "%s", prefix);
620
621 ad.id = id = config->aggr_map->map[s];
622 first = true;
623 evlist__for_each_entry(evlist, counter) {
624 if (is_duration_time(counter))
625 continue;
626
627 ad.val = ad.ena = ad.run = 0;
628 ad.nr = 0;
629 if (!collect_data(config, counter, aggr_cb, &ad))
630 continue;
631 nr = ad.nr;
632 ena = ad.ena;
633 run = ad.run;
634 val = ad.val;
635 if (first && metric_only) {
636 first = false;
637 aggr_printout(config, counter, id, nr);
638 }
639 if (prefix && !metric_only)
640 fprintf(output, "%s", prefix);
641
642 uval = val * counter->scale;
643 printout(config, id, nr, counter, uval, prefix,
644 run, ena, 1.0, &rt_stat);
645 if (!metric_only)
646 fputc('\n', output);
647 }
648 if (metric_only)
649 fputc('\n', output);
650 }
651}
652
653static int cmp_val(const void *a, const void *b)
654{
655 return ((struct perf_aggr_thread_value *)b)->val -
656 ((struct perf_aggr_thread_value *)a)->val;
657}
658
659static struct perf_aggr_thread_value *sort_aggr_thread(
660 struct perf_evsel *counter,
661 int nthreads, int ncpus,
662 int *ret,
663 struct target *_target)
664{
665 int cpu, thread, i = 0;
666 double uval;
667 struct perf_aggr_thread_value *buf;
668
669 buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
670 if (!buf)
671 return NULL;
672
673 for (thread = 0; thread < nthreads; thread++) {
674 u64 ena = 0, run = 0, val = 0;
675
676 for (cpu = 0; cpu < ncpus; cpu++) {
677 val += perf_counts(counter->counts, cpu, thread)->val;
678 ena += perf_counts(counter->counts, cpu, thread)->ena;
679 run += perf_counts(counter->counts, cpu, thread)->run;
680 }
681
682 uval = val * counter->scale;
683
684 /*
685 * Skip value 0 when enabling --per-thread globally,
686 * otherwise too many 0 output.
687 */
688 if (uval == 0.0 && target__has_per_thread(_target))
689 continue;
690
691 buf[i].counter = counter;
692 buf[i].id = thread;
693 buf[i].uval = uval;
694 buf[i].val = val;
695 buf[i].run = run;
696 buf[i].ena = ena;
697 i++;
698 }
699
700 qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
701
702 if (ret)
703 *ret = i;
704
705 return buf;
706}
707
708static void print_aggr_thread(struct perf_stat_config *config,
709 struct target *_target,
710 struct perf_evsel *counter, char *prefix)
711{
712 FILE *output = config->output;
713 int nthreads = thread_map__nr(counter->threads);
714 int ncpus = cpu_map__nr(counter->cpus);
715 int thread, sorted_threads, id;
716 struct perf_aggr_thread_value *buf;
717
718 buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
719 if (!buf) {
720 perror("cannot sort aggr thread");
721 return;
722 }
723
724 for (thread = 0; thread < sorted_threads; thread++) {
725 if (prefix)
726 fprintf(output, "%s", prefix);
727
728 id = buf[thread].id;
729 if (config->stats)
730 printout(config, id, 0, buf[thread].counter, buf[thread].uval,
731 prefix, buf[thread].run, buf[thread].ena, 1.0,
732 &config->stats[id]);
733 else
734 printout(config, id, 0, buf[thread].counter, buf[thread].uval,
735 prefix, buf[thread].run, buf[thread].ena, 1.0,
736 &rt_stat);
737 fputc('\n', output);
738 }
739
740 free(buf);
741}
742
743struct caggr_data {
744 double avg, avg_enabled, avg_running;
745};
746
747static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
748 struct perf_evsel *counter, void *data,
749 bool first __maybe_unused)
750{
751 struct caggr_data *cd = data;
752 struct perf_stat_evsel *ps = counter->stats;
753
754 cd->avg += avg_stats(&ps->res_stats[0]);
755 cd->avg_enabled += avg_stats(&ps->res_stats[1]);
756 cd->avg_running += avg_stats(&ps->res_stats[2]);
757}
758
759/*
760 * Print out the results of a single counter:
761 * aggregated counts in system-wide mode
762 */
763static void print_counter_aggr(struct perf_stat_config *config,
764 struct perf_evsel *counter, char *prefix)
765{
766 bool metric_only = config->metric_only;
767 FILE *output = config->output;
768 double uval;
769 struct caggr_data cd = { .avg = 0.0 };
770
771 if (!collect_data(config, counter, counter_aggr_cb, &cd))
772 return;
773
774 if (prefix && !metric_only)
775 fprintf(output, "%s", prefix);
776
777 uval = cd.avg * counter->scale;
778 printout(config, -1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled,
779 cd.avg, &rt_stat);
780 if (!metric_only)
781 fprintf(output, "\n");
782}
783
784static void counter_cb(struct perf_stat_config *config __maybe_unused,
785 struct perf_evsel *counter, void *data,
786 bool first __maybe_unused)
787{
788 struct aggr_data *ad = data;
789
790 ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
791 ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
792 ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
793}
794
795/*
796 * Print out the results of a single counter:
797 * does not use aggregated count in system-wide
798 */
799static void print_counter(struct perf_stat_config *config,
800 struct perf_evsel *counter, char *prefix)
801{
802 FILE *output = config->output;
803 u64 ena, run, val;
804 double uval;
805 int cpu;
806
807 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
808 struct aggr_data ad = { .cpu = cpu };
809
810 if (!collect_data(config, counter, counter_cb, &ad))
811 return;
812 val = ad.val;
813 ena = ad.ena;
814 run = ad.run;
815
816 if (prefix)
817 fprintf(output, "%s", prefix);
818
819 uval = val * counter->scale;
820 printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
821 &rt_stat);
822
823 fputc('\n', output);
824 }
825}
826
827static void print_no_aggr_metric(struct perf_stat_config *config,
828 struct perf_evlist *evlist,
829 char *prefix)
830{
831 int cpu;
832 int nrcpus = 0;
833 struct perf_evsel *counter;
834 u64 ena, run, val;
835 double uval;
836
837 nrcpus = evlist->cpus->nr;
838 for (cpu = 0; cpu < nrcpus; cpu++) {
839 bool first = true;
840
841 if (prefix)
842 fputs(prefix, config->output);
843 evlist__for_each_entry(evlist, counter) {
844 if (is_duration_time(counter))
845 continue;
846 if (first) {
847 aggr_printout(config, counter, cpu, 0);
848 first = false;
849 }
850 val = perf_counts(counter->counts, cpu, 0)->val;
851 ena = perf_counts(counter->counts, cpu, 0)->ena;
852 run = perf_counts(counter->counts, cpu, 0)->run;
853
854 uval = val * counter->scale;
855 printout(config, cpu, 0, counter, uval, prefix, run, ena, 1.0,
856 &rt_stat);
857 }
858 fputc('\n', config->output);
859 }
860}
861
862static int aggr_header_lens[] = {
863 [AGGR_CORE] = 18,
864 [AGGR_SOCKET] = 12,
865 [AGGR_NONE] = 6,
866 [AGGR_THREAD] = 24,
867 [AGGR_GLOBAL] = 0,
868};
869
870static const char *aggr_header_csv[] = {
871 [AGGR_CORE] = "core,cpus,",
872 [AGGR_SOCKET] = "socket,cpus",
873 [AGGR_NONE] = "cpu,",
874 [AGGR_THREAD] = "comm-pid,",
875 [AGGR_GLOBAL] = ""
876};
877
878static void print_metric_headers(struct perf_stat_config *config,
879 struct perf_evlist *evlist,
880 const char *prefix, bool no_indent)
881{
882 struct perf_stat_output_ctx out;
883 struct perf_evsel *counter;
884 struct outstate os = {
885 .fh = config->output
886 };
887
888 if (prefix)
889 fprintf(config->output, "%s", prefix);
890
891 if (!config->csv_output && !no_indent)
892 fprintf(config->output, "%*s",
893 aggr_header_lens[config->aggr_mode], "");
894 if (config->csv_output) {
895 if (config->interval)
896 fputs("time,", config->output);
897 fputs(aggr_header_csv[config->aggr_mode], config->output);
898 }
899
900 /* Print metrics headers only */
901 evlist__for_each_entry(evlist, counter) {
902 if (is_duration_time(counter))
903 continue;
904 os.evsel = counter;
905 out.ctx = &os;
906 out.print_metric = print_metric_header;
907 out.new_line = new_line_metric;
908 out.force_header = true;
909 os.evsel = counter;
910 perf_stat__print_shadow_stats(config, counter, 0,
911 0,
912 &out,
913 &config->metric_events,
914 &rt_stat);
915 }
916 fputc('\n', config->output);
917}
918
919static void print_interval(struct perf_stat_config *config,
920 struct perf_evlist *evlist,
921 char *prefix, struct timespec *ts)
922{
923 bool metric_only = config->metric_only;
924 unsigned int unit_width = config->unit_width;
925 FILE *output = config->output;
926 static int num_print_interval;
927
928 if (config->interval_clear)
929 puts(CONSOLE_CLEAR);
930
931 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, config->csv_sep);
932
933 if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
934 switch (config->aggr_mode) {
935 case AGGR_SOCKET:
936 fprintf(output, "# time socket cpus");
937 if (!metric_only)
938 fprintf(output, " counts %*s events\n", unit_width, "unit");
939 break;
940 case AGGR_CORE:
941 fprintf(output, "# time core cpus");
942 if (!metric_only)
943 fprintf(output, " counts %*s events\n", unit_width, "unit");
944 break;
945 case AGGR_NONE:
946 fprintf(output, "# time CPU ");
947 if (!metric_only)
948 fprintf(output, " counts %*s events\n", unit_width, "unit");
949 break;
950 case AGGR_THREAD:
951 fprintf(output, "# time comm-pid");
952 if (!metric_only)
953 fprintf(output, " counts %*s events\n", unit_width, "unit");
954 break;
955 case AGGR_GLOBAL:
956 default:
957 fprintf(output, "# time");
958 if (!metric_only)
959 fprintf(output, " counts %*s events\n", unit_width, "unit");
960 case AGGR_UNSET:
961 break;
962 }
963 }
964
965 if ((num_print_interval == 0 || config->interval_clear) && metric_only)
966 print_metric_headers(config, evlist, " ", true);
967 if (++num_print_interval == 25)
968 num_print_interval = 0;
969}
970
971static void print_header(struct perf_stat_config *config,
972 struct target *_target,
973 int argc, const char **argv)
974{
975 FILE *output = config->output;
976 int i;
977
978 fflush(stdout);
979
980 if (!config->csv_output) {
981 fprintf(output, "\n");
982 fprintf(output, " Performance counter stats for ");
983 if (_target->system_wide)
984 fprintf(output, "\'system wide");
985 else if (_target->cpu_list)
986 fprintf(output, "\'CPU(s) %s", _target->cpu_list);
987 else if (!target__has_task(_target)) {
988 fprintf(output, "\'%s", argv ? argv[0] : "pipe");
989 for (i = 1; argv && (i < argc); i++)
990 fprintf(output, " %s", argv[i]);
991 } else if (_target->pid)
992 fprintf(output, "process id \'%s", _target->pid);
993 else
994 fprintf(output, "thread id \'%s", _target->tid);
995
996 fprintf(output, "\'");
997 if (config->run_count > 1)
998 fprintf(output, " (%d runs)", config->run_count);
999 fprintf(output, ":\n\n");
1000 }
1001}
1002
1003static int get_precision(double num)
1004{
1005 if (num > 1)
1006 return 0;
1007
1008 return lround(ceil(-log10(num)));
1009}
1010
1011static void print_table(struct perf_stat_config *config,
1012 FILE *output, int precision, double avg)
1013{
1014 char tmp[64];
1015 int idx, indent = 0;
1016
1017 scnprintf(tmp, 64, " %17.*f", precision, avg);
1018 while (tmp[indent] == ' ')
1019 indent++;
1020
1021 fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
1022
1023 for (idx = 0; idx < config->run_count; idx++) {
1024 double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
1025 int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
1026
1027 fprintf(output, " %17.*f (%+.*f) ",
1028 precision, run, precision, run - avg);
1029
1030 for (h = 0; h < n; h++)
1031 fprintf(output, "#");
1032
1033 fprintf(output, "\n");
1034 }
1035
1036 fprintf(output, "\n%*s# Final result:\n", indent, "");
1037}
1038
1039static double timeval2double(struct timeval *t)
1040{
1041 return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
1042}
1043
1044static void print_footer(struct perf_stat_config *config)
1045{
1046 double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
1047 FILE *output = config->output;
1048 int n;
1049
1050 if (!config->null_run)
1051 fprintf(output, "\n");
1052
1053 if (config->run_count == 1) {
1054 fprintf(output, " %17.9f seconds time elapsed", avg);
1055
1056 if (config->ru_display) {
1057 double ru_utime = timeval2double(&config->ru_data.ru_utime);
1058 double ru_stime = timeval2double(&config->ru_data.ru_stime);
1059
1060 fprintf(output, "\n\n");
1061 fprintf(output, " %17.9f seconds user\n", ru_utime);
1062 fprintf(output, " %17.9f seconds sys\n", ru_stime);
1063 }
1064 } else {
1065 double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
1066 /*
1067 * Display at most 2 more significant
1068 * digits than the stddev inaccuracy.
1069 */
1070 int precision = get_precision(sd) + 2;
1071
1072 if (config->walltime_run_table)
1073 print_table(config, output, precision, avg);
1074
1075 fprintf(output, " %17.*f +- %.*f seconds time elapsed",
1076 precision, avg, precision, sd);
1077
1078 print_noise_pct(config, sd, avg);
1079 }
1080 fprintf(output, "\n\n");
1081
1082 if (config->print_free_counters_hint &&
1083 sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
1084 n > 0)
1085 fprintf(output,
1086"Some events weren't counted. Try disabling the NMI watchdog:\n"
1087" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1088" perf stat ...\n"
1089" echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1090
1091 if (config->print_mixed_hw_group_error)
1092 fprintf(output,
1093 "The events in group usually have to be from "
1094 "the same PMU. Try reorganizing the group.\n");
1095}
1096
1097void
1098perf_evlist__print_counters(struct perf_evlist *evlist,
1099 struct perf_stat_config *config,
1100 struct target *_target,
1101 struct timespec *ts,
1102 int argc, const char **argv)
1103{
1104 bool metric_only = config->metric_only;
1105 int interval = config->interval;
1106 struct perf_evsel *counter;
1107 char buf[64], *prefix = NULL;
1108
1109 if (interval)
1110 print_interval(config, evlist, prefix = buf, ts);
1111 else
1112 print_header(config, _target, argc, argv);
1113
1114 if (metric_only) {
1115 static int num_print_iv;
1116
1117 if (num_print_iv == 0 && !interval)
1118 print_metric_headers(config, evlist, prefix, false);
1119 if (num_print_iv++ == 25)
1120 num_print_iv = 0;
1121 if (config->aggr_mode == AGGR_GLOBAL && prefix)
1122 fprintf(config->output, "%s", prefix);
1123 }
1124
1125 switch (config->aggr_mode) {
1126 case AGGR_CORE:
1127 case AGGR_SOCKET:
1128 print_aggr(config, evlist, prefix);
1129 break;
1130 case AGGR_THREAD:
1131 evlist__for_each_entry(evlist, counter) {
1132 if (is_duration_time(counter))
1133 continue;
1134 print_aggr_thread(config, _target, counter, prefix);
1135 }
1136 break;
1137 case AGGR_GLOBAL:
1138 evlist__for_each_entry(evlist, counter) {
1139 if (is_duration_time(counter))
1140 continue;
1141 print_counter_aggr(config, counter, prefix);
1142 }
1143 if (metric_only)
1144 fputc('\n', config->output);
1145 break;
1146 case AGGR_NONE:
1147 if (metric_only)
1148 print_no_aggr_metric(config, evlist, prefix);
1149 else {
1150 evlist__for_each_entry(evlist, counter) {
1151 if (is_duration_time(counter))
1152 continue;
1153 print_counter(config, counter, prefix);
1154 }
1155 }
1156 break;
1157 case AGGR_UNSET:
1158 default:
1159 break;
1160 }
1161
1162 if (!interval && !config->csv_output)
1163 print_footer(config);
1164
1165 fflush(config->output);
1166}
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 99990f5f2512..8ad32763cfff 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -410,7 +410,8 @@ static double runtime_stat_n(struct runtime_stat *st,
410 return v->stats.n; 410 return v->stats.n;
411} 411}
412 412
413static void print_stalled_cycles_frontend(int cpu, 413static void print_stalled_cycles_frontend(struct perf_stat_config *config,
414 int cpu,
414 struct perf_evsel *evsel, double avg, 415 struct perf_evsel *evsel, double avg,
415 struct perf_stat_output_ctx *out, 416 struct perf_stat_output_ctx *out,
416 struct runtime_stat *st) 417 struct runtime_stat *st)
@@ -427,13 +428,14 @@ static void print_stalled_cycles_frontend(int cpu,
427 color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio); 428 color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
428 429
429 if (ratio) 430 if (ratio)
430 out->print_metric(out->ctx, color, "%7.2f%%", "frontend cycles idle", 431 out->print_metric(config, out->ctx, color, "%7.2f%%", "frontend cycles idle",
431 ratio); 432 ratio);
432 else 433 else
433 out->print_metric(out->ctx, NULL, NULL, "frontend cycles idle", 0); 434 out->print_metric(config, out->ctx, NULL, NULL, "frontend cycles idle", 0);
434} 435}
435 436
436static void print_stalled_cycles_backend(int cpu, 437static void print_stalled_cycles_backend(struct perf_stat_config *config,
438 int cpu,
437 struct perf_evsel *evsel, double avg, 439 struct perf_evsel *evsel, double avg,
438 struct perf_stat_output_ctx *out, 440 struct perf_stat_output_ctx *out,
439 struct runtime_stat *st) 441 struct runtime_stat *st)
@@ -449,10 +451,11 @@ static void print_stalled_cycles_backend(int cpu,
449 451
450 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); 452 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
451 453
452 out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio); 454 out->print_metric(config, out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
453} 455}
454 456
455static void print_branch_misses(int cpu, 457static void print_branch_misses(struct perf_stat_config *config,
458 int cpu,
456 struct perf_evsel *evsel, 459 struct perf_evsel *evsel,
457 double avg, 460 double avg,
458 struct perf_stat_output_ctx *out, 461 struct perf_stat_output_ctx *out,
@@ -469,10 +472,11 @@ static void print_branch_misses(int cpu,
469 472
470 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 473 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
471 474
472 out->print_metric(out->ctx, color, "%7.2f%%", "of all branches", ratio); 475 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all branches", ratio);
473} 476}
474 477
475static void print_l1_dcache_misses(int cpu, 478static void print_l1_dcache_misses(struct perf_stat_config *config,
479 int cpu,
476 struct perf_evsel *evsel, 480 struct perf_evsel *evsel,
477 double avg, 481 double avg,
478 struct perf_stat_output_ctx *out, 482 struct perf_stat_output_ctx *out,
@@ -490,10 +494,11 @@ static void print_l1_dcache_misses(int cpu,
490 494
491 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 495 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
492 496
493 out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio); 497 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
494} 498}
495 499
496static void print_l1_icache_misses(int cpu, 500static void print_l1_icache_misses(struct perf_stat_config *config,
501 int cpu,
497 struct perf_evsel *evsel, 502 struct perf_evsel *evsel,
498 double avg, 503 double avg,
499 struct perf_stat_output_ctx *out, 504 struct perf_stat_output_ctx *out,
@@ -510,10 +515,11 @@ static void print_l1_icache_misses(int cpu,
510 ratio = avg / total * 100.0; 515 ratio = avg / total * 100.0;
511 516
512 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 517 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
513 out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio); 518 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
514} 519}
515 520
516static void print_dtlb_cache_misses(int cpu, 521static void print_dtlb_cache_misses(struct perf_stat_config *config,
522 int cpu,
517 struct perf_evsel *evsel, 523 struct perf_evsel *evsel,
518 double avg, 524 double avg,
519 struct perf_stat_output_ctx *out, 525 struct perf_stat_output_ctx *out,
@@ -529,10 +535,11 @@ static void print_dtlb_cache_misses(int cpu,
529 ratio = avg / total * 100.0; 535 ratio = avg / total * 100.0;
530 536
531 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 537 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
532 out->print_metric(out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio); 538 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
533} 539}
534 540
535static void print_itlb_cache_misses(int cpu, 541static void print_itlb_cache_misses(struct perf_stat_config *config,
542 int cpu,
536 struct perf_evsel *evsel, 543 struct perf_evsel *evsel,
537 double avg, 544 double avg,
538 struct perf_stat_output_ctx *out, 545 struct perf_stat_output_ctx *out,
@@ -548,10 +555,11 @@ static void print_itlb_cache_misses(int cpu,
548 ratio = avg / total * 100.0; 555 ratio = avg / total * 100.0;
549 556
550 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 557 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
551 out->print_metric(out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio); 558 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
552} 559}
553 560
554static void print_ll_cache_misses(int cpu, 561static void print_ll_cache_misses(struct perf_stat_config *config,
562 int cpu,
555 struct perf_evsel *evsel, 563 struct perf_evsel *evsel,
556 double avg, 564 double avg,
557 struct perf_stat_output_ctx *out, 565 struct perf_stat_output_ctx *out,
@@ -567,7 +575,7 @@ static void print_ll_cache_misses(int cpu,
567 ratio = avg / total * 100.0; 575 ratio = avg / total * 100.0;
568 576
569 color = get_ratio_color(GRC_CACHE_MISSES, ratio); 577 color = get_ratio_color(GRC_CACHE_MISSES, ratio);
570 out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); 578 out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
571} 579}
572 580
573/* 581/*
@@ -674,7 +682,8 @@ static double td_be_bound(int ctx, int cpu, struct runtime_stat *st)
674 return sanitize_val(1.0 - sum); 682 return sanitize_val(1.0 - sum);
675} 683}
676 684
677static void print_smi_cost(int cpu, struct perf_evsel *evsel, 685static void print_smi_cost(struct perf_stat_config *config,
686 int cpu, struct perf_evsel *evsel,
678 struct perf_stat_output_ctx *out, 687 struct perf_stat_output_ctx *out,
679 struct runtime_stat *st) 688 struct runtime_stat *st)
680{ 689{
@@ -694,11 +703,12 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel,
694 703
695 if (cost > 10) 704 if (cost > 10)
696 color = PERF_COLOR_RED; 705 color = PERF_COLOR_RED;
697 out->print_metric(out->ctx, color, "%8.1f%%", "SMI cycles%", cost); 706 out->print_metric(config, out->ctx, color, "%8.1f%%", "SMI cycles%", cost);
698 out->print_metric(out->ctx, NULL, "%4.0f", "SMI#", smi_num); 707 out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num);
699} 708}
700 709
701static void generic_metric(const char *metric_expr, 710static void generic_metric(struct perf_stat_config *config,
711 const char *metric_expr,
702 struct perf_evsel **metric_events, 712 struct perf_evsel **metric_events,
703 char *name, 713 char *name,
704 const char *metric_name, 714 const char *metric_name,
@@ -737,20 +747,21 @@ static void generic_metric(const char *metric_expr,
737 const char *p = metric_expr; 747 const char *p = metric_expr;
738 748
739 if (expr__parse(&ratio, &pctx, &p) == 0) 749 if (expr__parse(&ratio, &pctx, &p) == 0)
740 print_metric(ctxp, NULL, "%8.1f", 750 print_metric(config, ctxp, NULL, "%8.1f",
741 metric_name ? 751 metric_name ?
742 metric_name : 752 metric_name :
743 out->force_header ? name : "", 753 out->force_header ? name : "",
744 ratio); 754 ratio);
745 else 755 else
746 print_metric(ctxp, NULL, NULL, 756 print_metric(config, ctxp, NULL, NULL,
747 out->force_header ? 757 out->force_header ?
748 (metric_name ? metric_name : name) : "", 0); 758 (metric_name ? metric_name : name) : "", 0);
749 } else 759 } else
750 print_metric(ctxp, NULL, NULL, "", 0); 760 print_metric(config, ctxp, NULL, NULL, "", 0);
751} 761}
752 762
753void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 763void perf_stat__print_shadow_stats(struct perf_stat_config *config,
764 struct perf_evsel *evsel,
754 double avg, int cpu, 765 double avg, int cpu,
755 struct perf_stat_output_ctx *out, 766 struct perf_stat_output_ctx *out,
756 struct rblist *metric_events, 767 struct rblist *metric_events,
@@ -769,10 +780,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
769 780
770 if (total) { 781 if (total) {
771 ratio = avg / total; 782 ratio = avg / total;
772 print_metric(ctxp, NULL, "%7.2f ", 783 print_metric(config, ctxp, NULL, "%7.2f ",
773 "insn per cycle", ratio); 784 "insn per cycle", ratio);
774 } else { 785 } else {
775 print_metric(ctxp, NULL, NULL, "insn per cycle", 0); 786 print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0);
776 } 787 }
777 788
778 total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT, 789 total = runtime_stat_avg(st, STAT_STALLED_CYCLES_FRONT,
@@ -783,20 +794,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
783 ctx, cpu)); 794 ctx, cpu));
784 795
785 if (total && avg) { 796 if (total && avg) {
786 out->new_line(ctxp); 797 out->new_line(config, ctxp);
787 ratio = total / avg; 798 ratio = total / avg;
788 print_metric(ctxp, NULL, "%7.2f ", 799 print_metric(config, ctxp, NULL, "%7.2f ",
789 "stalled cycles per insn", 800 "stalled cycles per insn",
790 ratio); 801 ratio);
791 } else if (have_frontend_stalled) { 802 } else if (have_frontend_stalled) {
792 print_metric(ctxp, NULL, NULL, 803 print_metric(config, ctxp, NULL, NULL,
793 "stalled cycles per insn", 0); 804 "stalled cycles per insn", 0);
794 } 805 }
795 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) { 806 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
796 if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0) 807 if (runtime_stat_n(st, STAT_BRANCHES, ctx, cpu) != 0)
797 print_branch_misses(cpu, evsel, avg, out, st); 808 print_branch_misses(config, cpu, evsel, avg, out, st);
798 else 809 else
799 print_metric(ctxp, NULL, NULL, "of all branches", 0); 810 print_metric(config, ctxp, NULL, NULL, "of all branches", 0);
800 } else if ( 811 } else if (
801 evsel->attr.type == PERF_TYPE_HW_CACHE && 812 evsel->attr.type == PERF_TYPE_HW_CACHE &&
802 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D | 813 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1D |
@@ -804,9 +815,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
804 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 815 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
805 816
806 if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0) 817 if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0)
807 print_l1_dcache_misses(cpu, evsel, avg, out, st); 818 print_l1_dcache_misses(config, cpu, evsel, avg, out, st);
808 else 819 else
809 print_metric(ctxp, NULL, NULL, "of all L1-dcache hits", 0); 820 print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0);
810 } else if ( 821 } else if (
811 evsel->attr.type == PERF_TYPE_HW_CACHE && 822 evsel->attr.type == PERF_TYPE_HW_CACHE &&
812 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I | 823 evsel->attr.config == ( PERF_COUNT_HW_CACHE_L1I |
@@ -814,9 +825,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
814 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 825 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
815 826
816 if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0) 827 if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0)
817 print_l1_icache_misses(cpu, evsel, avg, out, st); 828 print_l1_icache_misses(config, cpu, evsel, avg, out, st);
818 else 829 else
819 print_metric(ctxp, NULL, NULL, "of all L1-icache hits", 0); 830 print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0);
820 } else if ( 831 } else if (
821 evsel->attr.type == PERF_TYPE_HW_CACHE && 832 evsel->attr.type == PERF_TYPE_HW_CACHE &&
822 evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB | 833 evsel->attr.config == ( PERF_COUNT_HW_CACHE_DTLB |
@@ -824,9 +835,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
824 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 835 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
825 836
826 if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0) 837 if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0)
827 print_dtlb_cache_misses(cpu, evsel, avg, out, st); 838 print_dtlb_cache_misses(config, cpu, evsel, avg, out, st);
828 else 839 else
829 print_metric(ctxp, NULL, NULL, "of all dTLB cache hits", 0); 840 print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0);
830 } else if ( 841 } else if (
831 evsel->attr.type == PERF_TYPE_HW_CACHE && 842 evsel->attr.type == PERF_TYPE_HW_CACHE &&
832 evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB | 843 evsel->attr.config == ( PERF_COUNT_HW_CACHE_ITLB |
@@ -834,9 +845,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
834 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 845 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
835 846
836 if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0) 847 if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0)
837 print_itlb_cache_misses(cpu, evsel, avg, out, st); 848 print_itlb_cache_misses(config, cpu, evsel, avg, out, st);
838 else 849 else
839 print_metric(ctxp, NULL, NULL, "of all iTLB cache hits", 0); 850 print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0);
840 } else if ( 851 } else if (
841 evsel->attr.type == PERF_TYPE_HW_CACHE && 852 evsel->attr.type == PERF_TYPE_HW_CACHE &&
842 evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL | 853 evsel->attr.config == ( PERF_COUNT_HW_CACHE_LL |
@@ -844,9 +855,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
844 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) { 855 ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
845 856
846 if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0) 857 if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0)
847 print_ll_cache_misses(cpu, evsel, avg, out, st); 858 print_ll_cache_misses(config, cpu, evsel, avg, out, st);
848 else 859 else
849 print_metric(ctxp, NULL, NULL, "of all LL-cache hits", 0); 860 print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0);
850 } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) { 861 } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
851 total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu); 862 total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu);
852 863
@@ -854,32 +865,32 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
854 ratio = avg * 100 / total; 865 ratio = avg * 100 / total;
855 866
856 if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0) 867 if (runtime_stat_n(st, STAT_CACHEREFS, ctx, cpu) != 0)
857 print_metric(ctxp, NULL, "%8.3f %%", 868 print_metric(config, ctxp, NULL, "%8.3f %%",
858 "of all cache refs", ratio); 869 "of all cache refs", ratio);
859 else 870 else
860 print_metric(ctxp, NULL, NULL, "of all cache refs", 0); 871 print_metric(config, ctxp, NULL, NULL, "of all cache refs", 0);
861 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { 872 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
862 print_stalled_cycles_frontend(cpu, evsel, avg, out, st); 873 print_stalled_cycles_frontend(config, cpu, evsel, avg, out, st);
863 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) { 874 } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
864 print_stalled_cycles_backend(cpu, evsel, avg, out, st); 875 print_stalled_cycles_backend(config, cpu, evsel, avg, out, st);
865 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 876 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
866 total = runtime_stat_avg(st, STAT_NSECS, 0, cpu); 877 total = runtime_stat_avg(st, STAT_NSECS, 0, cpu);
867 878
868 if (total) { 879 if (total) {
869 ratio = avg / total; 880 ratio = avg / total;
870 print_metric(ctxp, NULL, "%8.3f", "GHz", ratio); 881 print_metric(config, ctxp, NULL, "%8.3f", "GHz", ratio);
871 } else { 882 } else {
872 print_metric(ctxp, NULL, NULL, "Ghz", 0); 883 print_metric(config, ctxp, NULL, NULL, "Ghz", 0);
873 } 884 }
874 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) { 885 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) {
875 total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu); 886 total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
876 887
877 if (total) 888 if (total)
878 print_metric(ctxp, NULL, 889 print_metric(config, ctxp, NULL,
879 "%7.2f%%", "transactional cycles", 890 "%7.2f%%", "transactional cycles",
880 100.0 * (avg / total)); 891 100.0 * (avg / total));
881 else 892 else
882 print_metric(ctxp, NULL, NULL, "transactional cycles", 893 print_metric(config, ctxp, NULL, NULL, "transactional cycles",
883 0); 894 0);
884 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) { 895 } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) {
885 total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu); 896 total = runtime_stat_avg(st, STAT_CYCLES, ctx, cpu);
@@ -888,10 +899,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
888 if (total2 < avg) 899 if (total2 < avg)
889 total2 = avg; 900 total2 = avg;
890 if (total) 901 if (total)
891 print_metric(ctxp, NULL, "%7.2f%%", "aborted cycles", 902 print_metric(config, ctxp, NULL, "%7.2f%%", "aborted cycles",
892 100.0 * ((total2-avg) / total)); 903 100.0 * ((total2-avg) / total));
893 else 904 else
894 print_metric(ctxp, NULL, NULL, "aborted cycles", 0); 905 print_metric(config, ctxp, NULL, NULL, "aborted cycles", 0);
895 } else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) { 906 } else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) {
896 total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, 907 total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
897 ctx, cpu); 908 ctx, cpu);
@@ -900,10 +911,10 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
900 ratio = total / avg; 911 ratio = total / avg;
901 912
902 if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0) 913 if (runtime_stat_n(st, STAT_CYCLES_IN_TX, ctx, cpu) != 0)
903 print_metric(ctxp, NULL, "%8.0f", 914 print_metric(config, ctxp, NULL, "%8.0f",
904 "cycles / transaction", ratio); 915 "cycles / transaction", ratio);
905 else 916 else
906 print_metric(ctxp, NULL, NULL, "cycles / transaction", 917 print_metric(config, ctxp, NULL, NULL, "cycles / transaction",
907 0); 918 0);
908 } else if (perf_stat_evsel__is(evsel, ELISION_START)) { 919 } else if (perf_stat_evsel__is(evsel, ELISION_START)) {
909 total = runtime_stat_avg(st, STAT_CYCLES_IN_TX, 920 total = runtime_stat_avg(st, STAT_CYCLES_IN_TX,
@@ -912,33 +923,33 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
912 if (avg) 923 if (avg)
913 ratio = total / avg; 924 ratio = total / avg;
914 925
915 print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio); 926 print_metric(config, ctxp, NULL, "%8.0f", "cycles / elision", ratio);
916 } else if (perf_evsel__is_clock(evsel)) { 927 } else if (perf_evsel__is_clock(evsel)) {
917 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0) 928 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
918 print_metric(ctxp, NULL, "%8.3f", "CPUs utilized", 929 print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized",
919 avg / (ratio * evsel->scale)); 930 avg / (ratio * evsel->scale));
920 else 931 else
921 print_metric(ctxp, NULL, NULL, "CPUs utilized", 0); 932 print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0);
922 } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) { 933 } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) {
923 double fe_bound = td_fe_bound(ctx, cpu, st); 934 double fe_bound = td_fe_bound(ctx, cpu, st);
924 935
925 if (fe_bound > 0.2) 936 if (fe_bound > 0.2)
926 color = PERF_COLOR_RED; 937 color = PERF_COLOR_RED;
927 print_metric(ctxp, color, "%8.1f%%", "frontend bound", 938 print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
928 fe_bound * 100.); 939 fe_bound * 100.);
929 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) { 940 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) {
930 double retiring = td_retiring(ctx, cpu, st); 941 double retiring = td_retiring(ctx, cpu, st);
931 942
932 if (retiring > 0.7) 943 if (retiring > 0.7)
933 color = PERF_COLOR_GREEN; 944 color = PERF_COLOR_GREEN;
934 print_metric(ctxp, color, "%8.1f%%", "retiring", 945 print_metric(config, ctxp, color, "%8.1f%%", "retiring",
935 retiring * 100.); 946 retiring * 100.);
936 } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) { 947 } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) {
937 double bad_spec = td_bad_spec(ctx, cpu, st); 948 double bad_spec = td_bad_spec(ctx, cpu, st);
938 949
939 if (bad_spec > 0.1) 950 if (bad_spec > 0.1)
940 color = PERF_COLOR_RED; 951 color = PERF_COLOR_RED;
941 print_metric(ctxp, color, "%8.1f%%", "bad speculation", 952 print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
942 bad_spec * 100.); 953 bad_spec * 100.);
943 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) { 954 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) {
944 double be_bound = td_be_bound(ctx, cpu, st); 955 double be_bound = td_be_bound(ctx, cpu, st);
@@ -955,12 +966,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
955 if (be_bound > 0.2) 966 if (be_bound > 0.2)
956 color = PERF_COLOR_RED; 967 color = PERF_COLOR_RED;
957 if (td_total_slots(ctx, cpu, st) > 0) 968 if (td_total_slots(ctx, cpu, st) > 0)
958 print_metric(ctxp, color, "%8.1f%%", name, 969 print_metric(config, ctxp, color, "%8.1f%%", name,
959 be_bound * 100.); 970 be_bound * 100.);
960 else 971 else
961 print_metric(ctxp, NULL, NULL, name, 0); 972 print_metric(config, ctxp, NULL, NULL, name, 0);
962 } else if (evsel->metric_expr) { 973 } else if (evsel->metric_expr) {
963 generic_metric(evsel->metric_expr, evsel->metric_events, evsel->name, 974 generic_metric(config, evsel->metric_expr, evsel->metric_events, evsel->name,
964 evsel->metric_name, avg, cpu, out, st); 975 evsel->metric_name, avg, cpu, out, st);
965 } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) { 976 } else if (runtime_stat_n(st, STAT_NSECS, 0, cpu) != 0) {
966 char unit = 'M'; 977 char unit = 'M';
@@ -975,9 +986,9 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
975 unit = 'K'; 986 unit = 'K';
976 } 987 }
977 snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit); 988 snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
978 print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio); 989 print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio);
979 } else if (perf_stat_evsel__is(evsel, SMI_NUM)) { 990 } else if (perf_stat_evsel__is(evsel, SMI_NUM)) {
980 print_smi_cost(cpu, evsel, out, st); 991 print_smi_cost(config, cpu, evsel, out, st);
981 } else { 992 } else {
982 num = 0; 993 num = 0;
983 } 994 }
@@ -987,12 +998,12 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
987 998
988 list_for_each_entry (mexp, &me->head, nd) { 999 list_for_each_entry (mexp, &me->head, nd) {
989 if (num++ > 0) 1000 if (num++ > 0)
990 out->new_line(ctxp); 1001 out->new_line(config, ctxp);
991 generic_metric(mexp->metric_expr, mexp->metric_events, 1002 generic_metric(config, mexp->metric_expr, mexp->metric_events,
992 evsel->name, mexp->metric_name, 1003 evsel->name, mexp->metric_name,
993 avg, cpu, out, st); 1004 avg, cpu, out, st);
994 } 1005 }
995 } 1006 }
996 if (num == 0) 1007 if (num == 0)
997 print_metric(ctxp, NULL, NULL, NULL, 0); 1008 print_metric(config, ctxp, NULL, NULL, NULL, 0);
998} 1009}
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index a0061e0b0fad..4d40515307b8 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -374,9 +374,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
374 return 0; 374 return 0;
375} 375}
376 376
377int perf_event__process_stat_event(struct perf_tool *tool __maybe_unused, 377int perf_event__process_stat_event(struct perf_session *session,
378 union perf_event *event, 378 union perf_event *event)
379 struct perf_session *session)
380{ 379{
381 struct perf_counts_values count; 380 struct perf_counts_values count;
382 struct stat_event *st = &event->stat; 381 struct stat_event *st = &event->stat;
@@ -435,3 +434,98 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
435 434
436 return ret; 435 return ret;
437} 436}
437
438int create_perf_stat_counter(struct perf_evsel *evsel,
439 struct perf_stat_config *config,
440 struct target *target)
441{
442 struct perf_event_attr *attr = &evsel->attr;
443 struct perf_evsel *leader = evsel->leader;
444
445 if (config->scale) {
446 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
447 PERF_FORMAT_TOTAL_TIME_RUNNING;
448 }
449
450 /*
451 * The event is part of non trivial group, let's enable
452 * the group read (for leader) and ID retrieval for all
453 * members.
454 */
455 if (leader->nr_members > 1)
456 attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
457
458 attr->inherit = !config->no_inherit;
459
460 /*
461 * Some events get initialized with sample_(period/type) set,
462 * like tracepoints. Clear it up for counting.
463 */
464 attr->sample_period = 0;
465
466 if (config->identifier)
467 attr->sample_type = PERF_SAMPLE_IDENTIFIER;
468
469 /*
470 * Disabling all counters initially, they will be enabled
471 * either manually by us or by kernel via enable_on_exec
472 * set later.
473 */
474 if (perf_evsel__is_group_leader(evsel)) {
475 attr->disabled = 1;
476
477 /*
478 * In case of initial_delay we enable tracee
479 * events manually.
480 */
481 if (target__none(target) && !config->initial_delay)
482 attr->enable_on_exec = 1;
483 }
484
485 if (target__has_cpu(target) && !target__has_per_thread(target))
486 return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
487
488 return perf_evsel__open_per_thread(evsel, evsel->threads);
489}
490
491int perf_stat_synthesize_config(struct perf_stat_config *config,
492 struct perf_tool *tool,
493 struct perf_evlist *evlist,
494 perf_event__handler_t process,
495 bool attrs)
496{
497 int err;
498
499 if (attrs) {
500 err = perf_event__synthesize_attrs(tool, evlist, process);
501 if (err < 0) {
502 pr_err("Couldn't synthesize attrs.\n");
503 return err;
504 }
505 }
506
507 err = perf_event__synthesize_extra_attr(tool, evlist, process,
508 attrs);
509
510 err = perf_event__synthesize_thread_map2(tool, evlist->threads,
511 process, NULL);
512 if (err < 0) {
513 pr_err("Couldn't synthesize thread map.\n");
514 return err;
515 }
516
517 err = perf_event__synthesize_cpu_map(tool, evlist->cpus,
518 process, NULL);
519 if (err < 0) {
520 pr_err("Couldn't synthesize thread map.\n");
521 return err;
522 }
523
524 err = perf_event__synthesize_stat_config(tool, config, process, NULL);
525 if (err < 0) {
526 pr_err("Couldn't synthesize config.\n");
527 return err;
528 }
529
530 return 0;
531}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 36efb986f7fc..2f9c9159a364 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -4,8 +4,14 @@
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <stdio.h> 6#include <stdio.h>
7#include <sys/types.h>
8#include <sys/time.h>
9#include <sys/resource.h>
10#include <sys/wait.h>
7#include "xyarray.h" 11#include "xyarray.h"
8#include "rblist.h" 12#include "rblist.h"
13#include "perf.h"
14#include "event.h"
9 15
10struct stats { 16struct stats {
11 double n, mean, M2; 17 double n, mean, M2;
@@ -84,15 +90,42 @@ struct runtime_stat {
84 struct rblist value_list; 90 struct rblist value_list;
85}; 91};
86 92
93typedef int (*aggr_get_id_t)(struct perf_stat_config *config,
94 struct cpu_map *m, int cpu);
95
87struct perf_stat_config { 96struct perf_stat_config {
88 enum aggr_mode aggr_mode; 97 enum aggr_mode aggr_mode;
89 bool scale; 98 bool scale;
90 FILE *output; 99 bool no_inherit;
91 unsigned int interval; 100 bool identifier;
92 unsigned int timeout; 101 bool csv_output;
93 int times; 102 bool interval_clear;
94 struct runtime_stat *stats; 103 bool metric_only;
95 int stats_num; 104 bool null_run;
105 bool ru_display;
106 bool big_num;
107 bool no_merge;
108 bool walltime_run_table;
109 FILE *output;
110 unsigned int interval;
111 unsigned int timeout;
112 unsigned int initial_delay;
113 unsigned int unit_width;
114 unsigned int metric_only_len;
115 int times;
116 int run_count;
117 int print_free_counters_hint;
118 int print_mixed_hw_group_error;
119 struct runtime_stat *stats;
120 int stats_num;
121 const char *csv_sep;
122 struct stats *walltime_nsecs_stats;
123 struct rusage ru_data;
124 struct cpu_map *aggr_map;
125 aggr_get_id_t aggr_get_id;
126 struct cpu_map *cpus_aggr_map;
127 u64 *walltime_run;
128 struct rblist metric_events;
96}; 129};
97 130
98void update_stats(struct stats *stats, u64 val); 131void update_stats(struct stats *stats, u64 val);
@@ -130,9 +163,10 @@ bool __perf_evsel_stat__is(struct perf_evsel *evsel,
130extern struct runtime_stat rt_stat; 163extern struct runtime_stat rt_stat;
131extern struct stats walltime_nsecs_stats; 164extern struct stats walltime_nsecs_stats;
132 165
133typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit, 166typedef void (*print_metric_t)(struct perf_stat_config *config,
167 void *ctx, const char *color, const char *unit,
134 const char *fmt, double val); 168 const char *fmt, double val);
135typedef void (*new_line_t )(void *ctx); 169typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx);
136 170
137void runtime_stat__init(struct runtime_stat *st); 171void runtime_stat__init(struct runtime_stat *st);
138void runtime_stat__exit(struct runtime_stat *st); 172void runtime_stat__exit(struct runtime_stat *st);
@@ -148,7 +182,8 @@ struct perf_stat_output_ctx {
148 bool force_header; 182 bool force_header;
149}; 183};
150 184
151void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 185void perf_stat__print_shadow_stats(struct perf_stat_config *config,
186 struct perf_evsel *evsel,
152 double avg, int cpu, 187 double avg, int cpu,
153 struct perf_stat_output_ctx *out, 188 struct perf_stat_output_ctx *out,
154 struct rblist *metric_events, 189 struct rblist *metric_events,
@@ -164,11 +199,25 @@ int perf_stat_process_counter(struct perf_stat_config *config,
164struct perf_tool; 199struct perf_tool;
165union perf_event; 200union perf_event;
166struct perf_session; 201struct perf_session;
167int perf_event__process_stat_event(struct perf_tool *tool, 202int perf_event__process_stat_event(struct perf_session *session,
168 union perf_event *event, 203 union perf_event *event);
169 struct perf_session *session);
170 204
171size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp); 205size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp);
172size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp); 206size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp);
173size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp); 207size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
208
209int create_perf_stat_counter(struct perf_evsel *evsel,
210 struct perf_stat_config *config,
211 struct target *target);
212int perf_stat_synthesize_config(struct perf_stat_config *config,
213 struct perf_tool *tool,
214 struct perf_evlist *evlist,
215 perf_event__handler_t process,
216 bool attrs);
217void
218perf_evlist__print_counters(struct perf_evlist *evlist,
219 struct perf_stat_config *config,
220 struct target *_target,
221 struct timespec *ts,
222 int argc, const char **argv);
174#endif 223#endif
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 3d1cf5bf7f18..9005fbe0780e 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -98,19 +98,25 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
98 98
99 va_copy(ap_saved, ap); 99 va_copy(ap_saved, ap);
100 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 100 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
101 if (len < 0) 101 if (len < 0) {
102 va_end(ap_saved);
102 return len; 103 return len;
104 }
103 if (len > strbuf_avail(sb)) { 105 if (len > strbuf_avail(sb)) {
104 ret = strbuf_grow(sb, len); 106 ret = strbuf_grow(sb, len);
105 if (ret) 107 if (ret) {
108 va_end(ap_saved);
106 return ret; 109 return ret;
110 }
107 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); 111 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
108 va_end(ap_saved); 112 va_end(ap_saved);
109 if (len > strbuf_avail(sb)) { 113 if (len > strbuf_avail(sb)) {
110 pr_debug("this should not happen, your vsnprintf is broken"); 114 pr_debug("this should not happen, your vsnprintf is broken");
115 va_end(ap_saved);
111 return -EINVAL; 116 return -EINVAL;
112 } 117 }
113 } 118 }
119 va_end(ap_saved);
114 return strbuf_setlen(sb, sb->len + len); 120 return strbuf_setlen(sb, sb->len + len);
115} 121}
116 122
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 29770ea61768..66a84d5846c8 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -324,7 +324,17 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
324 plt_entry_size = 16; 324 plt_entry_size = 16;
325 break; 325 break;
326 326
327 default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa need to be checked */ 327 case EM_SPARC:
328 plt_header_size = 48;
329 plt_entry_size = 12;
330 break;
331
332 case EM_SPARCV9:
333 plt_header_size = 128;
334 plt_entry_size = 32;
335 break;
336
337 default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/xtensa need to be checked */
328 plt_header_size = shdr_plt.sh_entsize; 338 plt_header_size = shdr_plt.sh_entsize;
329 plt_entry_size = shdr_plt.sh_entsize; 339 plt_entry_size = shdr_plt.sh_entsize;
330 break; 340 break;
@@ -1947,6 +1957,34 @@ void kcore_extract__delete(struct kcore_extract *kce)
1947} 1957}
1948 1958
1949#ifdef HAVE_GELF_GETNOTE_SUPPORT 1959#ifdef HAVE_GELF_GETNOTE_SUPPORT
1960
1961static void sdt_adjust_loc(struct sdt_note *tmp, GElf_Addr base_off)
1962{
1963 if (!base_off)
1964 return;
1965
1966 if (tmp->bit32)
1967 tmp->addr.a32[SDT_NOTE_IDX_LOC] =
1968 tmp->addr.a32[SDT_NOTE_IDX_LOC] + base_off -
1969 tmp->addr.a32[SDT_NOTE_IDX_BASE];
1970 else
1971 tmp->addr.a64[SDT_NOTE_IDX_LOC] =
1972 tmp->addr.a64[SDT_NOTE_IDX_LOC] + base_off -
1973 tmp->addr.a64[SDT_NOTE_IDX_BASE];
1974}
1975
1976static void sdt_adjust_refctr(struct sdt_note *tmp, GElf_Addr base_addr,
1977 GElf_Addr base_off)
1978{
1979 if (!base_off)
1980 return;
1981
1982 if (tmp->bit32 && tmp->addr.a32[SDT_NOTE_IDX_REFCTR])
1983 tmp->addr.a32[SDT_NOTE_IDX_REFCTR] -= (base_addr - base_off);
1984 else if (tmp->addr.a64[SDT_NOTE_IDX_REFCTR])
1985 tmp->addr.a64[SDT_NOTE_IDX_REFCTR] -= (base_addr - base_off);
1986}
1987
1950/** 1988/**
1951 * populate_sdt_note : Parse raw data and identify SDT note 1989 * populate_sdt_note : Parse raw data and identify SDT note
1952 * @elf: elf of the opened file 1990 * @elf: elf of the opened file
@@ -1964,7 +2002,6 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
1964 const char *provider, *name, *args; 2002 const char *provider, *name, *args;
1965 struct sdt_note *tmp = NULL; 2003 struct sdt_note *tmp = NULL;
1966 GElf_Ehdr ehdr; 2004 GElf_Ehdr ehdr;
1967 GElf_Addr base_off = 0;
1968 GElf_Shdr shdr; 2005 GElf_Shdr shdr;
1969 int ret = -EINVAL; 2006 int ret = -EINVAL;
1970 2007
@@ -2060,17 +2097,12 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
2060 * base address in the description of the SDT note. If its different, 2097 * base address in the description of the SDT note. If its different,
2061 * then accordingly, adjust the note location. 2098 * then accordingly, adjust the note location.
2062 */ 2099 */
2063 if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) { 2100 if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL))
2064 base_off = shdr.sh_offset; 2101 sdt_adjust_loc(tmp, shdr.sh_offset);
2065 if (base_off) { 2102
2066 if (tmp->bit32) 2103 /* Adjust reference counter offset */
2067 tmp->addr.a32[0] = tmp->addr.a32[0] + base_off - 2104 if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_PROBES_SCN, NULL))
2068 tmp->addr.a32[1]; 2105 sdt_adjust_refctr(tmp, shdr.sh_addr, shdr.sh_offset);
2069 else
2070 tmp->addr.a64[0] = tmp->addr.a64[0] + base_off -
2071 tmp->addr.a64[1];
2072 }
2073 }
2074 2106
2075 list_add_tail(&tmp->note_list, sdt_notes); 2107 list_add_tail(&tmp->note_list, sdt_notes);
2076 return 0; 2108 return 0;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index f25fae4b5743..d026d215bdc6 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -123,7 +123,8 @@ struct symbol_conf {
123 const char *vmlinux_name, 123 const char *vmlinux_name,
124 *kallsyms_name, 124 *kallsyms_name,
125 *source_prefix, 125 *source_prefix,
126 *field_sep; 126 *field_sep,
127 *graph_function;
127 const char *default_guest_vmlinux_name, 128 const char *default_guest_vmlinux_name,
128 *default_guest_kallsyms, 129 *default_guest_kallsyms,
129 *default_guest_modules; 130 *default_guest_modules;
@@ -379,12 +380,19 @@ int get_sdt_note_list(struct list_head *head, const char *target);
379int cleanup_sdt_note_list(struct list_head *sdt_notes); 380int cleanup_sdt_note_list(struct list_head *sdt_notes);
380int sdt_notes__get_count(struct list_head *start); 381int sdt_notes__get_count(struct list_head *start);
381 382
383#define SDT_PROBES_SCN ".probes"
382#define SDT_BASE_SCN ".stapsdt.base" 384#define SDT_BASE_SCN ".stapsdt.base"
383#define SDT_NOTE_SCN ".note.stapsdt" 385#define SDT_NOTE_SCN ".note.stapsdt"
384#define SDT_NOTE_TYPE 3 386#define SDT_NOTE_TYPE 3
385#define SDT_NOTE_NAME "stapsdt" 387#define SDT_NOTE_NAME "stapsdt"
386#define NR_ADDR 3 388#define NR_ADDR 3
387 389
390enum {
391 SDT_NOTE_IDX_LOC = 0,
392 SDT_NOTE_IDX_BASE,
393 SDT_NOTE_IDX_REFCTR,
394};
395
388struct mem_info *mem_info__new(void); 396struct mem_info *mem_info__new(void);
389struct mem_info *mem_info__get(struct mem_info *mi); 397struct mem_info *mem_info__get(struct mem_info *mi);
390void mem_info__put(struct mem_info *mi); 398void mem_info__put(struct mem_info *mi);
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index dd17d6a38d3a..61a4286a74dc 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -36,6 +36,7 @@
36 * @branch_count: the branch count when the entry was created 36 * @branch_count: the branch count when the entry was created
37 * @cp: call path 37 * @cp: call path
38 * @no_call: a 'call' was not seen 38 * @no_call: a 'call' was not seen
39 * @trace_end: a 'call' but trace ended
39 */ 40 */
40struct thread_stack_entry { 41struct thread_stack_entry {
41 u64 ret_addr; 42 u64 ret_addr;
@@ -44,6 +45,7 @@ struct thread_stack_entry {
44 u64 branch_count; 45 u64 branch_count;
45 struct call_path *cp; 46 struct call_path *cp;
46 bool no_call; 47 bool no_call;
48 bool trace_end;
47}; 49};
48 50
49/** 51/**
@@ -112,7 +114,8 @@ static struct thread_stack *thread_stack__new(struct thread *thread,
112 return ts; 114 return ts;
113} 115}
114 116
115static int thread_stack__push(struct thread_stack *ts, u64 ret_addr) 117static int thread_stack__push(struct thread_stack *ts, u64 ret_addr,
118 bool trace_end)
116{ 119{
117 int err = 0; 120 int err = 0;
118 121
@@ -124,6 +127,7 @@ static int thread_stack__push(struct thread_stack *ts, u64 ret_addr)
124 } 127 }
125 } 128 }
126 129
130 ts->stack[ts->cnt].trace_end = trace_end;
127 ts->stack[ts->cnt++].ret_addr = ret_addr; 131 ts->stack[ts->cnt++].ret_addr = ret_addr;
128 132
129 return err; 133 return err;
@@ -150,6 +154,18 @@ static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr)
150 } 154 }
151} 155}
152 156
157static void thread_stack__pop_trace_end(struct thread_stack *ts)
158{
159 size_t i;
160
161 for (i = ts->cnt; i; ) {
162 if (ts->stack[--i].trace_end)
163 ts->cnt = i;
164 else
165 return;
166 }
167}
168
153static bool thread_stack__in_kernel(struct thread_stack *ts) 169static bool thread_stack__in_kernel(struct thread_stack *ts)
154{ 170{
155 if (!ts->cnt) 171 if (!ts->cnt)
@@ -254,10 +270,19 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
254 ret_addr = from_ip + insn_len; 270 ret_addr = from_ip + insn_len;
255 if (ret_addr == to_ip) 271 if (ret_addr == to_ip)
256 return 0; /* Zero-length calls are excluded */ 272 return 0; /* Zero-length calls are excluded */
257 return thread_stack__push(thread->ts, ret_addr); 273 return thread_stack__push(thread->ts, ret_addr,
258 } else if (flags & PERF_IP_FLAG_RETURN) { 274 flags & PERF_IP_FLAG_TRACE_END);
259 if (!from_ip) 275 } else if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
260 return 0; 276 /*
277 * If the caller did not change the trace number (which would
278 * have flushed the stack) then try to make sense of the stack.
279 * Possibly, tracing began after returning to the current
280 * address, so try to pop that. Also, do not expect a call made
281 * when the trace ended, to return, so pop that.
282 */
283 thread_stack__pop(thread->ts, to_ip);
284 thread_stack__pop_trace_end(thread->ts);
285 } else if ((flags & PERF_IP_FLAG_RETURN) && from_ip) {
261 thread_stack__pop(thread->ts, to_ip); 286 thread_stack__pop(thread->ts, to_ip);
262 } 287 }
263 288
@@ -285,20 +310,46 @@ void thread_stack__free(struct thread *thread)
285 } 310 }
286} 311}
287 312
313static inline u64 callchain_context(u64 ip, u64 kernel_start)
314{
315 return ip < kernel_start ? PERF_CONTEXT_USER : PERF_CONTEXT_KERNEL;
316}
317
288void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 318void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
289 size_t sz, u64 ip) 319 size_t sz, u64 ip, u64 kernel_start)
290{ 320{
291 size_t i; 321 u64 context = callchain_context(ip, kernel_start);
322 u64 last_context;
323 size_t i, j;
292 324
293 if (!thread || !thread->ts) 325 if (sz < 2) {
294 chain->nr = 1; 326 chain->nr = 0;
295 else 327 return;
296 chain->nr = min(sz, thread->ts->cnt + 1); 328 }
329
330 chain->ips[0] = context;
331 chain->ips[1] = ip;
297 332
298 chain->ips[0] = ip; 333 if (!thread || !thread->ts) {
334 chain->nr = 2;
335 return;
336 }
337
338 last_context = context;
339
340 for (i = 2, j = 1; i < sz && j <= thread->ts->cnt; i++, j++) {
341 ip = thread->ts->stack[thread->ts->cnt - j].ret_addr;
342 context = callchain_context(ip, kernel_start);
343 if (context != last_context) {
344 if (i >= sz - 1)
345 break;
346 chain->ips[i++] = context;
347 last_context = context;
348 }
349 chain->ips[i] = ip;
350 }
299 351
300 for (i = 1; i < chain->nr; i++) 352 chain->nr = i;
301 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;
302} 353}
303 354
304struct call_return_processor * 355struct call_return_processor *
@@ -332,7 +383,7 @@ void call_return_processor__free(struct call_return_processor *crp)
332 383
333static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr, 384static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
334 u64 timestamp, u64 ref, struct call_path *cp, 385 u64 timestamp, u64 ref, struct call_path *cp,
335 bool no_call) 386 bool no_call, bool trace_end)
336{ 387{
337 struct thread_stack_entry *tse; 388 struct thread_stack_entry *tse;
338 int err; 389 int err;
@@ -350,6 +401,7 @@ static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
350 tse->branch_count = ts->branch_count; 401 tse->branch_count = ts->branch_count;
351 tse->cp = cp; 402 tse->cp = cp;
352 tse->no_call = no_call; 403 tse->no_call = no_call;
404 tse->trace_end = trace_end;
353 405
354 return 0; 406 return 0;
355} 407}
@@ -423,7 +475,7 @@ static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts,
423 return -ENOMEM; 475 return -ENOMEM;
424 476
425 return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp, 477 return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp,
426 true); 478 true, false);
427} 479}
428 480
429static int thread_stack__no_call_return(struct thread *thread, 481static int thread_stack__no_call_return(struct thread *thread,
@@ -455,7 +507,7 @@ static int thread_stack__no_call_return(struct thread *thread,
455 if (!cp) 507 if (!cp)
456 return -ENOMEM; 508 return -ENOMEM;
457 return thread_stack__push_cp(ts, 0, sample->time, ref, 509 return thread_stack__push_cp(ts, 0, sample->time, ref,
458 cp, true); 510 cp, true, false);
459 } 511 }
460 } else if (thread_stack__in_kernel(ts) && sample->ip < ks) { 512 } else if (thread_stack__in_kernel(ts) && sample->ip < ks) {
461 /* Return to userspace, so pop all kernel addresses */ 513 /* Return to userspace, so pop all kernel addresses */
@@ -480,7 +532,7 @@ static int thread_stack__no_call_return(struct thread *thread,
480 return -ENOMEM; 532 return -ENOMEM;
481 533
482 err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp, 534 err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp,
483 true); 535 true, false);
484 if (err) 536 if (err)
485 return err; 537 return err;
486 538
@@ -500,7 +552,7 @@ static int thread_stack__trace_begin(struct thread *thread,
500 552
501 /* Pop trace end */ 553 /* Pop trace end */
502 tse = &ts->stack[ts->cnt - 1]; 554 tse = &ts->stack[ts->cnt - 1];
503 if (tse->cp->sym == NULL && tse->cp->ip == 0) { 555 if (tse->trace_end) {
504 err = thread_stack__call_return(thread, ts, --ts->cnt, 556 err = thread_stack__call_return(thread, ts, --ts->cnt,
505 timestamp, ref, false); 557 timestamp, ref, false);
506 if (err) 558 if (err)
@@ -529,7 +581,7 @@ static int thread_stack__trace_end(struct thread_stack *ts,
529 ret_addr = sample->ip + sample->insn_len; 581 ret_addr = sample->ip + sample->insn_len;
530 582
531 return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp, 583 return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp,
532 false); 584 false, true);
533} 585}
534 586
535int thread_stack__process(struct thread *thread, struct comm *comm, 587int thread_stack__process(struct thread *thread, struct comm *comm,
@@ -579,6 +631,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
579 ts->last_time = sample->time; 631 ts->last_time = sample->time;
580 632
581 if (sample->flags & PERF_IP_FLAG_CALL) { 633 if (sample->flags & PERF_IP_FLAG_CALL) {
634 bool trace_end = sample->flags & PERF_IP_FLAG_TRACE_END;
582 struct call_path_root *cpr = ts->crp->cpr; 635 struct call_path_root *cpr = ts->crp->cpr;
583 struct call_path *cp; 636 struct call_path *cp;
584 u64 ret_addr; 637 u64 ret_addr;
@@ -596,7 +649,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
596 if (!cp) 649 if (!cp)
597 return -ENOMEM; 650 return -ENOMEM;
598 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref, 651 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
599 cp, false); 652 cp, false, trace_end);
600 } else if (sample->flags & PERF_IP_FLAG_RETURN) { 653 } else if (sample->flags & PERF_IP_FLAG_RETURN) {
601 if (!sample->ip || !sample->addr) 654 if (!sample->ip || !sample->addr)
602 return 0; 655 return 0;
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index b7e41c4ebfdd..f97c00a8c251 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -84,7 +84,7 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
84 u64 to_ip, u16 insn_len, u64 trace_nr); 84 u64 to_ip, u16 insn_len, u64 trace_nr);
85void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); 85void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
86void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, 86void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
87 size_t sz, u64 ip); 87 size_t sz, u64 ip, u64 kernel_start);
88int thread_stack__flush(struct thread *thread); 88int thread_stack__flush(struct thread *thread);
89void thread_stack__free(struct thread *thread); 89void thread_stack__free(struct thread *thread);
90size_t thread_stack__depth(struct thread *thread); 90size_t thread_stack__depth(struct thread *thread);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 2048d393ece6..3d9ed7d0e281 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -330,7 +330,8 @@ static int thread__prepare_access(struct thread *thread)
330} 330}
331 331
332static int thread__clone_map_groups(struct thread *thread, 332static int thread__clone_map_groups(struct thread *thread,
333 struct thread *parent) 333 struct thread *parent,
334 bool do_maps_clone)
334{ 335{
335 /* This is new thread, we share map groups for process. */ 336 /* This is new thread, we share map groups for process. */
336 if (thread->pid_ == parent->pid_) 337 if (thread->pid_ == parent->pid_)
@@ -341,15 +342,11 @@ static int thread__clone_map_groups(struct thread *thread,
341 thread->pid_, thread->tid, parent->pid_, parent->tid); 342 thread->pid_, thread->tid, parent->pid_, parent->tid);
342 return 0; 343 return 0;
343 } 344 }
344
345 /* But this one is new process, copy maps. */ 345 /* But this one is new process, copy maps. */
346 if (map_groups__clone(thread, parent->mg) < 0) 346 return do_maps_clone ? map_groups__clone(thread, parent->mg) : 0;
347 return -ENOMEM;
348
349 return 0;
350} 347}
351 348
352int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) 349int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone)
353{ 350{
354 if (parent->comm_set) { 351 if (parent->comm_set) {
355 const char *comm = thread__comm_str(parent); 352 const char *comm = thread__comm_str(parent);
@@ -362,7 +359,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
362 } 359 }
363 360
364 thread->ppid = parent->tid; 361 thread->ppid = parent->tid;
365 return thread__clone_map_groups(thread, parent); 362 return thread__clone_map_groups(thread, parent, do_maps_clone);
366} 363}
367 364
368void thread__find_cpumode_addr_location(struct thread *thread, u64 addr, 365void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 07606aa6998d..30e2b4c165fe 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -42,6 +42,8 @@ struct thread {
42 void *addr_space; 42 void *addr_space;
43 struct unwind_libunwind_ops *unwind_libunwind_ops; 43 struct unwind_libunwind_ops *unwind_libunwind_ops;
44#endif 44#endif
45 bool filter;
46 int filter_entry_depth;
45}; 47};
46 48
47struct machine; 49struct machine;
@@ -87,7 +89,7 @@ struct comm *thread__comm(const struct thread *thread);
87struct comm *thread__exec_comm(const struct thread *thread); 89struct comm *thread__exec_comm(const struct thread *thread);
88const char *thread__comm_str(const struct thread *thread); 90const char *thread__comm_str(const struct thread *thread);
89int thread__insert_map(struct thread *thread, struct map *map); 91int thread__insert_map(struct thread *thread, struct map *map);
90int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 92int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone);
91size_t thread__fprintf(struct thread *thread, FILE *fp); 93size_t thread__fprintf(struct thread *thread, FILE *fp);
92 94
93struct thread *thread__main_thread(struct machine *machine, struct thread *thread); 95struct thread *thread__main_thread(struct machine *machine, struct thread *thread);
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 183c91453522..56e4ca54020a 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -26,15 +26,12 @@ typedef int (*event_attr_op)(struct perf_tool *tool,
26 union perf_event *event, 26 union perf_event *event,
27 struct perf_evlist **pevlist); 27 struct perf_evlist **pevlist);
28 28
29typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event, 29typedef int (*event_op2)(struct perf_session *session, union perf_event *event);
30 struct perf_session *session); 30typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event);
31 31
32typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event, 32typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
33 struct ordered_events *oe); 33 struct ordered_events *oe);
34 34
35typedef s64 (*event_op3)(struct perf_tool *tool, union perf_event *event,
36 struct perf_session *session);
37
38enum show_feature_header { 35enum show_feature_header {
39 SHOW_FEAT_NO_HEADER = 0, 36 SHOW_FEAT_NO_HEADER = 0,
40 SHOW_FEAT_HEADER, 37 SHOW_FEAT_HEADER,
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 7b0ca7cbb7de..8ad8e755127b 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -531,12 +531,14 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs,
531 "/tmp/perf-XXXXXX"); 531 "/tmp/perf-XXXXXX");
532 if (!mkstemp(tdata->temp_file)) { 532 if (!mkstemp(tdata->temp_file)) {
533 pr_debug("Can't make temp file"); 533 pr_debug("Can't make temp file");
534 free(tdata);
534 return NULL; 535 return NULL;
535 } 536 }
536 537
537 temp_fd = open(tdata->temp_file, O_RDWR); 538 temp_fd = open(tdata->temp_file, O_RDWR);
538 if (temp_fd < 0) { 539 if (temp_fd < 0) {
539 pr_debug("Can't read '%s'", tdata->temp_file); 540 pr_debug("Can't read '%s'", tdata->temp_file);
541 free(tdata);
540 return NULL; 542 return NULL;
541 } 543 }
542 544
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index e76214f8d596..32e558a65af3 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -33,14 +33,15 @@ static int get_common_field(struct scripting_context *context,
33 int *offset, int *size, const char *type) 33 int *offset, int *size, const char *type)
34{ 34{
35 struct tep_handle *pevent = context->pevent; 35 struct tep_handle *pevent = context->pevent;
36 struct event_format *event; 36 struct tep_event_format *event;
37 struct format_field *field; 37 struct tep_format_field *field;
38 38
39 if (!*size) { 39 if (!*size) {
40 if (!pevent->events) 40
41 event = tep_get_first_event(pevent);
42 if (!event)
41 return 0; 43 return 0;
42 44
43 event = pevent->events[0];
44 field = tep_find_common_field(event, type); 45 field = tep_find_common_field(event, type);
45 if (!field) 46 if (!field)
46 return 0; 47 return 0;
@@ -94,9 +95,9 @@ int common_pc(struct scripting_context *context)
94} 95}
95 96
96unsigned long long 97unsigned long long
97raw_field_value(struct event_format *event, const char *name, void *data) 98raw_field_value(struct tep_event_format *event, const char *name, void *data)
98{ 99{
99 struct format_field *field; 100 struct tep_format_field *field;
100 unsigned long long val; 101 unsigned long long val;
101 102
102 field = tep_find_any_field(event, name); 103 field = tep_find_any_field(event, name);
@@ -108,12 +109,12 @@ raw_field_value(struct event_format *event, const char *name, void *data)
108 return val; 109 return val;
109} 110}
110 111
111unsigned long long read_size(struct event_format *event, void *ptr, int size) 112unsigned long long read_size(struct tep_event_format *event, void *ptr, int size)
112{ 113{
113 return tep_read_number(event->pevent, ptr, size); 114 return tep_read_number(event->pevent, ptr, size);
114} 115}
115 116
116void event_format__fprintf(struct event_format *event, 117void event_format__fprintf(struct tep_event_format *event,
117 int cpu, void *data, int size, FILE *fp) 118 int cpu, void *data, int size, FILE *fp)
118{ 119{
119 struct tep_record record; 120 struct tep_record record;
@@ -130,7 +131,7 @@ void event_format__fprintf(struct event_format *event,
130 trace_seq_destroy(&s); 131 trace_seq_destroy(&s);
131} 132}
132 133
133void event_format__print(struct event_format *event, 134void event_format__print(struct tep_event_format *event,
134 int cpu, void *data, int size) 135 int cpu, void *data, int size)
135{ 136{
136 return event_format__fprintf(event, cpu, data, size, stdout); 137 return event_format__fprintf(event, cpu, data, size, stdout);
@@ -158,6 +159,7 @@ void parse_ftrace_printk(struct tep_handle *pevent,
158 printk = strdup(fmt+1); 159 printk = strdup(fmt+1);
159 line = strtok_r(NULL, "\n", &next); 160 line = strtok_r(NULL, "\n", &next);
160 tep_register_print_string(pevent, printk, addr); 161 tep_register_print_string(pevent, printk, addr);
162 free(printk);
161 } 163 }
162} 164}
163 165
@@ -188,29 +190,33 @@ int parse_event_file(struct tep_handle *pevent,
188 return tep_parse_event(pevent, buf, size, sys); 190 return tep_parse_event(pevent, buf, size, sys);
189} 191}
190 192
191struct event_format *trace_find_next_event(struct tep_handle *pevent, 193struct tep_event_format *trace_find_next_event(struct tep_handle *pevent,
192 struct event_format *event) 194 struct tep_event_format *event)
193{ 195{
194 static int idx; 196 static int idx;
197 int events_count;
198 struct tep_event_format *all_events;
195 199
196 if (!pevent || !pevent->events) 200 all_events = tep_get_first_event(pevent);
201 events_count = tep_get_events_count(pevent);
202 if (!pevent || !all_events || events_count < 1)
197 return NULL; 203 return NULL;
198 204
199 if (!event) { 205 if (!event) {
200 idx = 0; 206 idx = 0;
201 return pevent->events[0]; 207 return all_events;
202 } 208 }
203 209
204 if (idx < pevent->nr_events && event == pevent->events[idx]) { 210 if (idx < events_count && event == (all_events + idx)) {
205 idx++; 211 idx++;
206 if (idx == pevent->nr_events) 212 if (idx == events_count)
207 return NULL; 213 return NULL;
208 return pevent->events[idx]; 214 return (all_events + idx);
209 } 215 }
210 216
211 for (idx = 1; idx < pevent->nr_events; idx++) { 217 for (idx = 1; idx < events_count; idx++) {
212 if (event == pevent->events[idx - 1]) 218 if (event == (all_events + (idx - 1)))
213 return pevent->events[idx]; 219 return (all_events + idx);
214 } 220 }
215 return NULL; 221 return NULL;
216} 222}
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 3dfc1db6b25b..76f12c705ef9 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -102,7 +102,7 @@ static unsigned int read4(struct tep_handle *pevent)
102 102
103 if (do_read(&data, 4) < 0) 103 if (do_read(&data, 4) < 0)
104 return 0; 104 return 0;
105 return __data2host4(pevent, data); 105 return __tep_data2host4(pevent, data);
106} 106}
107 107
108static unsigned long long read8(struct tep_handle *pevent) 108static unsigned long long read8(struct tep_handle *pevent)
@@ -111,7 +111,7 @@ static unsigned long long read8(struct tep_handle *pevent)
111 111
112 if (do_read(&data, 8) < 0) 112 if (do_read(&data, 8) < 0)
113 return 0; 113 return 0;
114 return __data2host8(pevent, data); 114 return __tep_data2host8(pevent, data);
115} 115}
116 116
117static char *read_string(void) 117static char *read_string(void)
@@ -241,7 +241,7 @@ static int read_header_files(struct tep_handle *pevent)
241 * The commit field in the page is of type long, 241 * The commit field in the page is of type long,
242 * use that instead, since it represents the kernel. 242 * use that instead, since it represents the kernel.
243 */ 243 */
244 tep_set_long_size(pevent, pevent->header_page_size_size); 244 tep_set_long_size(pevent, tep_get_header_page_size(pevent));
245 } 245 }
246 free(header_page); 246 free(header_page);
247 247
@@ -297,10 +297,8 @@ static int read_event_file(struct tep_handle *pevent, char *sys,
297 } 297 }
298 298
299 ret = do_read(buf, size); 299 ret = do_read(buf, size);
300 if (ret < 0) { 300 if (ret < 0)
301 free(buf);
302 goto out; 301 goto out;
303 }
304 302
305 ret = parse_event_file(pevent, buf, size, sys); 303 ret = parse_event_file(pevent, buf, size, sys);
306 if (ret < 0) 304 if (ret < 0)
@@ -349,9 +347,12 @@ static int read_event_files(struct tep_handle *pevent)
349 for (x=0; x < count; x++) { 347 for (x=0; x < count; x++) {
350 size = read8(pevent); 348 size = read8(pevent);
351 ret = read_event_file(pevent, sys, size); 349 ret = read_event_file(pevent, sys, size);
352 if (ret) 350 if (ret) {
351 free(sys);
353 return ret; 352 return ret;
353 }
354 } 354 }
355 free(sys);
355 } 356 }
356 return 0; 357 return 0;
357} 358}
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 58bb72f266f3..95664b2f771e 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -72,12 +72,12 @@ void trace_event__cleanup(struct trace_event *t)
72/* 72/*
73 * Returns pointer with encoded error via <linux/err.h> interface. 73 * Returns pointer with encoded error via <linux/err.h> interface.
74 */ 74 */
75static struct event_format* 75static struct tep_event_format*
76tp_format(const char *sys, const char *name) 76tp_format(const char *sys, const char *name)
77{ 77{
78 char *tp_dir = get_events_file(sys); 78 char *tp_dir = get_events_file(sys);
79 struct tep_handle *pevent = tevent.pevent; 79 struct tep_handle *pevent = tevent.pevent;
80 struct event_format *event = NULL; 80 struct tep_event_format *event = NULL;
81 char path[PATH_MAX]; 81 char path[PATH_MAX];
82 size_t size; 82 size_t size;
83 char *data; 83 char *data;
@@ -102,7 +102,7 @@ tp_format(const char *sys, const char *name)
102/* 102/*
103 * Returns pointer with encoded error via <linux/err.h> interface. 103 * Returns pointer with encoded error via <linux/err.h> interface.
104 */ 104 */
105struct event_format* 105struct tep_event_format*
106trace_event__tp_format(const char *sys, const char *name) 106trace_event__tp_format(const char *sys, const char *name)
107{ 107{
108 if (!tevent_initialized && trace_event__init2()) 108 if (!tevent_initialized && trace_event__init2())
@@ -111,7 +111,7 @@ trace_event__tp_format(const char *sys, const char *name)
111 return tp_format(sys, name); 111 return tp_format(sys, name);
112} 112}
113 113
114struct event_format *trace_event__tp_format_id(int id) 114struct tep_event_format *trace_event__tp_format_id(int id)
115{ 115{
116 if (!tevent_initialized && trace_event__init2()) 116 if (!tevent_initialized && trace_event__init2())
117 return ERR_PTR(-ENOMEM); 117 return ERR_PTR(-ENOMEM);
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 40204ec3a7a2..f024d73bfc40 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,6 +3,7 @@
3#define _PERF_UTIL_TRACE_EVENT_H 3#define _PERF_UTIL_TRACE_EVENT_H
4 4
5#include <traceevent/event-parse.h> 5#include <traceevent/event-parse.h>
6#include <traceevent/trace-seq.h>
6#include "parse-events.h" 7#include "parse-events.h"
7 8
8struct machine; 9struct machine;
@@ -10,28 +11,28 @@ struct perf_sample;
10union perf_event; 11union perf_event;
11struct perf_tool; 12struct perf_tool;
12struct thread; 13struct thread;
13struct plugin_list; 14struct tep_plugin_list;
14 15
15struct trace_event { 16struct trace_event {
16 struct tep_handle *pevent; 17 struct tep_handle *pevent;
17 struct plugin_list *plugin_list; 18 struct tep_plugin_list *plugin_list;
18}; 19};
19 20
20int trace_event__init(struct trace_event *t); 21int trace_event__init(struct trace_event *t);
21void trace_event__cleanup(struct trace_event *t); 22void trace_event__cleanup(struct trace_event *t);
22int trace_event__register_resolver(struct machine *machine, 23int trace_event__register_resolver(struct machine *machine,
23 tep_func_resolver_t *func); 24 tep_func_resolver_t *func);
24struct event_format* 25struct tep_event_format*
25trace_event__tp_format(const char *sys, const char *name); 26trace_event__tp_format(const char *sys, const char *name);
26 27
27struct event_format *trace_event__tp_format_id(int id); 28struct tep_event_format *trace_event__tp_format_id(int id);
28 29
29int bigendian(void); 30int bigendian(void);
30 31
31void event_format__fprintf(struct event_format *event, 32void event_format__fprintf(struct tep_event_format *event,
32 int cpu, void *data, int size, FILE *fp); 33 int cpu, void *data, int size, FILE *fp);
33 34
34void event_format__print(struct event_format *event, 35void event_format__print(struct tep_event_format *event,
35 int cpu, void *data, int size); 36 int cpu, void *data, int size);
36 37
37int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size); 38int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size);
@@ -39,7 +40,7 @@ int parse_event_file(struct tep_handle *pevent,
39 char *buf, unsigned long size, char *sys); 40 char *buf, unsigned long size, char *sys);
40 41
41unsigned long long 42unsigned long long
42raw_field_value(struct event_format *event, const char *name, void *data); 43raw_field_value(struct tep_event_format *event, const char *name, void *data);
43 44
44void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size); 45void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size);
45void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size); 46void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size);
@@ -47,9 +48,9 @@ void parse_saved_cmdline(struct tep_handle *pevent, char *file, unsigned int siz
47 48
48ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); 49ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
49 50
50struct event_format *trace_find_next_event(struct tep_handle *pevent, 51struct tep_event_format *trace_find_next_event(struct tep_handle *pevent,
51 struct event_format *event); 52 struct tep_event_format *event);
52unsigned long long read_size(struct event_format *event, void *ptr, int size); 53unsigned long long read_size(struct tep_event_format *event, void *ptr, int size);
53unsigned long long eval_flag(const char *flag); 54unsigned long long eval_flag(const char *flag);
54 55
55int read_tracing_data(int fd, struct list_head *pattrs); 56int read_tracing_data(int fd, struct list_head *pattrs);
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 6f318b15950e..5eff9bfc5758 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -45,13 +45,13 @@ static int __report_module(struct addr_location *al, u64 ip,
45 Dwarf_Addr s; 45 Dwarf_Addr s;
46 46
47 dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL); 47 dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL);
48 if (s != al->map->start) 48 if (s != al->map->start - al->map->pgoff)
49 mod = 0; 49 mod = 0;
50 } 50 }
51 51
52 if (!mod) 52 if (!mod)
53 mod = dwfl_report_elf(ui->dwfl, dso->short_name, 53 mod = dwfl_report_elf(ui->dwfl, dso->short_name,
54 (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start, 54 (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start - al->map->pgoff,
55 false); 55 false);
56 56
57 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; 57 return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index eac5b858a371..093352e93d50 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -221,7 +221,7 @@ out:
221 return err; 221 return err;
222} 222}
223 223
224static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size) 224int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size)
225{ 225{
226 void *ptr; 226 void *ptr;
227 loff_t pgoff; 227 loff_t pgoff;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index dc58254a2b69..14508ee7707a 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -6,6 +6,7 @@
6/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */ 6/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
7#define _DEFAULT_SOURCE 1 7#define _DEFAULT_SOURCE 1
8 8
9#include <fcntl.h>
9#include <stdbool.h> 10#include <stdbool.h>
10#include <stddef.h> 11#include <stddef.h>
11#include <stdlib.h> 12#include <stdlib.h>
@@ -35,6 +36,7 @@ bool lsdir_no_dot_filter(const char *name, struct dirent *d);
35int copyfile(const char *from, const char *to); 36int copyfile(const char *from, const char *to);
36int copyfile_mode(const char *from, const char *to, mode_t mode); 37int copyfile_mode(const char *from, const char *to, mode_t mode);
37int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi); 38int copyfile_ns(const char *from, const char *to, struct nsinfo *nsi);
39int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size);
38 40
39ssize_t readn(int fd, void *buf, size_t n); 41ssize_t readn(int fd, void *buf, size_t n);
40ssize_t writen(int fd, const void *buf, size_t n); 42ssize_t writen(int fd, const void *buf, size_t n);